diff --git a/.changeset/data-slot-catalog-typeset.md b/.changeset/data-slot-catalog-typeset.md
new file mode 100644
index 000000000..498f91cd8
--- /dev/null
+++ b/.changeset/data-slot-catalog-typeset.md
@@ -0,0 +1,11 @@
+---
+"fulldev-ui": minor
+---
+
+Complete Data Slot component coverage with Drawer, Toast, Toggle Group and Resizable, and upgrade all Data Slot packages to 1.0.2. Add Attachment, Button Group, Pagination and Aspect Ratio as Astro components without their own client scripts.
+
+Replace the Embla Carousel with Data Slot's native scrolling carousel. This is a breaking change: replace `opts` with `defaultIndex`, `orientation`, `drag` and `loop`; use `CarouselController` and `CarouselOptions` instead of Embla types; replace `carousel:init` and `carousel:select` with `carousel:change` and `carousel:set`. Carousel now displays one full-width slide at a time. Remove fractional slide widths and the old content/item spacing pattern. Examples and the reviews block use the new API.
+
+Adopt shadcn Typeset for rendered prose while preserving the existing Typography component exports. Typography sizes now control the prose rhythm, with updated heading spacing, nested content styling and semantic tables. Keep docs-specific code controls out of installable Typography styles.
+
+Improve Combobox trigger and clear focus styling, align Select popper placement and Slider thumb positioning with shadcn, and use a consistent 8px default Navigation Menu gap.
diff --git a/astro.config.ts b/astro.config.ts
index 9a58f5551..f2c12801b 100644
--- a/astro.config.ts
+++ b/astro.config.ts
@@ -57,6 +57,6 @@ export default defineConfig({
liveCode({
layout: "/src/components/live-code.astro",
}),
- mdx(),
+ mdx({ gfm: true }),
],
})
diff --git a/package.json b/package.json
index 678a69a6c..d9870a134 100644
--- a/package.json
+++ b/package.json
@@ -73,24 +73,29 @@
"dependencies": {
"@astrojs/mdx": "^5.0.6",
"@astrojs/sitemap": "^3.7.3",
- "@data-slot/accordion": "^1.0.1",
- "@data-slot/alert-dialog": "^1.0.1",
- "@data-slot/collapsible": "^1.0.1",
- "@data-slot/combobox": "^1.0.1",
- "@data-slot/command": "^1.0.1",
- "@data-slot/core": "^1.0.1",
- "@data-slot/dialog": "^1.0.1",
- "@data-slot/dropdown-menu": "^1.0.1",
- "@data-slot/hover-card": "^1.0.1",
- "@data-slot/navigation-menu": "^1.0.1",
- "@data-slot/popover": "^1.0.1",
- "@data-slot/radio-group": "^1.0.1",
- "@data-slot/select": "^1.0.1",
- "@data-slot/slider": "^1.0.1",
- "@data-slot/switch": "^1.0.1",
- "@data-slot/tabs": "^1.0.1",
- "@data-slot/toggle": "^1.0.1",
- "@data-slot/tooltip": "^1.0.1",
+ "@data-slot/accordion": "^1.0.2",
+ "@data-slot/alert-dialog": "^1.0.2",
+ "@data-slot/carousel": "^1.0.2",
+ "@data-slot/collapsible": "^1.0.2",
+ "@data-slot/combobox": "^1.0.2",
+ "@data-slot/command": "^1.0.2",
+ "@data-slot/core": "^1.0.2",
+ "@data-slot/dialog": "^1.0.2",
+ "@data-slot/drawer": "^1.0.2",
+ "@data-slot/dropdown-menu": "^1.0.2",
+ "@data-slot/hover-card": "^1.0.2",
+ "@data-slot/navigation-menu": "^1.0.2",
+ "@data-slot/popover": "^1.0.2",
+ "@data-slot/radio-group": "^1.0.2",
+ "@data-slot/resizable": "^1.0.2",
+ "@data-slot/select": "^1.0.2",
+ "@data-slot/slider": "^1.0.2",
+ "@data-slot/switch": "^1.0.2",
+ "@data-slot/tabs": "^1.0.2",
+ "@data-slot/toast": "^1.0.2",
+ "@data-slot/toggle": "^1.0.2",
+ "@data-slot/toggle-group": "^1.0.2",
+ "@data-slot/tooltip": "^1.0.2",
"@fontsource-variable/geist": "^5.2.9",
"@fontsource-variable/geist-mono": "^5.2.8",
"@lexingtonthemes/seo": "^0.2.0",
@@ -102,7 +107,6 @@
"astro-robots-txt": "^1.0.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
- "embla-carousel": "^8.6.0",
"lucide-static": "^1.22.0",
"shadcn": "^4.12.0",
"simple-icons": "^16.24.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ac67d3077..7f988a8e8 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -15,59 +15,74 @@ importers:
specifier: ^3.7.3
version: 3.7.3
'@data-slot/accordion':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/alert-dialog':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
+ '@data-slot/carousel':
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/collapsible':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/combobox':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/command':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/core':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/dialog':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
+ '@data-slot/drawer':
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/dropdown-menu':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/hover-card':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/navigation-menu':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/popover':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/radio-group':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
+ '@data-slot/resizable':
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/select':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/slider':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/switch':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/tabs':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
+ '@data-slot/toast':
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/toggle':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
+ '@data-slot/toggle-group':
+ specifier: ^1.0.2
+ version: 1.0.2
'@data-slot/tooltip':
- specifier: ^1.0.1
- version: 1.0.1
+ specifier: ^1.0.2
+ version: 1.0.2
'@fontsource-variable/geist':
specifier: ^5.2.9
version: 5.3.0
@@ -101,9 +116,6 @@ importers:
clsx:
specifier: ^2.1.1
version: 2.1.1
- embla-carousel:
- specifier: ^8.6.0
- version: 8.6.0
lucide-static:
specifier: ^1.22.0
version: 1.34.0
@@ -444,59 +456,74 @@ packages:
resolution: {integrity: sha512-GgcWwRCs/xPtaqlMy8qRhPnZf9vlWcWZNHAitnVQ3yk7JmSralSiq5q07yaffYE8SogtDm7zFeKccx1QNVARpw==}
engines: {node: '>= 20.12.0'}
- '@data-slot/accordion@1.0.1':
- resolution: {integrity: sha512-gmg671YTOia+c3zM42FAikylWLpDd84UN0/fg2JvTD821bspm8t7Du+ILX2aJlWoGZEkxk6At/aqOpMEsQMajA==}
+ '@data-slot/accordion@1.0.2':
+ resolution: {integrity: sha512-SOs0DBMdU5l8amuRu1MAEGXORmTFhK3wMLrbl12Rj3hdzIQ6DYsoPvRvVUEs2FZ1RB+gT0PB/JWB1vvzAvBiKA==}
- '@data-slot/alert-dialog@1.0.1':
- resolution: {integrity: sha512-+3oTGvS9gVb35XcAJZRf6yAM5P7Pb/3r9TS4t++DkX0KLSnKjJ21WG8aUS1A42qNDc+twUlqcc3CLGDxtKIl2w==}
+ '@data-slot/alert-dialog@1.0.2':
+ resolution: {integrity: sha512-muBiDNPYF3EXvNTC0nMK3qff95vaPdndGARaHsYFKx0tUI++6wkncIOPD0/PbSFng4wpIssVf4Ila7+VeXCxzg==}
- '@data-slot/collapsible@1.0.1':
- resolution: {integrity: sha512-y0ugQ7+nvB9qWYcwP4fNRew+W0MJYMa+dgqbPZLB9Ga3eGu0KLC7wfA5iGxg592rGN2xjohl5ixGNuhaWvObng==}
+ '@data-slot/carousel@1.0.2':
+ resolution: {integrity: sha512-6ElknTlUM8rKp0sk5TN7gamQgXtmQo/9DIpAChOUXsmwa9Rp27sNO2N9OxMV+FSa3qfL7mImt7idJbYNZHe82g==}
- '@data-slot/combobox@1.0.1':
- resolution: {integrity: sha512-GefwzKOn849DA32laG4QttII1rVdJ+I1sqTi4vAeyHhaK4DnJfJq85T563DCIR1TGTEefSsFZTzxjFlniwZgbg==}
+ '@data-slot/collapsible@1.0.2':
+ resolution: {integrity: sha512-aqBQpbbZBfA+1dQJ5MMMpd17pTCdiphqG77KbAuyctVCIUcT0QCtJ8XT/aw2mOrlAzFPuuTYuvQNhqauRyM+9Q==}
- '@data-slot/command@1.0.1':
- resolution: {integrity: sha512-vkgJvBr4HjSIsILOObtzuXz2A0YujzEqfRJe0dZsbDuSnMxSTVfTk5UuDNMOB3n65Q2dEthKrSYX280x0Q/u0A==}
+ '@data-slot/combobox@1.0.2':
+ resolution: {integrity: sha512-Es4k9oe0K5DyccOm/9dVGz4NVlsYo0/3TkJLRC1VplItpfU0nORF71Ze3udMbznz+pz1i7mjpRvkh+SVkOHRWg==}
- '@data-slot/core@1.0.1':
- resolution: {integrity: sha512-hR5970E+ANJoawzd2LSCxnMYl+pe0VMj1IZVWYlG1UDTS+n55QrvuITMwj35+gLOCCbABhD5IMBnIJp3aVZoJA==}
+ '@data-slot/command@1.0.2':
+ resolution: {integrity: sha512-ONZ1HNJBp/fxmiW7AGCb4Samrb0GynFMQyIv4Be2okHwMlfwFfN1VIe9+JxXv8tLWSdjB2GsOQrNQyijLt9QXQ==}
- '@data-slot/dialog@1.0.1':
- resolution: {integrity: sha512-0xtsy0p3m4082rVK8IBgJjPcav5pXYYemj7VxfTR/1OGcqXL8wu2m05HH+fKYANEPd4iHsULjX5AWbEC9l9Z7A==}
+ '@data-slot/core@1.0.2':
+ resolution: {integrity: sha512-x48OCoPuPpZviCBi9tGJXRX05mB/XPb+//2MVlQU6x3kQQVexSZONNfyv791+4WJz+nxi7oxjryiLmTLCFNVEw==}
- '@data-slot/dropdown-menu@1.0.1':
- resolution: {integrity: sha512-JpB7ZXxpaOrG9rN7Q76xkBJwpToe9b1nc7QMbJpgmDbog03pfpyTUBQFhHjqOEK+sNUkabG3JfVAnGG0xwm75g==}
+ '@data-slot/dialog@1.0.2':
+ resolution: {integrity: sha512-Xke0TXqQHYlsW1SGcY/t/bX1Gr3doTq1+fHTngNJ16QThz7xr96VzAXZkTKGJo/bTe4NmO87qpILRSq4QiZfZA==}
- '@data-slot/hover-card@1.0.1':
- resolution: {integrity: sha512-WQMXfc6RxYmc3t7R0N/Gjz3LkLeWSJqcBQuE4c+SgM4xaVXmoFxc7PEis1BE+JlmMwbLywrGubCWQo1n05yWjg==}
+ '@data-slot/drawer@1.0.2':
+ resolution: {integrity: sha512-nCje+U7gCX3OVxrNxvE0VGEOnNWKeGgaq1JSnJ9kwvA5+7K1Ag+P3IYrRFaQaFbYRU2GKE60PlrzY7TaaoEaZA==}
- '@data-slot/navigation-menu@1.0.1':
- resolution: {integrity: sha512-qSFqHpUN93dui/VPKYgFlHp7s9pNPrEoXofJVPFkZMHnaa9+HAmfoQbPHWn6xHfHplGF6AUIUccEOm3qtpUkZg==}
+ '@data-slot/dropdown-menu@1.0.2':
+ resolution: {integrity: sha512-YUQuIRoapwBPlS/2oqES9gsMxyJiRugWRHlvfdtqFKTPUJCBbndsLCO+vJ4t2KDZhWrHqxyhcDMr85WbxiSmdA==}
- '@data-slot/popover@1.0.1':
- resolution: {integrity: sha512-4/FhCz5w6MRhXVB8hquZO0W5uyrwNTDu/UdUsavzWfNVK9pmFt4Rc7xjK6KH/uMqIu8gvxAYAsVDaFaOFsflHA==}
+ '@data-slot/hover-card@1.0.2':
+ resolution: {integrity: sha512-Itf7MvxLVrmXScg+8NG3V0QY+28YPyhmhOlnRLw35d0mKwMBtxkyYFMMpBMxYRxV3WXuv0ZFyhFjzscjDFhgFg==}
- '@data-slot/radio-group@1.0.1':
- resolution: {integrity: sha512-HCAmwdjBHY69R/q6V1k6Xc88lzfUP4idXQoOUkWwwKqqlP2DXH2NEuk9/p0zSBXDKerY8qg8UI0Ldvff/ydnIA==}
+ '@data-slot/navigation-menu@1.0.2':
+ resolution: {integrity: sha512-duGcIWtwjFwurSZZsgUrrbIGgxUVext81cpOIIo2DIVuC/JhtcW5xD+AllPDqXvbyhhsv9fKcLx76WRF2koIIA==}
- '@data-slot/select@1.0.1':
- resolution: {integrity: sha512-megYWB6aa1OupAFmQeTiRLO0cKmXyvJvS6Tht6P/gc59ioduxGLdU1SjIZS1XVK6ejN2FfXKOgx4dSsqZLwzpA==}
+ '@data-slot/popover@1.0.2':
+ resolution: {integrity: sha512-eVDSmfiXHrUlwVdQ0yO0LPkbZJL0R1ygrieAC/LOzsi+ODhCgilnbT2azKlDuKJoPNMOaMOft2FkRz7HIMF4/A==}
- '@data-slot/slider@1.0.1':
- resolution: {integrity: sha512-1h41stz/cZXk2HStHgAqzH/ymaiNAg6tN51HS62WnL0m4y3MJ3OvKhXKp8hdd8PgXpg5CPxrPj5k57eVzMvF1g==}
+ '@data-slot/radio-group@1.0.2':
+ resolution: {integrity: sha512-Pp2clfsNDm2g1JdLhRs3a7c9t2k4gYtEndxBkQ6E9wwcHLs0fXiUiG3JMyenGPGdTdNkAlfq3Y9yY+z73AXycg==}
- '@data-slot/switch@1.0.1':
- resolution: {integrity: sha512-q5Y0vwuKTro/FbZAjf67CcFK+Bl7MZoA4TOyvPPtlIeRcNmblx1Bn1OQxwpwtAE5nObNCo7l3ily3OcssAk5pw==}
+ '@data-slot/resizable@1.0.2':
+ resolution: {integrity: sha512-bEqPmnuD2wNqkuqM+uaku09kw5/0wSBbvtEQb8YM785pxQEa8Rs54hK6whLpP5RZmxH8h5OdT7anRQaftmlHQw==}
- '@data-slot/tabs@1.0.1':
- resolution: {integrity: sha512-hnr1PJhVbX+yKEAbGgo+/ITAY/Ibegxqb6G5+IFTfukQ5zJOapxrlHr4M0ERlmAKy/nNQGs830DbI5JQbBTNaA==}
+ '@data-slot/select@1.0.2':
+ resolution: {integrity: sha512-JWI1G14HsdS6HoTlLqfjqyaMwkfoWKVjwjp1If96UTqFnlyee65pRvVi4h1qEJm/GlRbUR9l4bh9YPvdzUZKow==}
- '@data-slot/toggle@1.0.1':
- resolution: {integrity: sha512-ktkHGv/E3razY5+LGXyVC9hAwnNHZkXViBE3uyWEaO4leW/0ui4le7Fepg37J6PmK4hQTqhTMDKC1Gfs1ccHTQ==}
+ '@data-slot/slider@1.0.2':
+ resolution: {integrity: sha512-NBOsXVtg7l5SDJPK/LFc9WO88P642fGhdfz7edUXPu5VpcKXHkb+TRt4YGcsnNREYKm+2nWgFIzki9Bifn35oQ==}
- '@data-slot/tooltip@1.0.1':
- resolution: {integrity: sha512-Fmv/KqjnaoreUAbOMy1QsZnwGEFTh5eVFuWtOrp/a7J6NFi2oQNyzuqq3ZTx9lVJqSuSAkjPFk+FID3RDdyVUw==}
+ '@data-slot/switch@1.0.2':
+ resolution: {integrity: sha512-m6GUA8XoCWVw08W8GXqo5NGi9qi/1hMxwFcCXFYlHSQnmtvDCIX2U0tr/gFnkP7+y9I7g1Mm1KVKAX+1Rw6Gwg==}
+
+ '@data-slot/tabs@1.0.2':
+ resolution: {integrity: sha512-2Oc13RY/sMtXTKX3TuUhCJbh+q/g1GjuNOC7wGHC82X2rmJK6Xc+CXd9eIS1imzcRp7hpjJigGichstJ0vVGkw==}
+
+ '@data-slot/toast@1.0.2':
+ resolution: {integrity: sha512-WOUXTlmFC1j5EwBgo6AAjaEs09HKUOhUFo2vDXBGwgpOIRZo4hOH49B9LvGusMVp43+1rHBv2EfWWvrM21008w==}
+
+ '@data-slot/toggle-group@1.0.2':
+ resolution: {integrity: sha512-/poEuONG6GM4HkTzvYyWBvwFMR2KLeIVQfOofuFz+hAKw09CY4WkuLqiBOdKjZKmLgA5H+AoHyKVQ5LPYA/EMA==}
+
+ '@data-slot/toggle@1.0.2':
+ resolution: {integrity: sha512-iJdvqRE1ClFv8uNswUMM7u5edR1uhMkGbnfAO6t3KlB2mAwIxeuX9Y/3seml5qvq89l7CTLZwSaJHYnGHfhlLg==}
+
+ '@data-slot/tooltip@1.0.2':
+ resolution: {integrity: sha512-B++AfDWpbD8M7TRNs3Md5mF3ztgaDRHvBqBkSVOFti+9dx8xNRBUtficyixnew67Yqdxwu3DXVqEac1342WWnw==}
'@dotenvx/dotenvx@1.64.0':
resolution: {integrity: sha512-6+xRpZaWuHXEqnhBjae+VmQI9Uaqw5Uzu/ScpO+W7ww9Zp3lHSNBoNjFcUxhrCyc7pRGQzyDjhKzloqrPHERiQ==}
@@ -2114,9 +2141,6 @@ packages:
electron-to-chromium@1.5.349:
resolution: {integrity: sha512-QsWVGyRuY07Aqb234QytTfwd5d9AJlfNIQ5wIOl1L+PZDzI9d9+Fn0FRale/QYlFxt/bUnB0/nLd1jFPGxGK1A==}
- embla-carousel@8.6.0:
- resolution: {integrity: sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==}
-
emmet@2.4.11:
resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==}
@@ -3809,10 +3833,6 @@ packages:
tmp-promise@3.0.3:
resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==}
- tmp@0.2.5:
- resolution: {integrity: sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==}
- engines: {node: '>=14.14'}
-
tmp@0.2.7:
resolution: {integrity: sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==}
engines: {node: '>=14.14'}
@@ -4835,75 +4855,95 @@ snapshots:
fast-wrap-ansi: 0.2.0
sisteransi: 1.0.5
- '@data-slot/accordion@1.0.1':
+ '@data-slot/accordion@1.0.2':
+ dependencies:
+ '@data-slot/core': 1.0.2
+
+ '@data-slot/alert-dialog@1.0.2':
+ dependencies:
+ '@data-slot/core': 1.0.2
+
+ '@data-slot/carousel@1.0.2':
+ dependencies:
+ '@data-slot/core': 1.0.2
+
+ '@data-slot/collapsible@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/alert-dialog@1.0.1':
+ '@data-slot/combobox@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/collapsible@1.0.1':
+ '@data-slot/command@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/combobox@1.0.1':
+ '@data-slot/core@1.0.2': {}
+
+ '@data-slot/dialog@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/command@1.0.1':
+ '@data-slot/drawer@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/core@1.0.1': {}
+ '@data-slot/dropdown-menu@1.0.2':
+ dependencies:
+ '@data-slot/core': 1.0.2
- '@data-slot/dialog@1.0.1':
+ '@data-slot/hover-card@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/dropdown-menu@1.0.1':
+ '@data-slot/navigation-menu@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/hover-card@1.0.1':
+ '@data-slot/popover@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/navigation-menu@1.0.1':
+ '@data-slot/radio-group@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/popover@1.0.1':
+ '@data-slot/resizable@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/radio-group@1.0.1':
+ '@data-slot/select@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/select@1.0.1':
+ '@data-slot/slider@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/slider@1.0.1':
+ '@data-slot/switch@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/switch@1.0.1':
+ '@data-slot/tabs@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/tabs@1.0.1':
+ '@data-slot/toast@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/toggle@1.0.1':
+ '@data-slot/toggle-group@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
- '@data-slot/tooltip@1.0.1':
+ '@data-slot/toggle@1.0.2':
dependencies:
- '@data-slot/core': 1.0.1
+ '@data-slot/core': 1.0.2
+
+ '@data-slot/tooltip@1.0.2':
+ dependencies:
+ '@data-slot/core': 1.0.2
'@dotenvx/dotenvx@1.64.0':
dependencies:
@@ -6440,8 +6480,6 @@ snapshots:
electron-to-chromium@1.5.349: {}
- embla-carousel@8.6.0: {}
-
emmet@2.4.11:
dependencies:
'@emmetio/abbreviation': 2.3.3
@@ -8602,10 +8640,7 @@ snapshots:
tmp-promise@3.0.3:
dependencies:
- tmp: 0.2.5
- optional: true
-
- tmp@0.2.5:
+ tmp: 0.2.7
optional: true
tmp@0.2.7: {}
diff --git a/public/r/accordion.json b/public/r/accordion.json
index 1304ffd9c..ac4f81d3a 100644
--- a/public/r/accordion.json
+++ b/public/r/accordion.json
@@ -4,7 +4,7 @@
"title": "Accordion",
"description": "A vertically stacked set of interactive headings that each reveal a section of content.",
"dependencies": [
- "@data-slot/accordion@^1.0.1",
+ "@data-slot/accordion@^1.0.2",
"@lucide/astro"
],
"files": [
diff --git a/public/r/alert-dialog.json b/public/r/alert-dialog.json
index e0fa792c0..3d5694549 100644
--- a/public/r/alert-dialog.json
+++ b/public/r/alert-dialog.json
@@ -4,7 +4,7 @@
"title": "Alert Dialog",
"description": "A modal dialog for important confirmations that expects a response.",
"dependencies": [
- "@data-slot/alert-dialog@^1.0.1"
+ "@data-slot/alert-dialog@^1.0.2"
],
"registryDependencies": [
"@fulldev/button"
diff --git a/public/r/aspect-ratio.json b/public/r/aspect-ratio.json
new file mode 100644
index 000000000..bfdeee85b
--- /dev/null
+++ b/public/r/aspect-ratio.json
@@ -0,0 +1,23 @@
+{
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
+ "name": "aspect-ratio",
+ "title": "Aspect Ratio",
+ "description": "Displays content within a desired ratio.",
+ "files": [
+ {
+ "path": "src/components/ui/aspect-ratio/aspect-ratio.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n ratio: number\n}\n\nconst { class: className, ratio, style, ...props } = Astro.props\n\nconst resolvedStyle =\n typeof style === \"string\"\n ? `--ratio: ${ratio}; ${style}`\n : { \"--ratio\": ratio, ...(style ?? {}) }\n---\n\n
\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/aspect-ratio/index.ts",
+ "content": "export { default as AspectRatio } from \"./aspect-ratio.astro\"\n",
+ "type": "registry:ui"
+ }
+ ],
+ "docs": "https://ui.full.dev/components/aspect-ratio/",
+ "categories": [
+ "ui"
+ ],
+ "type": "registry:ui"
+}
\ No newline at end of file
diff --git a/public/r/attachment.json b/public/r/attachment.json
new file mode 100644
index 000000000..bfbfdb1a5
--- /dev/null
+++ b/public/r/attachment.json
@@ -0,0 +1,66 @@
+{
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
+ "name": "attachment",
+ "title": "Attachment",
+ "description": "Displays a file or image attachment with media, metadata, state, and actions.",
+ "registryDependencies": [
+ "@fulldev/button"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/attachment/attachment-action.astro",
+ "content": "---\nimport type { HTMLTag, Polymorphic } from \"astro/types\"\n\nimport { Button, type ButtonVariantProps } from \"@/components/ui/button\"\n\ntype Props = Polymorphic<{ as: Tag }> &\n ButtonVariantProps\n\nconst { as, variant = \"ghost\", size = \"icon-xs\", ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-actions.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-content.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-description.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"span\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-group.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-media.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst attachmentMediaVariants = cva(\n \"bg-muted text-foreground group-data-[state=error]/attachment:bg-destructive/10 group-data-[state=error]/attachment:text-destructive relative flex aspect-square w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg group-data-[orientation=vertical]/attachment:w-full group-data-[size=sm]/attachment:w-8 group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-md group-data-[orientation=vertical]/attachment:*:data-[slot=spinner]:size-6! [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 group-data-[orientation=vertical]/attachment:[&_svg:not([class*='size-'])]:size-6 group-data-[size=xs]/attachment:[&_svg:not([class*='size-'])]:size-3.5\",\n {\n variants: {\n variant: {\n icon: \"\",\n image:\n \"opacity-60 group-data-[state=done]/attachment:opacity-100 group-data-[state=idle]/attachment:opacity-100 *:[img]:aspect-square *:[img]:w-full *:[img]:object-cover\",\n },\n },\n defaultVariants: {\n variant: \"icon\",\n },\n }\n)\n\ntype Props = HTMLAttributes<\"div\"> &\n VariantProps\n\nconst { class: className, variant = \"icon\", ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-title.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"span\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-trigger.astro",
+ "content": "---\nimport type { HTMLTag, Polymorphic } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = Polymorphic<{ as: Tag }>\n\nconst {\n as: Tag = \"href\" in Astro.props ? \"a\" : \"button\",\n class: className,\n ...props\n} = Astro.props\n\nconst attributes: Record = { ...props }\nif (Tag === \"button\") attributes.type ??= \"button\"\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst attachmentVariants = cva(\n \"group/attachment bg-card text-card-foreground focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border transition-colors focus-within:ring-1 data-[state=idle]:border-dashed\",\n {\n variants: {\n size: {\n default:\n \"gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2\",\n sm: \"gap-2.5 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5\",\n xs: \"gap-1.5 rounded-lg text-xs has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1\",\n },\n orientation: {\n horizontal: \"min-w-40 items-center\",\n vertical: \"w-24 flex-col has-data-[slot=attachment-content]:w-30\",\n },\n },\n defaultVariants: {\n size: \"default\",\n orientation: \"horizontal\",\n },\n }\n)\n\ntype Props = HTMLAttributes<\"div\"> &\n VariantProps & {\n state?: \"idle\" | \"uploading\" | \"processing\" | \"error\" | \"done\"\n }\n\nconst {\n class: className,\n state = \"done\",\n size = \"default\",\n orientation = \"horizontal\",\n ...props\n} = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/index.ts",
+ "content": "export { default as Attachment } from \"./attachment.astro\"\nexport { default as AttachmentAction } from \"./attachment-action.astro\"\nexport { default as AttachmentActions } from \"./attachment-actions.astro\"\nexport { default as AttachmentContent } from \"./attachment-content.astro\"\nexport { default as AttachmentDescription } from \"./attachment-description.astro\"\nexport { default as AttachmentGroup } from \"./attachment-group.astro\"\nexport { default as AttachmentMedia } from \"./attachment-media.astro\"\nexport { default as AttachmentTitle } from \"./attachment-title.astro\"\nexport { default as AttachmentTrigger } from \"./attachment-trigger.astro\"\n",
+ "type": "registry:ui"
+ }
+ ],
+ "docs": "https://ui.full.dev/components/attachment/",
+ "categories": [
+ "ui"
+ ],
+ "type": "registry:ui"
+}
\ No newline at end of file
diff --git a/public/r/button-group.json b/public/r/button-group.json
new file mode 100644
index 000000000..706a31d1c
--- /dev/null
+++ b/public/r/button-group.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
+ "name": "button-group",
+ "title": "Button Group",
+ "description": "Groups related controls with connected edges and consistent focus behavior.",
+ "registryDependencies": [
+ "@fulldev/separator"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/button-group/button-group-separator.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Separator } from \"@/components/ui/separator\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n orientation?: \"horizontal\" | \"vertical\"\n decorative?: boolean\n}\n\nconst {\n class: className,\n orientation = \"vertical\",\n decorative = true,\n ...props\n} = Astro.props\n---\n\n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/button-group-text.astro",
+ "content": "---\nimport type { HTMLTag, Polymorphic } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = Polymorphic<{ as: Tag }>\n\nconst { as: Tag = \"div\", class: className, ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/button-group-variants.ts",
+ "content": "import { cva, type VariantProps } from \"class-variance-authority\"\n\nexport const buttonGroupVariants = cva(\n \"flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1\",\n {\n variants: {\n orientation: {\n horizontal:\n \"*:data-slot:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-md! [&>[data-slot]~[data-slot]]:rounded-l-none [&>[data-slot]~[data-slot]]:border-l-0\",\n vertical:\n \"flex-col *:data-slot:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-md! [&>[data-slot]~[data-slot]]:rounded-t-none [&>[data-slot]~[data-slot]]:border-t-0\",\n },\n },\n defaultVariants: {\n orientation: \"horizontal\",\n },\n }\n)\n\nexport type ButtonGroupVariantProps = VariantProps\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/button-group.astro",
+ "content": "---\nimport type { HTMLTag, Polymorphic } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\nimport {\n buttonGroupVariants,\n type ButtonGroupVariantProps,\n} from \"./button-group-variants\"\n\ntype Props = Polymorphic<{ as: Tag }> &\n ButtonGroupVariantProps\n\nconst {\n as: Tag = \"div\",\n class: className,\n orientation = \"horizontal\",\n ...props\n} = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/index.ts",
+ "content": "export { default as ButtonGroup } from \"./button-group.astro\"\nexport { default as ButtonGroupSeparator } from \"./button-group-separator.astro\"\nexport { default as ButtonGroupText } from \"./button-group-text.astro\"\nexport {\n buttonGroupVariants,\n type ButtonGroupVariantProps,\n} from \"./button-group-variants\"\n",
+ "type": "registry:ui"
+ }
+ ],
+ "docs": "https://ui.full.dev/components/button-group/",
+ "categories": [
+ "ui"
+ ],
+ "type": "registry:ui"
+}
\ No newline at end of file
diff --git a/public/r/carousel.json b/public/r/carousel.json
index ae6989572..8586df5fd 100644
--- a/public/r/carousel.json
+++ b/public/r/carousel.json
@@ -2,9 +2,9 @@
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "carousel",
"title": "Carousel",
- "description": "A carousel with motion and swipe built using Embla.",
+ "description": "An accessible carousel built on native scrolling with Data Slot.",
"dependencies": [
- "embla-carousel",
+ "@data-slot/carousel@^1.0.2",
"@lucide/astro"
],
"registryDependencies": [
@@ -13,32 +13,32 @@
"files": [
{
"path": "src/components/ui/carousel/carousel.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport type { EmblaOptionsType } from \"embla-carousel\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n opts?: EmblaOptionsType\n orientation?: \"horizontal\" | \"vertical\"\n}\n\nconst {\n class: className,\n opts,\n orientation = \"horizontal\",\n ...props\n} = Astro.props\n\nconst resolvedOpts: EmblaOptionsType = {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n}\n---\n\n\n \n
\n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n defaultIndex?: number\n orientation?: \"horizontal\" | \"vertical\"\n drag?: boolean\n loop?: boolean\n}\n\nconst {\n class: className,\n defaultIndex,\n orientation = \"horizontal\",\n drag,\n loop,\n ...props\n} = Astro.props\n---\n\n\n \n
\n\n\n",
"type": "registry:ui"
},
{
"path": "src/components/ui/carousel/carousel-content.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
"type": "registry:ui"
},
{
"path": "src/components/ui/carousel/carousel-item.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
"type": "registry:ui"
},
{
"path": "src/components/ui/carousel/carousel-next.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport ChevronRightIcon from \"@lucide/astro/icons/chevron-right\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants, type ButtonVariantProps } from \"@/components/ui/button\"\n\ntype Props = Omit, \"type\"> & ButtonVariantProps\n\nconst {\n class: className,\n variant = \"outline\",\n size = \"icon-sm\",\n disabled,\n ...props\n} = Astro.props\n---\n\n\n \n \n Next slide \n \n \n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport ChevronRightIcon from \"@lucide/astro/icons/chevron-right\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants, type ButtonVariantProps } from \"@/components/ui/button\"\n\ntype Props = Omit, \"type\"> & ButtonVariantProps\n\nconst {\n class: className,\n variant = \"outline\",\n size = \"icon-sm\",\n ...props\n} = Astro.props\n---\n\n\n \n \n Next slide \n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/carousel/carousel-previous.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport ChevronLeftIcon from \"@lucide/astro/icons/chevron-left\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants, type ButtonVariantProps } from \"@/components/ui/button\"\n\ntype Props = Omit, \"type\"> & ButtonVariantProps\n\nconst {\n class: className,\n variant = \"outline\",\n size = \"icon-sm\",\n disabled,\n ...props\n} = Astro.props\n---\n\n\n \n \n Previous slide \n \n \n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport ChevronLeftIcon from \"@lucide/astro/icons/chevron-left\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants, type ButtonVariantProps } from \"@/components/ui/button\"\n\ntype Props = Omit, \"type\"> & ButtonVariantProps\n\nconst {\n class: className,\n variant = \"outline\",\n size = \"icon-sm\",\n ...props\n} = Astro.props\n---\n\n\n \n \n Previous slide \n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/carousel/index.ts",
- "content": "export type {\n EmblaCarouselType as CarouselApi,\n EmblaOptionsType as CarouselOptions,\n EmblaPluginType as CarouselPlugin,\n} from \"embla-carousel\"\n\nexport { default as Carousel } from \"./carousel.astro\"\nexport { default as CarouselContent } from \"./carousel-content.astro\"\nexport { default as CarouselItem } from \"./carousel-item.astro\"\nexport { default as CarouselPrevious } from \"./carousel-previous.astro\"\nexport { default as CarouselNext } from \"./carousel-next.astro\"\n",
+ "content": "export type { CarouselController, CarouselOptions } from \"@data-slot/carousel\"\n\nexport { default as Carousel } from \"./carousel.astro\"\nexport { default as CarouselContent } from \"./carousel-content.astro\"\nexport { default as CarouselItem } from \"./carousel-item.astro\"\nexport { default as CarouselPrevious } from \"./carousel-previous.astro\"\nexport { default as CarouselNext } from \"./carousel-next.astro\"\n",
"type": "registry:ui"
}
],
diff --git a/public/r/collapsible.json b/public/r/collapsible.json
index e1cc26faf..2377a7429 100644
--- a/public/r/collapsible.json
+++ b/public/r/collapsible.json
@@ -4,7 +4,7 @@
"title": "Collapsible",
"description": "An interactive component which expands/collapses a panel.",
"dependencies": [
- "@data-slot/collapsible@^1.0.1"
+ "@data-slot/collapsible@^1.0.2"
],
"files": [
{
diff --git a/public/r/combobox.json b/public/r/combobox.json
index 779c7f22c..f00b41e8b 100644
--- a/public/r/combobox.json
+++ b/public/r/combobox.json
@@ -4,8 +4,8 @@
"title": "Combobox",
"description": "Autocomplete input with a list of suggestions.",
"dependencies": [
- "@data-slot/combobox@^1.0.1",
- "@data-slot/core@^1.0.1",
+ "@data-slot/combobox@^1.0.2",
+ "@data-slot/core@^1.0.2",
"@lucide/astro"
],
"registryDependencies": [
@@ -34,7 +34,7 @@
},
{
"path": "src/components/ui/combobox/combobox-input.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport XIcon from \"@lucide/astro/icons/x\"\n\nimport { cn } from \"@/lib/utils\"\nimport InputGroupAddon from \"@/components/ui/input-group/input-group-addon.astro\"\nimport InputGroupInput from \"@/components/ui/input-group/input-group-input.astro\"\nimport InputGroup from \"@/components/ui/input-group/input-group.astro\"\n\nimport ComboboxTrigger from \"./combobox-trigger.astro\"\n\ntype Props = HTMLAttributes<\"input\"> & {\n showTrigger?: boolean\n showClear?: boolean\n}\n\nconst {\n class: className,\n type = \"text\",\n disabled = false,\n showTrigger = true,\n showClear = false,\n ...props\n} = Astro.props\n---\n\n\n \n \n {\n showTrigger && (\n \n )\n }\n {\n showClear && (\n \n \n \n )\n }\n \n \n \n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport XIcon from \"@lucide/astro/icons/x\"\n\nimport { cn } from \"@/lib/utils\"\nimport InputGroupAddon from \"@/components/ui/input-group/input-group-addon.astro\"\nimport InputGroupButton from \"@/components/ui/input-group/input-group-button.astro\"\nimport InputGroupInput from \"@/components/ui/input-group/input-group-input.astro\"\nimport InputGroup from \"@/components/ui/input-group/input-group.astro\"\n\nimport ComboboxTrigger from \"./combobox-trigger.astro\"\n\ntype Props = HTMLAttributes<\"input\"> & {\n showTrigger?: boolean\n showClear?: boolean\n}\n\nconst {\n class: className,\n type = \"text\",\n disabled = false,\n showTrigger = true,\n showClear = false,\n ...props\n} = Astro.props\n---\n\n\n \n \n {\n showTrigger && (\n \n )\n }\n {\n showClear && (\n \n \n \n )\n }\n \n \n \n",
"type": "registry:ui"
},
{
@@ -59,7 +59,7 @@
},
{
"path": "src/components/ui/combobox/combobox-trigger.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport ChevronDownIcon from \"@lucide/astro/icons/chevron-down\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"button\"> & {\n showIcon?: boolean\n}\n\nconst {\n class: className,\n type = \"button\",\n showIcon = true,\n ...props\n} = Astro.props\n---\n\n\n \n {\n showIcon && (\n \n )\n }\n \n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport ChevronDownIcon from \"@lucide/astro/icons/chevron-down\"\n\nimport { cn } from \"@/lib/utils\"\nimport InputGroupButton from \"@/components/ui/input-group/input-group-button.astro\"\n\ntype Props = HTMLAttributes<\"button\"> & {\n showIcon?: boolean\n}\n\nconst {\n class: className,\n type = \"button\",\n showIcon = true,\n ...props\n} = Astro.props\n---\n\n\n \n {\n showIcon && (\n \n )\n }\n \n",
"type": "registry:ui"
},
{
diff --git a/public/r/command.json b/public/r/command.json
index 7c998ba23..be0a872ee 100644
--- a/public/r/command.json
+++ b/public/r/command.json
@@ -4,9 +4,9 @@
"title": "Command",
"description": "Command menu for search and quick actions.",
"dependencies": [
- "@data-slot/command@^1.0.1",
+ "@data-slot/command@^1.0.2",
"@lucide/astro",
- "@data-slot/core@^1.0.1"
+ "@data-slot/core@^1.0.2"
],
"registryDependencies": [
"@fulldev/dialog"
diff --git a/public/r/components.json b/public/r/components.json
index 4d4050ca0..90872f412 100644
--- a/public/r/components.json
+++ b/public/r/components.json
@@ -7,11 +7,14 @@
"@fulldev/accordion",
"@fulldev/alert",
"@fulldev/alert-dialog",
+ "@fulldev/aspect-ratio",
+ "@fulldev/attachment",
"@fulldev/avatar",
"@fulldev/badge",
"@fulldev/banner",
"@fulldev/breadcrumb",
"@fulldev/button",
+ "@fulldev/button-group",
"@fulldev/card",
"@fulldev/carousel",
"@fulldev/checkbox",
@@ -19,6 +22,7 @@
"@fulldev/combobox",
"@fulldev/command",
"@fulldev/dialog",
+ "@fulldev/drawer",
"@fulldev/dropdown-menu",
"@fulldev/empty",
"@fulldev/field",
@@ -36,10 +40,12 @@
"@fulldev/marquee",
"@fulldev/native-select",
"@fulldev/navigation-menu",
+ "@fulldev/pagination",
"@fulldev/popover",
"@fulldev/price",
"@fulldev/radio-group",
"@fulldev/rating",
+ "@fulldev/resizable",
"@fulldev/section",
"@fulldev/select",
"@fulldev/separator",
@@ -53,8 +59,10 @@
"@fulldev/tabs",
"@fulldev/textarea",
"@fulldev/theme-toggle",
+ "@fulldev/toast",
"@fulldev/toc",
"@fulldev/toggle",
+ "@fulldev/toggle-group",
"@fulldev/tooltip",
"@fulldev/typography",
"@fulldev/video"
diff --git a/public/r/dialog.json b/public/r/dialog.json
index 7efc1928a..3db40b95f 100644
--- a/public/r/dialog.json
+++ b/public/r/dialog.json
@@ -4,7 +4,7 @@
"title": "Dialog",
"description": "A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.",
"dependencies": [
- "@data-slot/dialog@^1.0.1",
+ "@data-slot/dialog@^1.0.2",
"@lucide/astro"
],
"registryDependencies": [
diff --git a/public/r/doc-1.json b/public/r/doc-1.json
index c83d79bea..1a40cc41f 100644
--- a/public/r/doc-1.json
+++ b/public/r/doc-1.json
@@ -18,7 +18,7 @@
"files": [
{
"path": "src/components/blocks/doc-1.astro",
- "content": "---\nimport ArrowLeft from \"@lucide/astro/icons/arrow-left\"\nimport ArrowRight from \"@lucide/astro/icons/arrow-right\"\nimport Check from \"@lucide/astro/icons/check\"\nimport ChevronDown from \"@lucide/astro/icons/chevron-down\"\nimport Copy from \"@lucide/astro/icons/copy\"\nimport ExternalLink from \"@lucide/astro/icons/external-link\"\nimport Claude from \"simple-icons-astro/Claude\"\nimport Cursor from \"simple-icons-astro/Cursor\"\nimport Markdown from \"simple-icons-astro/Markdown\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { buttonVariants } from \"@/components/ui/button/button-variants\"\nimport {\n Card,\n CardDescription,\n CardFooter,\n CardHeader,\n} from \"@/components/ui/card\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\nimport { SectionContainer } from \"@/components/ui/section\"\nimport {\n Toc,\n TocMenu,\n TocMenuItem,\n TocMenuLink,\n TocTitle,\n} from \"@/components/ui/toc\"\nimport {\n Typography,\n TypographyH1,\n TypographyLead,\n} from \"@/components/ui/typography\"\n\ntype Props = {\n class?: string\n title: string\n description?: string\n copyButton?: {\n id: string\n source: string\n }\n markdownUrl?: string\n tocItems: {\n depth: number\n href: string\n label: string\n }[]\n callout?: {\n description: string\n button: {\n label: string\n href: string\n variant?: \"default\" | \"outline\" | \"secondary\" | \"ghost\"\n }\n }\n previousPage?: {\n href: string\n title: string\n }\n nextPage?: {\n href: string\n title: string\n }\n labels: {\n copyMarkdown: string\n openIn: string\n openInMarkdown: string\n openInChatGPT: string\n openInClaude: string\n openInCursor: string\n pagination: {\n previous: string\n next: string\n ariaLabel: string\n }\n toc: string\n }\n}\n\nconst {\n class: className,\n title,\n description,\n copyButton,\n markdownUrl,\n tocItems,\n callout,\n previousPage,\n nextPage,\n labels,\n} = Astro.props\nconst showCopyButton = Boolean(copyButton)\nconst showOpenButton = Boolean(markdownUrl)\nconst showPagination = Boolean(previousPage || nextPage)\nconst assistantPrompt = markdownUrl\n ? `Read ${new URL(markdownUrl, Astro.site ?? Astro.url.origin).href}, I want to ask questions about it.`\n : \"\"\nconst openLinks = markdownUrl\n ? [\n {\n label: labels.openInMarkdown,\n href: markdownUrl,\n icon: \"markdown\",\n },\n {\n label: labels.openInChatGPT,\n href: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(assistantPrompt)}`,\n icon: \"chatgpt\",\n },\n {\n label: labels.openInClaude,\n href: `https://claude.ai/new?q=${encodeURIComponent(assistantPrompt)}`,\n icon: \"claude\",\n },\n {\n label: labels.openInCursor,\n href: `https://cursor.com/link/prompt?text=${encodeURIComponent(assistantPrompt)}`,\n icon: \"cursor\",\n },\n ]\n : []\n---\n\n\n \n
\n \n \n {title}\n \n {\n description && (\n \n {description}\n \n )\n }\n
\n \n {\n showCopyButton && (\n
\n \n \n {labels.copyMarkdown} \n \n )\n }\n {\n showOpenButton && (\n
\n \n {labels.openIn} \n \n \n \n {openLinks.map((link) => (\n \n {link.icon === \"markdown\" && }\n {link.icon === \"chatgpt\" && (\n \n \n \n )}\n {link.icon === \"claude\" && }\n {link.icon === \"cursor\" && }\n {link.label} \n \n \n ))}\n \n \n )\n }\n
\n \n\n
\n \n \n\n {\n showPagination && (\n
\n {previousPage ? (\n \n \n \n {previousPage.title}\n \n \n ) : (\n
\n )}\n\n {nextPage ? (\n \n {nextPage.title} \n \n \n ) : (\n
\n )}\n \n )\n }\n
\n\n {\n (tocItems.length > 0 || callout) && (\n \n \n {tocItems.length > 0 && (\n \n {labels.toc} \n \n {tocItems.map((item) => (\n \n \n {item.label}\n \n \n ))}\n \n \n )}\n\n {callout && (\n \n \n {callout.description} \n \n \n \n {callout.button.label}\n \n \n \n )}\n
\n \n )\n }\n \n\n\n",
+ "content": "---\nimport ArrowLeft from \"@lucide/astro/icons/arrow-left\"\nimport ArrowRight from \"@lucide/astro/icons/arrow-right\"\nimport Check from \"@lucide/astro/icons/check\"\nimport ChevronDown from \"@lucide/astro/icons/chevron-down\"\nimport Copy from \"@lucide/astro/icons/copy\"\nimport ExternalLink from \"@lucide/astro/icons/external-link\"\nimport Claude from \"simple-icons-astro/Claude\"\nimport Cursor from \"simple-icons-astro/Cursor\"\nimport Markdown from \"simple-icons-astro/Markdown\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\nimport { buttonVariants } from \"@/components/ui/button/button-variants\"\nimport {\n Card,\n CardDescription,\n CardFooter,\n CardHeader,\n} from \"@/components/ui/card\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\nimport { SectionContainer } from \"@/components/ui/section\"\nimport {\n Toc,\n TocMenu,\n TocMenuItem,\n TocMenuLink,\n TocTitle,\n} from \"@/components/ui/toc\"\nimport {\n Typography,\n TypographyH1,\n TypographyLead,\n} from \"@/components/ui/typography\"\n\ntype Props = {\n class?: string\n title: string\n description?: string\n copyButton?: {\n id: string\n source: string\n }\n markdownUrl?: string\n tocItems: {\n depth: number\n href: string\n label: string\n }[]\n callout?: {\n description: string\n button: {\n label: string\n href: string\n variant?: \"default\" | \"outline\" | \"secondary\" | \"ghost\"\n }\n }\n previousPage?: {\n href: string\n title: string\n }\n nextPage?: {\n href: string\n title: string\n }\n labels: {\n copyMarkdown: string\n openIn: string\n openInMarkdown: string\n openInChatGPT: string\n openInClaude: string\n openInCursor: string\n pagination: {\n previous: string\n next: string\n ariaLabel: string\n }\n toc: string\n }\n}\n\nconst {\n class: className,\n title,\n description,\n copyButton,\n markdownUrl,\n tocItems,\n callout,\n previousPage,\n nextPage,\n labels,\n} = Astro.props\nconst showCopyButton = Boolean(copyButton)\nconst showOpenButton = Boolean(markdownUrl)\nconst showPagination = Boolean(previousPage || nextPage)\nconst assistantPrompt = markdownUrl\n ? `Read ${new URL(markdownUrl, Astro.site ?? Astro.url.origin).href}, I want to ask questions about it.`\n : \"\"\nconst openLinks = markdownUrl\n ? [\n {\n label: labels.openInMarkdown,\n href: markdownUrl,\n icon: \"markdown\",\n },\n {\n label: labels.openInChatGPT,\n href: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(assistantPrompt)}`,\n icon: \"chatgpt\",\n },\n {\n label: labels.openInClaude,\n href: `https://claude.ai/new?q=${encodeURIComponent(assistantPrompt)}`,\n icon: \"claude\",\n },\n {\n label: labels.openInCursor,\n href: `https://cursor.com/link/prompt?text=${encodeURIComponent(assistantPrompt)}`,\n icon: \"cursor\",\n },\n ]\n : []\n---\n\n\n \n
\n \n \n {title}\n \n {\n description && (\n \n {description}\n \n )\n }\n
\n \n {\n showCopyButton && (\n
\n \n \n {labels.copyMarkdown} \n \n )\n }\n {\n showOpenButton && (\n
\n \n {labels.openIn} \n \n \n \n {openLinks.map((link) => (\n \n {link.icon === \"markdown\" && }\n {link.icon === \"chatgpt\" && (\n \n \n \n )}\n {link.icon === \"claude\" && }\n {link.icon === \"cursor\" && }\n {link.label} \n \n \n ))}\n \n \n )\n }\n
\n \n\n
\n \n \n\n {\n showPagination && (\n
\n {previousPage ? (\n \n \n \n {previousPage.title}\n \n \n ) : (\n
\n )}\n\n {nextPage ? (\n \n {nextPage.title} \n \n \n ) : (\n
\n )}\n \n )\n }\n
\n\n {\n (tocItems.length > 0 || callout) && (\n \n \n {tocItems.length > 0 && (\n \n {labels.toc} \n \n {tocItems.map((item) => (\n \n \n {item.label}\n \n \n ))}\n \n \n )}\n\n {callout && (\n \n \n {callout.description} \n \n \n \n {callout.button.label}\n \n \n \n )}\n
\n \n )\n }\n \n\n\n\n\n",
"type": "registry:block"
}
],
diff --git a/public/r/drawer.json b/public/r/drawer.json
new file mode 100644
index 000000000..192ba35f7
--- /dev/null
+++ b/public/r/drawer.json
@@ -0,0 +1,109 @@
+{
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
+ "name": "drawer",
+ "title": "Drawer",
+ "description": "A swipeable panel that opens from an edge of the screen.",
+ "dependencies": [
+ "@data-slot/drawer@^1.0.2"
+ ],
+ "registryDependencies": [
+ "@fulldev/button"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/drawer/drawer-close.astro",
+ "content": "---\nimport type { ComponentProps } from \"astro/types\"\n\nimport { Button } from \"@/components/ui/button\"\n\ntype Props = ComponentProps\n\nconst { ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-content.astro",
+ "content": "---\nimport type { ComponentProps } from \"astro/types\"\n\nimport DrawerOverlay from \"./drawer-overlay.astro\"\nimport DrawerPopup from \"./drawer-popup.astro\"\nimport DrawerPortal from \"./drawer-portal.astro\"\nimport DrawerSwipeHandle from \"./drawer-swipe-handle.astro\"\nimport DrawerViewport from \"./drawer-viewport.astro\"\n\ntype Props = ComponentProps & {\n showOverlay?: boolean\n showSwipeHandle?: boolean\n container?: string\n keepMounted?: boolean\n overlayClass?: string\n viewportClass?: string\n}\n\nconst {\n showOverlay = true,\n showSwipeHandle = false,\n container,\n keepMounted,\n overlayClass,\n viewportClass,\n ...props\n} = Astro.props\n---\n\n\n {showOverlay && }\n \n \n {showSwipeHandle && }\n \n \n
\n \n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-description.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"p\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-footer.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-header.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-indent-background.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-indent.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-overlay.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, hidden = true, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-popup.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n initialFocus?: boolean | string\n finalFocus?: boolean | string\n}\n\nconst {\n class: className,\n initialFocus,\n finalFocus,\n hidden = true,\n ...props\n} = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-portal.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n container?: string\n keepMounted?: boolean\n}\n\nconst {\n class: className,\n container,\n keepMounted,\n hidden = true,\n ...props\n} = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-provider.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-swipe-handle.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-title.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"h2\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-trigger.astro",
+ "content": "---\nimport type { ComponentProps } from \"astro/types\"\n\nimport { Button } from \"@/components/ui/button\"\n\ntype Props = ComponentProps & {\n drawerTarget?: string\n payload?: string\n}\n\nconst { drawerTarget, payload, ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-viewport.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, hidden = true, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-virtual-keyboard-provider.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport type { DrawerSnapPoint, DrawerSwipeDirection } from \"@data-slot/drawer\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n defaultOpen?: boolean\n modal?: boolean | \"trap-focus\"\n disablePointerDismissal?: boolean\n closeOnEscape?: boolean\n swipeDirection?: DrawerSwipeDirection\n snapPoint?: DrawerSnapPoint | null\n defaultSnapPoint?: DrawerSnapPoint | null\n triggerId?: string | null\n defaultTriggerId?: string | null\n}\n\nconst {\n class: className,\n defaultOpen,\n modal,\n disablePointerDismissal,\n closeOnEscape,\n swipeDirection,\n snapPoint,\n defaultSnapPoint,\n triggerId,\n defaultTriggerId,\n ...props\n} = Astro.props\n---\n\n\n \n
\n\n\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/index.ts",
+ "content": "export { default as Drawer } from \"./drawer.astro\"\nexport { default as DrawerTrigger } from \"./drawer-trigger.astro\"\nexport { default as DrawerClose } from \"./drawer-close.astro\"\nexport { default as DrawerPortal } from \"./drawer-portal.astro\"\nexport { default as DrawerOverlay } from \"./drawer-overlay.astro\"\nexport { default as DrawerBackdrop } from \"./drawer-overlay.astro\"\nexport { default as DrawerViewport } from \"./drawer-viewport.astro\"\nexport { default as DrawerPopup } from \"./drawer-popup.astro\"\nexport { default as DrawerContent } from \"./drawer-content.astro\"\nexport { default as DrawerSwipeHandle } from \"./drawer-swipe-handle.astro\"\nexport { default as DrawerHeader } from \"./drawer-header.astro\"\nexport { default as DrawerFooter } from \"./drawer-footer.astro\"\nexport { default as DrawerTitle } from \"./drawer-title.astro\"\nexport { default as DrawerDescription } from \"./drawer-description.astro\"\nexport { default as DrawerProvider } from \"./drawer-provider.astro\"\nexport { default as DrawerIndent } from \"./drawer-indent.astro\"\nexport { default as DrawerIndentBackground } from \"./drawer-indent-background.astro\"\nexport { default as DrawerVirtualKeyboardProvider } from \"./drawer-virtual-keyboard-provider.astro\"\n\nexport type {\n DrawerChangeDetails,\n DrawerChangeReason,\n DrawerController,\n DrawerOptions,\n DrawerSnapChangeDetails,\n DrawerSnapPoint,\n DrawerSwipeDirection,\n} from \"@data-slot/drawer\"\n",
+ "type": "registry:ui"
+ }
+ ],
+ "docs": "https://ui.full.dev/components/drawer/",
+ "categories": [
+ "ui"
+ ],
+ "type": "registry:ui"
+}
\ No newline at end of file
diff --git a/public/r/dropdown-menu.json b/public/r/dropdown-menu.json
index 58bba60c2..dd71cfe79 100644
--- a/public/r/dropdown-menu.json
+++ b/public/r/dropdown-menu.json
@@ -4,7 +4,7 @@
"title": "Dropdown Menu",
"description": "Displays a menu to the user, such as a set of actions or functions, triggered by a button.",
"dependencies": [
- "@data-slot/dropdown-menu@^1.0.1",
+ "@data-slot/dropdown-menu@^1.0.2",
"@lucide/astro"
],
"files": [
diff --git a/public/r/hover-card.json b/public/r/hover-card.json
index e17759b5e..b40eda095 100644
--- a/public/r/hover-card.json
+++ b/public/r/hover-card.json
@@ -4,8 +4,8 @@
"title": "Hover Card",
"description": "For sighted users to preview content available behind a link.",
"dependencies": [
- "@data-slot/hover-card@^1.0.1",
- "@data-slot/core@^1.0.1"
+ "@data-slot/hover-card@^1.0.2",
+ "@data-slot/core@^1.0.2"
],
"files": [
{
diff --git a/public/r/init.json b/public/r/init.json
index 5d91d426e..49a52e5a3 100644
--- a/public/r/init.json
+++ b/public/r/init.json
@@ -18,7 +18,7 @@
},
{
"path": "registry/init/global.css",
- "content": "@import \"tailwindcss\";\n@import \"tw-animate-css\";\n@import \"shadcn/tailwind.css\";\n\n@custom-variant dark (&:where(.dark, .dark *));\n\n:root {\n --background: oklch(1 0 0);\n --foreground: oklch(0.145 0 0);\n --card: oklch(1 0 0);\n --card-foreground: oklch(0.145 0 0);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.145 0 0);\n --primary: oklch(0.5488 0.2498 261.783);\n --primary-foreground: oklch(1 0 0);\n --secondary: oklch(0.97 0 0);\n --secondary-foreground: oklch(0.205 0 0);\n --muted: oklch(0.97 0 0);\n --muted-foreground: oklch(0.556 0 0);\n --accent: oklch(0.97 0 0);\n --accent-foreground: oklch(0.205 0 0);\n --destructive: oklch(0.577 0.245 27.325);\n --destructive-foreground: oklch(1 0 0);\n --border: oklch(0.922 0 0);\n --input: oklch(0.922 0 0);\n --ring: oklch(0.708 0 0);\n --chart-1: oklch(0.81 0.1 252);\n --chart-2: oklch(0.62 0.19 260);\n --chart-3: oklch(0.55 0.22 263);\n --chart-4: oklch(0.49 0.22 264);\n --chart-5: oklch(0.42 0.18 266);\n --sidebar: oklch(0.985 0 0);\n --sidebar-foreground: oklch(0.145 0 0);\n --sidebar-primary: oklch(0.5488 0.2498 261.783);\n --sidebar-primary-foreground: oklch(1 0 0);\n --sidebar-accent: oklch(0.97 0 0);\n --sidebar-accent-foreground: oklch(0.205 0 0);\n --sidebar-border: oklch(0.922 0 0);\n --sidebar-ring: oklch(0.708 0 0);\n --radius: 0.625rem;\n --shadow-x: 0;\n --shadow-y: 1px;\n --shadow-blur: 3px;\n --shadow-spread: 0px;\n --shadow-opacity: 0.1;\n --shadow-color: oklch(0 0 0);\n --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-sm:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);\n --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);\n --shadow-md:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1);\n --shadow-lg:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1);\n --shadow-xl:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1);\n --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);\n --tracking-normal: 0em;\n --spacing: 0.25rem;\n}\n\n.dark {\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.205 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.269 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --primary: oklch(0.686 0.2105 41.139);\n --primary-foreground: oklch(1 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.371 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.704 0.191 22.216);\n --destructive-foreground: oklch(0.985 0 0);\n --border: oklch(0.275 0 0);\n --input: oklch(0.325 0 0);\n --ring: oklch(0.556 0 0);\n --chart-1: oklch(0.81 0.1 252);\n --chart-2: oklch(0.62 0.19 260);\n --chart-3: oklch(0.55 0.22 263);\n --chart-4: oklch(0.49 0.22 264);\n --chart-5: oklch(0.42 0.18 266);\n --sidebar: oklch(0.205 0 0);\n --sidebar-foreground: oklch(0.985 0 0);\n --sidebar-primary: oklch(0.686 0.2105 41.139);\n --sidebar-primary-foreground: oklch(1 0 0);\n --sidebar-accent: oklch(0.269 0 0);\n --sidebar-accent-foreground: oklch(0.985 0 0);\n --sidebar-border: oklch(0.275 0 0);\n --sidebar-ring: oklch(0.439 0 0);\n --radius: 0.625rem;\n --shadow-x: 0;\n --shadow-y: 1px;\n --shadow-blur: 3px;\n --shadow-spread: 0px;\n --shadow-opacity: 0.1;\n --shadow-color: oklch(0 0 0);\n --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-sm:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);\n --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);\n --shadow-md:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1);\n --shadow-lg:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1);\n --shadow-xl:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1);\n --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);\n}\n\n@theme inline {\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-destructive-foreground: var(--destructive-foreground);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n --color-chart-1: var(--chart-1);\n --color-chart-2: var(--chart-2);\n --color-chart-3: var(--chart-3);\n --color-chart-4: var(--chart-4);\n --color-chart-5: var(--chart-5);\n --color-sidebar: var(--sidebar);\n --color-sidebar-foreground: var(--sidebar-foreground);\n --color-sidebar-primary: var(--sidebar-primary);\n --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);\n --color-sidebar-accent: var(--sidebar-accent);\n --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);\n --color-sidebar-border: var(--sidebar-border);\n --color-sidebar-ring: var(--sidebar-ring);\n\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n\n --shadow-2xs: var(--shadow-2xs);\n --shadow-xs: var(--shadow-xs);\n --shadow-sm: var(--shadow-sm);\n --shadow: var(--shadow);\n --shadow-md: var(--shadow-md);\n --shadow-lg: var(--shadow-lg);\n --shadow-xl: var(--shadow-xl);\n --shadow-2xl: var(--shadow-2xl);\n}\n\n@layer base {\n * {\n @apply border-border outline-ring/50;\n }\n html {\n @apply font-sans;\n }\n body {\n @apply bg-background text-foreground font-sans;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n ::before,\n ::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n scroll-behavior: auto !important;\n }\n}\n",
+ "content": "@import \"tailwindcss\";\n@import \"tw-animate-css\";\n@import \"shadcn/tailwind.css\";\n\n@custom-variant dark (&:where(.dark, .dark *));\n\n:root {\n --background: oklch(1 0 0);\n --foreground: oklch(0.145 0 0);\n --card: oklch(1 0 0);\n --card-foreground: oklch(0.145 0 0);\n --popover: oklch(1 0 0);\n --popover-foreground: oklch(0.145 0 0);\n --primary: oklch(0.5488 0.2498 261.783);\n --primary-foreground: oklch(1 0 0);\n --secondary: oklch(0.97 0 0);\n --secondary-foreground: oklch(0.205 0 0);\n --muted: oklch(0.97 0 0);\n --muted-foreground: oklch(0.556 0 0);\n --accent: oklch(0.97 0 0);\n --accent-foreground: oklch(0.205 0 0);\n --destructive: oklch(0.577 0.245 27.325);\n --destructive-foreground: oklch(1 0 0);\n --border: oklch(0.922 0 0);\n --input: oklch(0.922 0 0);\n --ring: oklch(0.708 0 0);\n --chart-1: oklch(0.81 0.1 252);\n --chart-2: oklch(0.62 0.19 260);\n --chart-3: oklch(0.55 0.22 263);\n --chart-4: oklch(0.49 0.22 264);\n --chart-5: oklch(0.42 0.18 266);\n --sidebar: oklch(0.985 0 0);\n --sidebar-foreground: oklch(0.145 0 0);\n --sidebar-primary: oklch(0.5488 0.2498 261.783);\n --sidebar-primary-foreground: oklch(1 0 0);\n --sidebar-accent: oklch(0.97 0 0);\n --sidebar-accent-foreground: oklch(0.205 0 0);\n --sidebar-border: oklch(0.922 0 0);\n --sidebar-ring: oklch(0.708 0 0);\n --radius: 0.625rem;\n --shadow-x: 0;\n --shadow-y: 1px;\n --shadow-blur: 3px;\n --shadow-spread: 0px;\n --shadow-opacity: 0.1;\n --shadow-color: oklch(0 0 0);\n --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-sm:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);\n --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);\n --shadow-md:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1);\n --shadow-lg:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1);\n --shadow-xl:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1);\n --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);\n --tracking-normal: 0em;\n --spacing: 0.25rem;\n}\n\n.dark {\n --background: oklch(0.145 0 0);\n --foreground: oklch(0.985 0 0);\n --card: oklch(0.205 0 0);\n --card-foreground: oklch(0.985 0 0);\n --popover: oklch(0.269 0 0);\n --popover-foreground: oklch(0.985 0 0);\n --primary: oklch(0.686 0.2105 41.139);\n --primary-foreground: oklch(1 0 0);\n --secondary: oklch(0.269 0 0);\n --secondary-foreground: oklch(0.985 0 0);\n --muted: oklch(0.269 0 0);\n --muted-foreground: oklch(0.708 0 0);\n --accent: oklch(0.371 0 0);\n --accent-foreground: oklch(0.985 0 0);\n --destructive: oklch(0.704 0.191 22.216);\n --destructive-foreground: oklch(0.985 0 0);\n --border: oklch(0.275 0 0);\n --input: oklch(0.325 0 0);\n --ring: oklch(0.556 0 0);\n --chart-1: oklch(0.81 0.1 252);\n --chart-2: oklch(0.62 0.19 260);\n --chart-3: oklch(0.55 0.22 263);\n --chart-4: oklch(0.49 0.22 264);\n --chart-5: oklch(0.42 0.18 266);\n --sidebar: oklch(0.205 0 0);\n --sidebar-foreground: oklch(0.985 0 0);\n --sidebar-primary: oklch(0.686 0.2105 41.139);\n --sidebar-primary-foreground: oklch(1 0 0);\n --sidebar-accent: oklch(0.269 0 0);\n --sidebar-accent-foreground: oklch(0.985 0 0);\n --sidebar-border: oklch(0.275 0 0);\n --sidebar-ring: oklch(0.439 0 0);\n --radius: 0.625rem;\n --shadow-x: 0;\n --shadow-y: 1px;\n --shadow-blur: 3px;\n --shadow-spread: 0px;\n --shadow-opacity: 0.1;\n --shadow-color: oklch(0 0 0);\n --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);\n --shadow-sm:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);\n --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);\n --shadow-md:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1);\n --shadow-lg:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1);\n --shadow-xl:\n 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1);\n --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);\n}\n\n@theme inline {\n --font-heading: var(--font-sans);\n\n --color-background: var(--background);\n --color-foreground: var(--foreground);\n --color-card: var(--card);\n --color-card-foreground: var(--card-foreground);\n --color-popover: var(--popover);\n --color-popover-foreground: var(--popover-foreground);\n --color-primary: var(--primary);\n --color-primary-foreground: var(--primary-foreground);\n --color-secondary: var(--secondary);\n --color-secondary-foreground: var(--secondary-foreground);\n --color-muted: var(--muted);\n --color-muted-foreground: var(--muted-foreground);\n --color-accent: var(--accent);\n --color-accent-foreground: var(--accent-foreground);\n --color-destructive: var(--destructive);\n --color-destructive-foreground: var(--destructive-foreground);\n --color-border: var(--border);\n --color-input: var(--input);\n --color-ring: var(--ring);\n --color-chart-1: var(--chart-1);\n --color-chart-2: var(--chart-2);\n --color-chart-3: var(--chart-3);\n --color-chart-4: var(--chart-4);\n --color-chart-5: var(--chart-5);\n --color-sidebar: var(--sidebar);\n --color-sidebar-foreground: var(--sidebar-foreground);\n --color-sidebar-primary: var(--sidebar-primary);\n --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);\n --color-sidebar-accent: var(--sidebar-accent);\n --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);\n --color-sidebar-border: var(--sidebar-border);\n --color-sidebar-ring: var(--sidebar-ring);\n\n --radius-sm: calc(var(--radius) - 4px);\n --radius-md: calc(var(--radius) - 2px);\n --radius-lg: var(--radius);\n --radius-xl: calc(var(--radius) + 4px);\n\n --shadow-2xs: var(--shadow-2xs);\n --shadow-xs: var(--shadow-xs);\n --shadow-sm: var(--shadow-sm);\n --shadow: var(--shadow);\n --shadow-md: var(--shadow-md);\n --shadow-lg: var(--shadow-lg);\n --shadow-xl: var(--shadow-xl);\n --shadow-2xl: var(--shadow-2xl);\n}\n\n@layer base {\n * {\n @apply border-border outline-ring/50;\n }\n html {\n @apply font-sans;\n }\n body {\n @apply bg-background text-foreground font-sans;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n ::before,\n ::after {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n scroll-behavior: auto !important;\n }\n}\n",
"type": "registry:style",
"target": "src/styles/global.css"
}
diff --git a/public/r/navigation-menu.json b/public/r/navigation-menu.json
index 145ea44f9..8493248cb 100644
--- a/public/r/navigation-menu.json
+++ b/public/r/navigation-menu.json
@@ -4,13 +4,13 @@
"title": "Navigation Menu",
"description": "A collection of links for navigating websites.",
"dependencies": [
- "@data-slot/navigation-menu@^1.0.1",
+ "@data-slot/navigation-menu@^1.0.2",
"@lucide/astro"
],
"files": [
{
"path": "src/components/ui/navigation-menu/navigation-menu.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\nimport NavigationMenuPositioner from \"./navigation-menu-positioner.astro\"\n\ntype Props = HTMLAttributes<\"nav\"> & {\n mountStrategy?: \"lazy\" | \"eager\"\n delayOpen?: number\n delayClose?: number\n openOnFocus?: boolean\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n align?: \"start\" | \"center\" | \"end\"\n sideOffset?: number\n alignOffset?: number\n positionMethod?: \"absolute\" | \"fixed\"\n safeTriangle?: boolean\n debugSafeTriangle?: boolean\n}\n\nconst {\n mountStrategy,\n class: className = \"\",\n delayOpen = 0,\n delayClose = 0,\n openOnFocus,\n side = \"bottom\",\n align = \"start\",\n sideOffset = 0,\n alignOffset = 0,\n positionMethod = \"absolute\",\n safeTriangle,\n debugSafeTriangle,\n ...props\n} = Astro.props\n---\n\n\n \n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\nimport NavigationMenuPositioner from \"./navigation-menu-positioner.astro\"\n\ntype Props = HTMLAttributes<\"nav\"> & {\n mountStrategy?: \"lazy\" | \"eager\"\n delayOpen?: number\n delayClose?: number\n openOnFocus?: boolean\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n align?: \"start\" | \"center\" | \"end\"\n sideOffset?: number\n alignOffset?: number\n positionMethod?: \"absolute\" | \"fixed\"\n safeTriangle?: boolean\n debugSafeTriangle?: boolean\n}\n\nconst {\n mountStrategy,\n class: className = \"\",\n delayOpen = 0,\n delayClose = 0,\n openOnFocus,\n side = \"bottom\",\n align = \"start\",\n sideOffset = 8,\n alignOffset = 0,\n positionMethod = \"absolute\",\n safeTriangle,\n debugSafeTriangle,\n ...props\n} = Astro.props\n---\n\n\n \n \n \n\n\n",
"type": "registry:ui"
},
{
diff --git a/public/r/pagination.json b/public/r/pagination.json
new file mode 100644
index 000000000..a5893ed3a
--- /dev/null
+++ b/public/r/pagination.json
@@ -0,0 +1,59 @@
+{
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
+ "name": "pagination",
+ "title": "Pagination",
+ "description": "Page navigation with previous, next, numbered, and overflow links.",
+ "dependencies": [
+ "@lucide/astro"
+ ],
+ "registryDependencies": [
+ "@fulldev/button"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/pagination/index.ts",
+ "content": "export { default as Pagination } from \"./pagination.astro\"\nexport { default as PaginationContent } from \"./pagination-content.astro\"\nexport { default as PaginationEllipsis } from \"./pagination-ellipsis.astro\"\nexport { default as PaginationItem } from \"./pagination-item.astro\"\nexport { default as PaginationLink } from \"./pagination-link.astro\"\nexport { default as PaginationNext } from \"./pagination-next.astro\"\nexport { default as PaginationPrevious } from \"./pagination-previous.astro\"\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-content.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"ul\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-ellipsis.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport EllipsisIcon from \"@lucide/astro/icons/ellipsis\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"span\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n More pages \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-item.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\ntype Props = HTMLAttributes<\"li\">\n\nconst { ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-link.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button, type ButtonVariantProps } from \"@/components/ui/button\"\n\ntype Props = HTMLAttributes<\"a\"> & {\n isActive?: boolean\n disabled?: boolean\n size?: ButtonVariantProps[\"size\"]\n}\n\nconst {\n class: className,\n href,\n isActive,\n disabled,\n size = \"icon\",\n tabindex,\n ...props\n} = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-next.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport ChevronRightIcon from \"@lucide/astro/icons/chevron-right\"\n\nimport { cn } from \"@/lib/utils\"\nimport type { ButtonVariantProps } from \"@/components/ui/button\"\n\nimport PaginationLink from \"./pagination-link.astro\"\n\ntype Props = HTMLAttributes<\"a\"> & {\n text?: string\n disabled?: boolean\n size?: ButtonVariantProps[\"size\"]\n}\n\nconst { class: className, text = \"Next\", ...props } = Astro.props\n---\n\n\n {text} \n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-previous.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport ChevronLeftIcon from \"@lucide/astro/icons/chevron-left\"\n\nimport { cn } from \"@/lib/utils\"\nimport type { ButtonVariantProps } from \"@/components/ui/button\"\n\nimport PaginationLink from \"./pagination-link.astro\"\n\ntype Props = HTMLAttributes<\"a\"> & {\n text?: string\n disabled?: boolean\n size?: ButtonVariantProps[\"size\"]\n}\n\nconst { class: className, text = \"Previous\", ...props } = Astro.props\n---\n\n\n \n {text} \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"nav\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ }
+ ],
+ "docs": "https://ui.full.dev/components/pagination/",
+ "categories": [
+ "ui"
+ ],
+ "type": "registry:ui"
+}
\ No newline at end of file
diff --git a/public/r/popover.json b/public/r/popover.json
index 935120c9c..2d7047e8a 100644
--- a/public/r/popover.json
+++ b/public/r/popover.json
@@ -4,7 +4,7 @@
"title": "Popover",
"description": "Displays rich content in a floating layer, triggered by a button.",
"dependencies": [
- "@data-slot/popover@^1.0.1"
+ "@data-slot/popover@^1.0.2"
],
"files": [
{
diff --git a/public/r/radio-group.json b/public/r/radio-group.json
index 1f2625f85..839a1721b 100644
--- a/public/r/radio-group.json
+++ b/public/r/radio-group.json
@@ -4,7 +4,7 @@
"title": "Radio Group",
"description": "A set of checkable buttons, known as radio buttons, where no more than one of the buttons can be checked at a time.",
"dependencies": [
- "@data-slot/radio-group@^1.0.1"
+ "@data-slot/radio-group@^1.0.2"
],
"files": [
{
diff --git a/public/r/registry.json b/public/r/registry.json
index 15d80d9e6..6ef55485b 100644
--- a/public/r/registry.json
+++ b/public/r/registry.json
@@ -13,7 +13,7 @@
],
"docs": "https://ui.full.dev/components/accordion/",
"dependencies": [
- "@data-slot/accordion@^1.0.1",
+ "@data-slot/accordion@^1.0.2",
"@lucide/astro"
],
"files": [
@@ -77,7 +77,7 @@
],
"docs": "https://ui.full.dev/components/alert-dialog/",
"dependencies": [
- "@data-slot/alert-dialog@^1.0.1"
+ "@data-slot/alert-dialog@^1.0.2"
],
"registryDependencies": [
"@fulldev/button"
@@ -361,7 +361,7 @@
],
"docs": "https://ui.full.dev/components/collapsible/",
"dependencies": [
- "@data-slot/collapsible@^1.0.1"
+ "@data-slot/collapsible@^1.0.2"
],
"files": [
{
@@ -392,8 +392,8 @@
],
"docs": "https://ui.full.dev/components/combobox/",
"dependencies": [
- "@data-slot/combobox@^1.0.1",
- "@data-slot/core@^1.0.1",
+ "@data-slot/combobox@^1.0.2",
+ "@data-slot/core@^1.0.2",
"@lucide/astro"
],
"registryDependencies": [
@@ -460,9 +460,9 @@
],
"docs": "https://ui.full.dev/components/command/",
"dependencies": [
- "@data-slot/command@^1.0.1",
+ "@data-slot/command@^1.0.2",
"@lucide/astro",
- "@data-slot/core@^1.0.1"
+ "@data-slot/core@^1.0.2"
],
"registryDependencies": [
"@fulldev/dialog"
@@ -520,7 +520,7 @@
],
"docs": "https://ui.full.dev/components/dialog/",
"dependencies": [
- "@data-slot/dialog@^1.0.1",
+ "@data-slot/dialog@^1.0.2",
"@lucide/astro"
],
"registryDependencies": [
@@ -583,7 +583,7 @@
],
"docs": "https://ui.full.dev/components/dropdown-menu/",
"dependencies": [
- "@data-slot/dropdown-menu@^1.0.1",
+ "@data-slot/dropdown-menu@^1.0.2",
"@lucide/astro"
],
"files": [
@@ -798,8 +798,8 @@
],
"docs": "https://ui.full.dev/components/hover-card/",
"dependencies": [
- "@data-slot/hover-card@^1.0.1",
- "@data-slot/core@^1.0.1"
+ "@data-slot/hover-card@^1.0.2",
+ "@data-slot/core@^1.0.2"
],
"files": [
{
@@ -1079,13 +1079,13 @@
"name": "carousel",
"type": "registry:ui",
"title": "Carousel",
- "description": "A carousel with motion and swipe built using Embla.",
+ "description": "An accessible carousel built on native scrolling with Data Slot.",
"categories": [
"ui"
],
"docs": "https://ui.full.dev/components/carousel/",
"dependencies": [
- "embla-carousel",
+ "@data-slot/carousel@^1.0.2",
"@lucide/astro"
],
"registryDependencies": [
@@ -1128,7 +1128,7 @@
],
"docs": "https://ui.full.dev/components/navigation-menu/",
"dependencies": [
- "@data-slot/navigation-menu@^1.0.1",
+ "@data-slot/navigation-menu@^1.0.2",
"@lucide/astro"
],
"files": [
@@ -1215,7 +1215,7 @@
],
"docs": "https://ui.full.dev/components/popover/",
"dependencies": [
- "@data-slot/popover@^1.0.1"
+ "@data-slot/popover@^1.0.2"
],
"files": [
{
@@ -1290,7 +1290,7 @@
],
"docs": "https://ui.full.dev/components/radio-group/",
"dependencies": [
- "@data-slot/radio-group@^1.0.1"
+ "@data-slot/radio-group@^1.0.2"
],
"files": [
{
@@ -1340,7 +1340,7 @@
],
"docs": "https://ui.full.dev/components/select/",
"dependencies": [
- "@data-slot/select@^1.0.1",
+ "@data-slot/select@^1.0.2",
"@lucide/astro"
],
"files": [
@@ -1444,7 +1444,7 @@
],
"docs": "https://ui.full.dev/components/sheet/",
"dependencies": [
- "@data-slot/dialog@^1.0.1",
+ "@data-slot/dialog@^1.0.2",
"@lucide/astro"
],
"registryDependencies": [
@@ -1500,7 +1500,7 @@
],
"docs": "https://ui.full.dev/components/sidebar/",
"dependencies": [
- "@data-slot/tooltip@^1.0.1",
+ "@data-slot/tooltip@^1.0.2",
"@lucide/astro"
],
"registryDependencies": [
@@ -1621,7 +1621,7 @@
],
"docs": "https://ui.full.dev/components/slider/",
"dependencies": [
- "@data-slot/slider@^1.0.1"
+ "@data-slot/slider@^1.0.2"
],
"files": [
{
@@ -1687,7 +1687,7 @@
],
"docs": "https://ui.full.dev/components/switch/",
"dependencies": [
- "@data-slot/switch@^1.0.1"
+ "@data-slot/switch@^1.0.2"
],
"files": [
{
@@ -1758,7 +1758,7 @@
],
"docs": "https://ui.full.dev/components/tabs/",
"dependencies": [
- "@data-slot/tabs@^1.0.1"
+ "@data-slot/tabs@^1.0.2"
],
"files": [
{
@@ -1833,7 +1833,7 @@
],
"docs": "https://ui.full.dev/components/toggle/",
"dependencies": [
- "@data-slot/toggle@^1.0.1"
+ "@data-slot/toggle@^1.0.2"
],
"files": [
{
@@ -1880,7 +1880,7 @@
],
"docs": "https://ui.full.dev/components/tooltip/",
"dependencies": [
- "@data-slot/tooltip@^1.0.1"
+ "@data-slot/tooltip@^1.0.2"
],
"files": [
{
@@ -1978,6 +1978,10 @@
{
"path": "src/components/ui/typography/index.ts",
"type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/typography/typeset.css",
+ "type": "registry:ui"
}
]
},
@@ -2001,6 +2005,384 @@
}
]
},
+ {
+ "name": "drawer",
+ "type": "registry:ui",
+ "title": "Drawer",
+ "description": "A swipeable panel that opens from an edge of the screen.",
+ "categories": [
+ "ui"
+ ],
+ "docs": "https://ui.full.dev/components/drawer/",
+ "dependencies": [
+ "@data-slot/drawer@^1.0.2"
+ ],
+ "registryDependencies": [
+ "@fulldev/button"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/drawer/drawer-close.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-content.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-description.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-footer.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-header.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-indent-background.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-indent.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-overlay.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-popup.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-portal.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-provider.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-swipe-handle.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-title.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-trigger.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-viewport.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-virtual-keyboard-provider.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/index.ts",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "resizable",
+ "type": "registry:ui",
+ "title": "Resizable",
+ "description": "Accessible panel groups with pointer and keyboard resizing.",
+ "categories": [
+ "ui"
+ ],
+ "docs": "https://ui.full.dev/components/resizable/",
+ "dependencies": [
+ "@data-slot/resizable@^1.0.2"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/resizable/index.ts",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/resizable/resizable-handle.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/resizable/resizable-panel.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/resizable/resizable.astro",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "toast",
+ "type": "registry:ui",
+ "title": "Toast",
+ "description": "A brief notification that appears without interrupting the user.",
+ "categories": [
+ "ui"
+ ],
+ "docs": "https://ui.full.dev/components/toast/",
+ "dependencies": [
+ "@data-slot/toast@^1.0.2",
+ "@lucide/astro"
+ ],
+ "registryDependencies": [
+ "@fulldev/button"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/toast/index.ts",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-action.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-close.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-content.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-description.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-icon.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-item.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-template.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-title.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-viewport.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toaster.astro",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "toggle-group",
+ "type": "registry:ui",
+ "title": "Toggle Group",
+ "description": "A set of two-state buttons that can be toggled independently or as a single choice.",
+ "categories": [
+ "ui"
+ ],
+ "docs": "https://ui.full.dev/components/toggle-group/",
+ "dependencies": [
+ "@data-slot/toggle-group@^1.0.2"
+ ],
+ "registryDependencies": [
+ "@fulldev/toggle"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/toggle-group/index.ts",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toggle-group/toggle-group-item.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toggle-group/toggle-group.astro",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "attachment",
+ "type": "registry:ui",
+ "title": "Attachment",
+ "description": "Displays a file or image attachment with media, metadata, state, and actions.",
+ "categories": [
+ "ui"
+ ],
+ "docs": "https://ui.full.dev/components/attachment/",
+ "registryDependencies": [
+ "@fulldev/button"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/attachment/attachment-action.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-actions.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-content.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-description.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-group.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-media.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-title.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-trigger.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/index.ts",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "button-group",
+ "type": "registry:ui",
+ "title": "Button Group",
+ "description": "Groups related controls with connected edges and consistent focus behavior.",
+ "categories": [
+ "ui"
+ ],
+ "docs": "https://ui.full.dev/components/button-group/",
+ "registryDependencies": [
+ "@fulldev/separator"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/button-group/button-group-separator.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/button-group-text.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/button-group-variants.ts",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/button-group.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/index.ts",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "pagination",
+ "type": "registry:ui",
+ "title": "Pagination",
+ "description": "Page navigation with previous, next, numbered, and overflow links.",
+ "categories": [
+ "ui"
+ ],
+ "docs": "https://ui.full.dev/components/pagination/",
+ "dependencies": [
+ "@lucide/astro"
+ ],
+ "registryDependencies": [
+ "@fulldev/button"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/pagination/index.ts",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-content.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-ellipsis.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-item.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-link.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-next.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-previous.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination.astro",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "aspect-ratio",
+ "type": "registry:ui",
+ "title": "Aspect Ratio",
+ "description": "Displays content within a desired ratio.",
+ "categories": [
+ "ui"
+ ],
+ "docs": "https://ui.full.dev/components/aspect-ratio/",
+ "files": [
+ {
+ "path": "src/components/ui/aspect-ratio/aspect-ratio.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/aspect-ratio/index.ts",
+ "type": "registry:ui"
+ }
+ ]
+ },
{
"name": "components",
"type": "registry:item",
@@ -2011,11 +2393,14 @@
"@fulldev/accordion",
"@fulldev/alert",
"@fulldev/alert-dialog",
+ "@fulldev/aspect-ratio",
+ "@fulldev/attachment",
"@fulldev/avatar",
"@fulldev/badge",
"@fulldev/banner",
"@fulldev/breadcrumb",
"@fulldev/button",
+ "@fulldev/button-group",
"@fulldev/card",
"@fulldev/carousel",
"@fulldev/checkbox",
@@ -2023,6 +2408,7 @@
"@fulldev/combobox",
"@fulldev/command",
"@fulldev/dialog",
+ "@fulldev/drawer",
"@fulldev/dropdown-menu",
"@fulldev/empty",
"@fulldev/field",
@@ -2040,10 +2426,12 @@
"@fulldev/marquee",
"@fulldev/native-select",
"@fulldev/navigation-menu",
+ "@fulldev/pagination",
"@fulldev/popover",
"@fulldev/price",
"@fulldev/radio-group",
"@fulldev/rating",
+ "@fulldev/resizable",
"@fulldev/section",
"@fulldev/select",
"@fulldev/separator",
@@ -2057,8 +2445,10 @@
"@fulldev/tabs",
"@fulldev/textarea",
"@fulldev/theme-toggle",
+ "@fulldev/toast",
"@fulldev/toc",
"@fulldev/toggle",
+ "@fulldev/toggle-group",
"@fulldev/tooltip",
"@fulldev/typography",
"@fulldev/video"
diff --git a/public/r/resizable.json b/public/r/resizable.json
new file mode 100644
index 000000000..101260f75
--- /dev/null
+++ b/public/r/resizable.json
@@ -0,0 +1,36 @@
+{
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
+ "name": "resizable",
+ "title": "Resizable",
+ "description": "Accessible panel groups with pointer and keyboard resizing.",
+ "dependencies": [
+ "@data-slot/resizable@^1.0.2"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/resizable/index.ts",
+ "content": "export { default as Resizable } from \"./resizable.astro\"\nexport { default as ResizablePanelGroup } from \"./resizable.astro\"\nexport { default as ResizablePanel } from \"./resizable-panel.astro\"\nexport { default as ResizableHandle } from \"./resizable-handle.astro\"\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/resizable/resizable-handle.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n withHandle?: boolean\n disabled?: boolean\n}\n\nconst { class: className, withHandle, disabled, ...props } = Astro.props\n---\n\ndiv]:rotate-90\",\n className\n )}\n {...props}\n>\n {\n withHandle && (\n
\n )\n }\n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/resizable/resizable-panel.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n defaultSize?: number\n minSize?: number\n maxSize?: number\n collapsible?: boolean\n collapsedSize?: number\n}\n\nconst {\n class: className,\n defaultSize,\n minSize,\n maxSize,\n collapsible,\n collapsedSize,\n ...props\n} = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/resizable/resizable.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n direction?: \"horizontal\" | \"vertical\"\n keyboardResizeBy?: number\n}\n\nconst {\n class: className,\n direction = \"horizontal\",\n keyboardResizeBy,\n ...props\n} = Astro.props\n---\n\n\n \n
\n\n\n",
+ "type": "registry:ui"
+ }
+ ],
+ "docs": "https://ui.full.dev/components/resizable/",
+ "categories": [
+ "ui"
+ ],
+ "type": "registry:ui"
+}
\ No newline at end of file
diff --git a/public/r/reviews-3.json b/public/r/reviews-3.json
index 9cc0cd3e8..cc38797dc 100644
--- a/public/r/reviews-3.json
+++ b/public/r/reviews-3.json
@@ -15,7 +15,7 @@
"files": [
{
"path": "src/components/blocks/reviews-3.astro",
- "content": "---\nimport type { ImageMetadata } from \"astro\"\nimport type { HTMLAttributes } from \"astro/types\"\nimport QuoteIcon from \"@lucide/astro/icons/quote\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\"\nimport {\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselNext,\n CarouselPrevious,\n} from \"@/components/ui/carousel\"\nimport { Rating } from \"@/components/ui/rating\"\nimport {\n Section,\n SectionContainer,\n SectionDescription,\n SectionTitle,\n} from \"@/components/ui/section\"\n\ntype Props = HTMLAttributes<\"section\"> & {\n title?: string\n description?: string\n reviews: {\n rating: number\n quote: string\n image?: ImageMetadata\n initials: string\n name: string\n role: string\n }[]\n}\n\nconst { class: className, title, description, reviews, ...props } = Astro.props\n---\n\n\n {\n (title || description) && (\n \n {title && {title} }\n {description && (\n \n {description}\n \n )}\n \n )\n }\n \n \n \n {\n reviews.map((item) => (\n \n \n
\n
\n
\n {item.quote}\n \n
\n
\n \n {item.initials} \n \n
\n
\n {item.name}\n
\n
{item.role}
\n
\n
\n
\n \n ))\n }\n \n \n \n \n \n \n",
+ "content": "---\nimport type { ImageMetadata } from \"astro\"\nimport type { HTMLAttributes } from \"astro/types\"\nimport QuoteIcon from \"@lucide/astro/icons/quote\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Avatar, AvatarFallback, AvatarImage } from \"@/components/ui/avatar\"\nimport {\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselNext,\n CarouselPrevious,\n} from \"@/components/ui/carousel\"\nimport { Rating } from \"@/components/ui/rating\"\nimport {\n Section,\n SectionContainer,\n SectionDescription,\n SectionTitle,\n} from \"@/components/ui/section\"\n\ntype Props = HTMLAttributes<\"section\"> & {\n title?: string\n description?: string\n reviews: {\n rating: number\n quote: string\n image?: ImageMetadata\n initials: string\n name: string\n role: string\n }[]\n}\n\nconst { class: className, title, description, reviews, ...props } = Astro.props\n---\n\n\n {\n (title || description) && (\n \n {title && {title} }\n {description && (\n \n {description}\n \n )}\n \n )\n }\n \n \n \n {\n reviews.map((item) => (\n \n \n
\n
\n
\n {item.quote}\n \n
\n
\n \n {item.initials} \n \n
\n
\n {item.name}\n
\n
{item.role}
\n
\n
\n
\n \n ))\n }\n \n \n \n \n \n \n",
"type": "registry:block"
}
],
diff --git a/public/r/select.json b/public/r/select.json
index 10b5ca1c3..6d14a751d 100644
--- a/public/r/select.json
+++ b/public/r/select.json
@@ -4,7 +4,7 @@
"title": "Select",
"description": "Displays a list of options for the user to pick from, triggered by a button.",
"dependencies": [
- "@data-slot/select@^1.0.1",
+ "@data-slot/select@^1.0.2",
"@lucide/astro"
],
"files": [
diff --git a/public/r/sheet.json b/public/r/sheet.json
index 9759879c3..342505dc9 100644
--- a/public/r/sheet.json
+++ b/public/r/sheet.json
@@ -4,7 +4,7 @@
"title": "Sheet",
"description": "A sliding panel component that appears from the edge of the screen.",
"dependencies": [
- "@data-slot/dialog@^1.0.1",
+ "@data-slot/dialog@^1.0.2",
"@lucide/astro"
],
"registryDependencies": [
diff --git a/public/r/sidebar.json b/public/r/sidebar.json
index 45669fa49..57a79c163 100644
--- a/public/r/sidebar.json
+++ b/public/r/sidebar.json
@@ -4,7 +4,7 @@
"title": "Sidebar",
"description": "A composable, themeable, and customizable Astro sidebar component.",
"dependencies": [
- "@data-slot/tooltip@^1.0.1",
+ "@data-slot/tooltip@^1.0.2",
"@lucide/astro"
],
"registryDependencies": [
diff --git a/public/r/slider.json b/public/r/slider.json
index a12da5a16..2188dd94f 100644
--- a/public/r/slider.json
+++ b/public/r/slider.json
@@ -4,12 +4,12 @@
"title": "Slider",
"description": "An input where the user selects a value from within a given range.",
"dependencies": [
- "@data-slot/slider@^1.0.1"
+ "@data-slot/slider@^1.0.2"
],
"files": [
{
"path": "src/components/ui/slider/slider.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype SliderValue = number | [number, number]\ntype ThumbAlignment = \"center\" | \"edge\" | \"edge-client-only\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n defaultValue?: SliderValue\n min?: number\n max?: number\n step?: number\n largeStep?: number\n orientation?: \"horizontal\" | \"vertical\"\n thumbAlignment?: ThumbAlignment\n disabled?: boolean\n}\n\nconst {\n class: className,\n defaultValue,\n min,\n max,\n step,\n largeStep,\n orientation = \"horizontal\",\n thumbAlignment = \"center\",\n disabled,\n ...props\n} = Astro.props\n\nconst serializedDefaultValue = Array.isArray(defaultValue)\n ? defaultValue.join(\",\")\n : defaultValue\nconst thumbCount = String(serializedDefaultValue ?? \"\").includes(\",\") ? 2 : 1\n---\n\n\n
\n
\n {\n Array.from({ length: thumbCount }).map(() => (\n
\n ))\n }\n
\n
\n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype SliderValue = number | [number, number]\ntype ThumbAlignment = \"center\" | \"edge\" | \"edge-client-only\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n defaultValue?: SliderValue\n min?: number\n max?: number\n step?: number\n largeStep?: number\n orientation?: \"horizontal\" | \"vertical\"\n thumbAlignment?: ThumbAlignment\n disabled?: boolean\n}\n\nconst {\n class: className,\n defaultValue,\n min,\n max,\n step,\n largeStep,\n orientation = \"horizontal\",\n thumbAlignment = \"edge\",\n disabled,\n ...props\n} = Astro.props\n\nconst serializedDefaultValue = Array.isArray(defaultValue)\n ? defaultValue.join(\",\")\n : defaultValue\nconst thumbCount = String(serializedDefaultValue ?? \"\").includes(\",\") ? 2 : 1\n---\n\n\n
\n
\n {\n Array.from({ length: thumbCount }).map(() => (\n
\n ))\n }\n
\n
\n\n\n",
"type": "registry:ui"
},
{
diff --git a/public/r/switch.json b/public/r/switch.json
index 413b52ac5..8395a7beb 100644
--- a/public/r/switch.json
+++ b/public/r/switch.json
@@ -4,7 +4,7 @@
"title": "Switch",
"description": "A control that allows the user to toggle between checked and not checked.",
"dependencies": [
- "@data-slot/switch@^1.0.1"
+ "@data-slot/switch@^1.0.2"
],
"files": [
{
diff --git a/public/r/tabs.json b/public/r/tabs.json
index de8867333..65aff29da 100644
--- a/public/r/tabs.json
+++ b/public/r/tabs.json
@@ -4,7 +4,7 @@
"title": "Tabs",
"description": "A set of layered sections of content, known as tabs, that display one panel of content at a time.",
"dependencies": [
- "@data-slot/tabs@^1.0.1"
+ "@data-slot/tabs@^1.0.2"
],
"files": [
{
diff --git a/public/r/toast.json b/public/r/toast.json
new file mode 100644
index 000000000..82e6bd53b
--- /dev/null
+++ b/public/r/toast.json
@@ -0,0 +1,80 @@
+{
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
+ "name": "toast",
+ "title": "Toast",
+ "description": "A brief notification that appears without interrupting the user.",
+ "dependencies": [
+ "@data-slot/toast@^1.0.2",
+ "@lucide/astro"
+ ],
+ "registryDependencies": [
+ "@fulldev/button"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/toast/index.ts",
+ "content": "export { default as Toast } from \"./toast.astro\"\nexport { default as ToastTemplate } from \"./toast-template.astro\"\nexport { default as ToastViewport } from \"./toast-viewport.astro\"\nexport { default as ToastItem } from \"./toast-item.astro\"\nexport { default as ToastContent } from \"./toast-content.astro\"\nexport { default as ToastIcon } from \"./toast-icon.astro\"\nexport { default as ToastTitle } from \"./toast-title.astro\"\nexport { default as ToastDescription } from \"./toast-description.astro\"\nexport { default as ToastAction } from \"./toast-action.astro\"\nexport { default as ToastClose } from \"./toast-close.astro\"\nexport { default as Toaster } from \"./toaster.astro\"\n\nexport type {\n ToastActionEvent,\n ToastClearableField,\n ToastController,\n ToastOptions,\n ToastPosition,\n ToastPromiseErrorValue,\n ToastPromiseHandle,\n ToastPromiseOptions,\n ToastPromiseState,\n ToastPromiseStateValue,\n ToastShowOptions,\n ToastUpdateOptions,\n} from \"@data-slot/toast\"\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-action.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } from \"@/components/ui/button\"\n\ntype Props = HTMLAttributes<\"button\">\n\nconst {\n class: className,\n hidden = true,\n type = \"button\",\n ...props\n} = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-close.astro",
+ "content": "---\nimport type { ComponentProps } from \"astro/types\"\nimport XIcon from \"@lucide/astro/icons/x\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\n\ntype Props = ComponentProps\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n \n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-content.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-description.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, hidden = true, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-icon.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport CircleCheckIcon from \"@lucide/astro/icons/circle-check\"\nimport InfoIcon from \"@lucide/astro/icons/info\"\nimport LoaderIcon from \"@lucide/astro/icons/loader-circle\"\nimport OctagonXIcon from \"@lucide/astro/icons/octagon-x\"\nimport TriangleAlertIcon from \"@lucide/astro/icons/triangle-alert\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"span\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n \n \n \n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-item.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"li\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n*]:opacity-0\",\n className\n )}\n {...props}\n>\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-template.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-title.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"div\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n
\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-viewport.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Props = HTMLAttributes<\"ol\">\n\nconst { class: className, ...props } = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\nimport type { ToastPosition } from \"@data-slot/toast\"\n\ntype Props = HTMLAttributes<\"div\"> & {\n limit?: number\n duration?: number\n position?: ToastPosition\n pauseOnHover?: boolean\n pauseOnFocus?: boolean\n portal?: boolean\n}\n\nconst {\n class: className,\n limit,\n duration,\n position,\n pauseOnHover,\n pauseOnFocus,\n portal,\n ...props\n} = Astro.props\n---\n\n\n \n
\n\n\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toaster.astro",
+ "content": "---\nimport type { ComponentProps } from \"astro/types\"\n\nimport ToastAction from \"./toast-action.astro\"\nimport ToastClose from \"./toast-close.astro\"\nimport ToastContent from \"./toast-content.astro\"\nimport ToastDescription from \"./toast-description.astro\"\nimport ToastIcon from \"./toast-icon.astro\"\nimport ToastItem from \"./toast-item.astro\"\nimport ToastTemplate from \"./toast-template.astro\"\nimport ToastTitle from \"./toast-title.astro\"\nimport ToastViewport from \"./toast-viewport.astro\"\nimport Toast from \"./toast.astro\"\n\ntype Props = ComponentProps & {\n viewportClass?: string\n}\n\nconst { viewportClass, ...props } = Astro.props\n---\n\n\n \n \n \n \n \n \n \n
\n \n \n \n \n \n \n \n",
+ "type": "registry:ui"
+ }
+ ],
+ "docs": "https://ui.full.dev/components/toast/",
+ "categories": [
+ "ui"
+ ],
+ "type": "registry:ui"
+}
\ No newline at end of file
diff --git a/public/r/toggle-group.json b/public/r/toggle-group.json
new file mode 100644
index 000000000..037f2c0f3
--- /dev/null
+++ b/public/r/toggle-group.json
@@ -0,0 +1,34 @@
+{
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
+ "name": "toggle-group",
+ "title": "Toggle Group",
+ "description": "A set of two-state buttons that can be toggled independently or as a single choice.",
+ "dependencies": [
+ "@data-slot/toggle-group@^1.0.2"
+ ],
+ "registryDependencies": [
+ "@fulldev/toggle"
+ ],
+ "files": [
+ {
+ "path": "src/components/ui/toggle-group/index.ts",
+ "content": "export { default as ToggleGroup } from \"./toggle-group.astro\"\nexport { default as ToggleGroupItem } from \"./toggle-group-item.astro\"\n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toggle-group/toggle-group-item.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\nimport {\n toggleVariants,\n type ToggleVariantProps,\n} from \"@/components/ui/toggle/toggle-variants\"\n\ntype Props = HTMLAttributes<\"button\"> &\n ToggleVariantProps & {\n value: string\n disabled?: boolean\n }\n\nconst {\n class: className,\n value,\n disabled,\n variant = \"default\",\n size = \"default\",\n type = \"button\",\n ...props\n} = Astro.props\n---\n\n\n \n \n",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toggle-group/toggle-group.astro",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\nimport type { ToggleVariantProps } from \"@/components/ui/toggle/toggle-variants\"\n\ntype Props = HTMLAttributes<\"div\"> &\n ToggleVariantProps & {\n defaultValue?: string | string[]\n multiple?: boolean\n orientation?: \"horizontal\" | \"vertical\"\n loop?: boolean\n disabled?: boolean\n spacing?: number\n }\n\nconst {\n class: className,\n style,\n defaultValue,\n multiple,\n orientation = \"horizontal\",\n loop,\n disabled,\n variant,\n size,\n spacing = 2,\n ...props\n} = Astro.props\n\nconst serializedDefaultValue = Array.isArray(defaultValue)\n ? defaultValue.join(\" \")\n : defaultValue\n\nconst resolvedStyle =\n typeof style === \"string\"\n ? `--gap: ${spacing}; ${style}`\n : { \"--gap\": spacing, ...(style ?? {}) }\n---\n\n[data-slot=toggle-group-item]:first-child]:rounded-l-md [&[data-orientation=horizontal][data-spacing='0']>[data-slot=toggle-group-item]:last-child]:rounded-r-md [&[data-orientation=horizontal][data-spacing='0'][data-variant=outline]>[data-slot=toggle-group-item]:not(:first-child)]:border-l-0 [&[data-orientation=vertical][data-spacing='0']>[data-slot=toggle-group-item]:first-child]:rounded-t-md [&[data-orientation=vertical][data-spacing='0']>[data-slot=toggle-group-item]:last-child]:rounded-b-md [&[data-orientation=vertical][data-spacing='0'][data-variant=outline]>[data-slot=toggle-group-item]:not(:first-child)]:border-t-0 [&[data-spacing='0']>[data-slot=toggle-group-item]]:rounded-none [&[data-spacing='0']>[data-slot=toggle-group-item]]:px-2 [&[data-spacing='0']>[data-slot=toggle-group-item]]:shadow-none [&[data-spacing='0']>[data-slot=toggle-group-item]:has([data-icon=inline-end])]:pr-1.5 [&[data-spacing='0']>[data-slot=toggle-group-item]:has([data-icon=inline-start])]:pl-1.5\",\n className\n )}\n {...props}\n>\n \n
\n\n\n",
+ "type": "registry:ui"
+ }
+ ],
+ "docs": "https://ui.full.dev/components/toggle-group/",
+ "categories": [
+ "ui"
+ ],
+ "type": "registry:ui"
+}
\ No newline at end of file
diff --git a/public/r/toggle.json b/public/r/toggle.json
index f634f3eb7..f47bc46d5 100644
--- a/public/r/toggle.json
+++ b/public/r/toggle.json
@@ -4,7 +4,7 @@
"title": "Toggle",
"description": "A two-state button that can be either on or off.",
"dependencies": [
- "@data-slot/toggle@^1.0.1"
+ "@data-slot/toggle@^1.0.2"
],
"files": [
{
diff --git a/public/r/tooltip.json b/public/r/tooltip.json
index ce5107bee..df89f42e7 100644
--- a/public/r/tooltip.json
+++ b/public/r/tooltip.json
@@ -4,7 +4,7 @@
"title": "Tooltip",
"description": "Displays contextual information when a user hovers or focuses a trigger.",
"dependencies": [
- "@data-slot/tooltip@^1.0.1"
+ "@data-slot/tooltip@^1.0.2"
],
"files": [
{
diff --git a/public/r/typography.json b/public/r/typography.json
index 09b979048..6fc564add 100644
--- a/public/r/typography.json
+++ b/public/r/typography.json
@@ -6,88 +6,93 @@
"files": [
{
"path": "src/components/ui/typography/typography.astro",
- "content": "---\nimport type { HTMLTag, Polymorphic } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = Polymorphic<{ as: Tag; size?: Size }>\n\nconst {\n as: Tag = \"div\",\n class: className,\n size = \"default\",\n ...props\n} = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLTag, Polymorphic } from \"astro/types\"\n\nimport \"./typeset.css\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = Polymorphic<{ as: Tag; size?: Size }>\n\nconst {\n as: Tag = \"div\",\n class: className,\n size = \"default\",\n ...props\n} = Astro.props\n\nconst sizeClass =\n size === \"sm\"\n ? \"[--typeset-flow:1.125em] [--typeset-leading:1.7] [--typeset-size:0.875rem]\"\n : size === \"lg\"\n ? \"[--typeset-flow:1.5em] [--typeset-leading:1.8] [--typeset-size:1.125rem]\"\n : \"[--typeset-flow:1.25em] [--typeset-leading:1.75] [--typeset-size:1rem]\"\n---\n\n\n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-a.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"a\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"a\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-sm\" : size === \"lg\" ? \"text-lg\" : \"text-base\"\n---\n\n\n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-blockquote.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"blockquote\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"blockquote\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-sm\" : size === \"lg\" ? \"text-lg\" : \"text-base\"\n---\n\n\n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-h1.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"h1\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"h1\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-3xl\" : size === \"lg\" ? \"text-5xl\" : \"text-4xl\"\n---\n\n\n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-h2.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"h2\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"h2\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-2xl\" : size === \"lg\" ? \"text-4xl\" : \"text-3xl\"\n---\n\n\n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-h3.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"h3\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"h3\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-xl\" : size === \"lg\" ? \"text-3xl\" : \"text-2xl\"\n---\n\n\n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-h4.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"h4\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"h4\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-lg\" : size === \"lg\" ? \"text-2xl\" : \"text-xl\"\n---\n\n\n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-inline-code.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"code\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n\n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"code\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-xs\" : size === \"lg\" ? \"text-base\" : \"text-sm\"\n---\n\n\n \n\n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-lead.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"p\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n
\n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"p\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-base\" : size === \"lg\" ? \"text-xl\" : \"text-lg\"\n---\n\n\n \n
\n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-list.astro",
- "content": "---\nimport type { HTMLTag, Polymorphic } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = Polymorphic<{ as: Tag; size?: Size }>\n\nconst {\n as: Tag = \"ul\",\n class: className,\n size = \"default\",\n ...props\n} = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { Polymorphic } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = Polymorphic<{ as: Tag; size?: Size }>\n\nconst {\n as: Tag = \"ul\",\n class: className,\n size = \"default\",\n ...props\n} = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-sm\" : size === \"lg\" ? \"text-lg\" : \"text-base\"\n---\n\n\n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-list-item.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"li\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"li\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-sm\" : size === \"lg\" ? \"text-lg\" : \"text-base\"\n---\n\n\n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-p.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"p\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n
\n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"p\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-sm\" : size === \"lg\" ? \"text-lg\" : \"text-base\"\n---\n\n\n \n
\n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-table.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"table\"> & {\n containerClass?: string\n size?: Size\n}\n\nconst {\n class: className,\n containerClass,\n size = \"default\",\n ...props\n} = Astro.props\n---\n\n\n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"table\"> & {\n containerClass?: string\n size?: Size\n}\n\nconst {\n class: className,\n containerClass,\n size = \"default\",\n ...props\n} = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-sm\" : size === \"lg\" ? \"text-lg\" : \"text-base\"\n---\n\n\n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-table-row.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"tr\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"tr\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-sm\" : size === \"lg\" ? \"text-lg\" : \"text-base\"\n---\n\n\n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-table-head.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"th\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"th\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-sm\" : size === \"lg\" ? \"text-lg\" : \"text-base\"\n---\n\n\n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/typography-table-cell.astro",
- "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"td\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n---\n\n\n \n \n\n\n",
+ "content": "---\nimport type { HTMLAttributes } from \"astro/types\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype Size = \"sm\" | \"default\" | \"lg\"\ntype Props = HTMLAttributes<\"td\"> & {\n size?: Size\n}\n\nconst { class: className, size = \"default\", ...props } = Astro.props\n\nconst sizeClass =\n size === \"sm\" ? \"text-sm\" : size === \"lg\" ? \"text-lg\" : \"text-base\"\n---\n\n\n \n \n",
"type": "registry:ui"
},
{
"path": "src/components/ui/typography/index.ts",
"content": "export { default as Typography } from \"./typography.astro\"\nexport { default as TypographyA } from \"./typography-a.astro\"\nexport { default as TypographyBlockquote } from \"./typography-blockquote.astro\"\nexport { default as TypographyH1 } from \"./typography-h1.astro\"\nexport { default as TypographyH2 } from \"./typography-h2.astro\"\nexport { default as TypographyH3 } from \"./typography-h3.astro\"\nexport { default as TypographyH4 } from \"./typography-h4.astro\"\nexport { default as TypographyInlineCode } from \"./typography-inline-code.astro\"\nexport { default as TypographyLead } from \"./typography-lead.astro\"\nexport { default as TypographyList } from \"./typography-list.astro\"\nexport { default as TypographyListItem } from \"./typography-list-item.astro\"\nexport { default as TypographyP } from \"./typography-p.astro\"\nexport { default as TypographyTable } from \"./typography-table.astro\"\nexport { default as TypographyTableCell } from \"./typography-table-cell.astro\"\nexport { default as TypographyTableHead } from \"./typography-table-head.astro\"\nexport { default as TypographyTableRow } from \"./typography-table-row.astro\"\n",
"type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/typography/typeset.css",
+ "content": "/*\n * shadcn/typeset\n * https://ui.shadcn.com/docs/typeset.\n */\n\n@layer components {\n .typeset {\n --typeset-font-body: inherit;\n --typeset-font-heading: var(--font-heading);\n --typeset-font-mono: var(--font-mono);\n --typeset-size: 1em;\n --typeset-leading: 1.75;\n --typeset-flow: 1.25em;\n }\n}\n\n@layer components {\n .typeset {\n font-family: var(--typeset-font-body);\n font-size: calc(var(--typeset-size) * 1.125);\n line-height: var(--typeset-leading);\n color: var(--color-foreground, currentColor);\n overflow-wrap: break-word;\n margin-trim: block-start;\n\n @media (min-width: 48rem), print {\n font-size: var(--typeset-size);\n }\n\n --typeset-muted: var(\n --color-muted-foreground,\n color-mix(in oklab, currentColor 60%, transparent)\n );\n --typeset-rule: var(\n --color-border,\n color-mix(in oklab, currentColor 20%, transparent)\n );\n }\n\n .typeset\n *:not(\n :where(\n .not-typeset,\n [data-not-typeset],\n .not-typeset *,\n [data-not-typeset] *\n )\n ) {\n &:where(p) {\n margin-block-start: var(--typeset-flow);\n margin-block-end: 0;\n }\n &:where(h1, h2, h3, h4, h5, h6) {\n color: var(--color-foreground, currentColor);\n font-family: var(--typeset-font-heading);\n font-weight: 600;\n margin-block-end: 0;\n }\n &:where(h1) {\n font-size: 1.75em;\n line-height: 1.3;\n margin-block-start: var(--typeset-flow);\n }\n &:where(h2) {\n font-size: 1.25em;\n line-height: 1.4;\n margin-block-start: calc(var(--typeset-flow) * 1.4);\n }\n &:where(h3) {\n font-size: 1.125em;\n line-height: 1.45;\n margin-block-start: var(--typeset-flow);\n }\n &:where(h4) {\n font-size: 1em;\n line-height: 1.5;\n margin-block-start: var(--typeset-flow);\n }\n &:where(h5) {\n font-size: 0.875em;\n line-height: 1.5;\n font-weight: 500;\n color: var(--typeset-muted);\n margin-block-start: calc(var(--typeset-flow) / 0.875);\n }\n &:where(h6) {\n font-size: 0.8125em;\n line-height: 1.5;\n font-weight: 500;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--typeset-muted);\n margin-block-start: calc(var(--typeset-flow) / 0.8125);\n }\n &:where([id]) {\n scroll-margin-block-start: var(--typeset-flow);\n }\n &:where(h1 + *, h2 + *, h3 + *, h4 + *, h5 + *, h6 + *) {\n margin-block-start: 1em;\n }\n &:where(:is(h1, h2, h3, h4) :is(code)) {\n font-size: 0.9em;\n }\n &:where(a) {\n color: inherit;\n font-weight: 500;\n text-decoration-line: underline;\n text-decoration-color: color-mix(in oklab, currentColor 30%, transparent);\n }\n &:where(a:hover) {\n text-decoration-color: currentColor;\n }\n &:where(a:focus-visible) {\n outline: 2px solid var(--color-ring, currentColor);\n outline-offset: 2px;\n border-radius: 0.125em;\n }\n &:where(:is(h1, h2, h3, h4, h5, h6) :is(a)) {\n font-weight: inherit;\n }\n &:where(strong, b) {\n font-weight: 600;\n }\n &:where(:is(h1, h2, h3, h4) :is(strong, b)) {\n font-weight: 600;\n }\n &:where(mark) {\n background-color: color-mix(\n in oklab,\n oklch(0.86 0.17 95) 40%,\n transparent\n );\n color: inherit;\n padding: 0.05em 0.15em;\n border-radius: 0.2em;\n }\n &:where(abbr[title]) {\n text-decoration-line: underline;\n text-decoration-style: dotted;\n text-underline-offset: 0.2em;\n cursor: help;\n }\n &:where(del, s) {\n color: var(--typeset-muted);\n text-decoration-line: line-through;\n }\n &:where(sup, sub) {\n font-size: 0.75em;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n &:where(sup) {\n top: -0.5em;\n }\n &:where(sub) {\n bottom: -0.25em;\n }\n &:where(sup a) {\n text-decoration-line: none;\n font-weight: 500;\n }\n &:where(ul) {\n list-style-type: disc;\n }\n &:where(ol) {\n list-style-type: decimal;\n }\n &:where(ul ul) {\n list-style-type: circle;\n }\n &:where(ul ul ul) {\n list-style-type: square;\n }\n &:where(ol[type=\"a\" i]) {\n list-style-type: lower-alpha;\n }\n &:where(ol[type=\"i\" i]) {\n list-style-type: lower-roman;\n }\n &:where(ol[type=\"A\" s]) {\n list-style-type: upper-alpha;\n }\n &:where(ol[type=\"I\" s]) {\n list-style-type: upper-roman;\n }\n &:where(ul, ol) {\n margin-block-start: var(--typeset-flow);\n margin-block-end: 0;\n padding-inline-start: 1.5em;\n }\n &:where(li) {\n margin-block-start: 0.5em;\n padding-inline-start: 0.4em;\n }\n &:where(li > p, li > ul, li > ol) {\n margin-block-start: 0.5em;\n }\n &:where(ul > li)::marker,\n &:where(ol > li)::marker {\n color: var(--typeset-muted);\n }\n &:where(ul.contains-task-list) {\n list-style-type: none;\n padding-inline-start: 0.25em;\n }\n &:where(li.task-list-item > input[type=\"checkbox\"]) {\n margin-inline-end: 0.5em;\n vertical-align: -0.1em;\n accent-color: var(--color-primary, currentColor);\n }\n &:where(details) {\n margin-block-start: var(--typeset-flow);\n margin-block-end: 0;\n }\n &:where(summary) {\n cursor: pointer;\n font-weight: 500;\n }\n &:where(summary)::marker {\n color: var(--typeset-muted);\n }\n &:where(kbd) {\n font-family: inherit;\n font-size: 0.85em;\n font-weight: 500;\n border: 1px solid var(--typeset-rule);\n border-block-end-width: 2px;\n border-radius: min(calc(var(--radius, 0.5em) * 0.6), 0.35em);\n padding: 0.0625em 0.35em;\n }\n &:where(dl) {\n margin-block-start: var(--typeset-flow);\n margin-block-end: 0;\n }\n &:where(dt) {\n font-weight: 500;\n margin-block-start: 1em;\n }\n &:where(dt + dt) {\n margin-block-start: 0.25em;\n }\n &:where(dd) {\n margin-block-start: 0.25em;\n margin-inline-start: 0;\n padding-inline-start: 1em;\n color: var(--typeset-muted);\n }\n &:where(:not(pre) > code) {\n background-color: var(\n --color-muted,\n color-mix(in oklab, currentColor 8%, transparent)\n );\n font-family: var(--typeset-font-mono);\n font-size: 0.85em;\n border-radius: min(calc(var(--radius, 0.5em) * 0.6), 0.35em);\n padding: 0.125em 0.3em;\n }\n &:where(pre) {\n background-color: var(\n --color-muted,\n color-mix(in oklab, currentColor 8%, transparent)\n );\n font-family: var(--typeset-font-mono);\n font-size: 0.875em;\n line-height: 1.5;\n tab-size: 2;\n direction: ltr;\n border-radius: var(--radius, 0.5em);\n padding: 0.75em 1em;\n overflow-x: auto;\n margin-block-start: calc(var(--typeset-flow) / 0.875);\n margin-block-end: 0;\n }\n &:where(pre code) {\n background-color: transparent;\n font-family: inherit;\n font-size: inherit;\n padding: 0;\n border-radius: 0;\n }\n &:where(blockquote) {\n border-inline-start: 2px solid var(--typeset-rule);\n padding-inline-start: 1em;\n margin-block-start: var(--typeset-flow);\n margin-block-end: 0;\n margin-inline: 0;\n }\n &:where(hr) {\n border: 0;\n border-block-start: 1px solid var(--typeset-rule);\n margin-block-start: calc(var(--typeset-flow) * 2.4);\n margin-block-end: 0;\n }\n &:where(hr + h1, hr + h2, hr + h3, hr + h4) {\n margin-block-start: var(--typeset-flow);\n }\n &:where(.footnotes, [data-footnotes]) {\n margin-block-start: calc(var(--typeset-flow) * 2);\n border-block-start: 1px solid var(--typeset-rule);\n padding-block-start: var(--typeset-flow);\n font-size: 0.875em;\n color: var(--typeset-muted);\n }\n &:where(math[display=\"block\"]) {\n margin-block-start: var(--typeset-flow);\n margin-block-end: 0;\n overflow-x: auto;\n overflow-y: hidden;\n padding-block: 0.25em;\n }\n &:where(img, video) {\n border-radius: var(--radius, 0.5em);\n max-width: 100%;\n height: auto;\n margin-block-start: var(--typeset-flow);\n margin-block-end: 0;\n }\n &:where(p img) {\n margin-block-start: 0;\n }\n &:where(figure) {\n margin-block-start: var(--typeset-flow);\n margin-block-end: 0;\n margin-inline: 0;\n }\n &:where(figcaption, caption) {\n color: var(--typeset-muted);\n font-size: 0.875em;\n text-align: center;\n margin-block-start: calc(0.75em / 0.875);\n }\n &:where(caption) {\n caption-side: bottom;\n }\n &:where(table) {\n max-width: 100%;\n font-size: 1em;\n line-height: 1.5;\n font-variant-numeric: tabular-nums;\n border-collapse: separate;\n border-spacing: 0;\n border-block-end: 1px solid var(--typeset-rule);\n margin-block-start: var(--typeset-flow);\n margin-block-end: 0;\n }\n &:where(.typeset-scroll) {\n overflow-x: auto;\n margin-block-start: var(--typeset-flow);\n }\n &:where(.typeset-scroll > *) {\n margin-block-start: 0;\n }\n &:where(.typeset-scroll table) {\n width: max-content;\n max-width: none;\n }\n &:where(thead th) {\n font-weight: 500;\n text-align: start;\n white-space: nowrap;\n padding: 0.65em 1em;\n }\n &:where(:is(tbody, tfoot) :is(td, th)) {\n padding: 0.75em 1em;\n text-align: start;\n vertical-align: top;\n border-block-start: 1px solid var(--typeset-rule);\n }\n &:where(tbody th, tfoot th) {\n font-weight: 500;\n }\n &:where(th:first-child, td:first-child) {\n padding-inline-start: 0;\n }\n &:where(th[align=\"center\"], td[align=\"center\"]) {\n text-align: center;\n }\n &:where(th[align=\"right\"], td[align=\"right\"]) {\n text-align: end;\n }\n &:where(li > blockquote, li > table, li > figure) {\n margin-block-start: 0.5em;\n }\n &:where(li > pre) {\n margin-block-start: calc(0.5em / 0.875);\n }\n @media print {\n &:where(pre, table, blockquote, figure) {\n break-inside: avoid;\n }\n &:where(h1, h2, h3, h4) {\n break-after: avoid;\n }\n }\n @media (forced-colors: active) {\n &:where(:not(pre) > code) {\n border: 1px solid;\n }\n }\n }\n\n .typeset\n > :where(:first-child):not(\n :where(\n .not-typeset,\n [data-not-typeset],\n .not-typeset *,\n [data-not-typeset] *\n )\n ),\n .typeset\n > :where(:first-child)\n > :where(:first-child):not(\n :where(\n .not-typeset,\n [data-not-typeset],\n .not-typeset *,\n [data-not-typeset] *\n )\n ),\n .typeset\n :where(\n li > :first-child,\n blockquote > :first-child,\n td > :first-child,\n th > :first-child,\n dd > :first-child,\n figure > :first-child,\n figure > picture > img\n ):not(\n :where(\n .not-typeset,\n [data-not-typeset],\n .not-typeset *,\n [data-not-typeset] *\n )\n ) {\n margin-block-start: 0;\n }\n}\n",
+ "type": "registry:ui"
}
],
"docs": "https://ui.full.dev/components/typography/",
diff --git a/registry.json b/registry.json
index 269e38119..673508033 100644
--- a/registry.json
+++ b/registry.json
@@ -10,7 +10,7 @@
"description": "A vertically stacked set of interactive headings that each reveal a section of content.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/accordion/",
- "dependencies": ["@data-slot/accordion@^1.0.1", "@lucide/astro"],
+ "dependencies": ["@data-slot/accordion@^1.0.2", "@lucide/astro"],
"files": [
{
"path": "src/components/ui/accordion/accordion.astro",
@@ -67,7 +67,7 @@
"description": "A modal dialog for important confirmations that expects a response.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/alert-dialog/",
- "dependencies": ["@data-slot/alert-dialog@^1.0.1"],
+ "dependencies": ["@data-slot/alert-dialog@^1.0.2"],
"registryDependencies": ["@fulldev/button"],
"files": [
{
@@ -327,7 +327,7 @@
"description": "An interactive component which expands/collapses a panel.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/collapsible/",
- "dependencies": ["@data-slot/collapsible@^1.0.1"],
+ "dependencies": ["@data-slot/collapsible@^1.0.2"],
"files": [
{
"path": "src/components/ui/collapsible/collapsible.astro",
@@ -355,8 +355,8 @@
"categories": ["ui"],
"docs": "https://ui.full.dev/components/combobox/",
"dependencies": [
- "@data-slot/combobox@^1.0.1",
- "@data-slot/core@^1.0.1",
+ "@data-slot/combobox@^1.0.2",
+ "@data-slot/core@^1.0.2",
"@lucide/astro"
],
"registryDependencies": ["@fulldev/input-group"],
@@ -419,9 +419,9 @@
"categories": ["ui"],
"docs": "https://ui.full.dev/components/command/",
"dependencies": [
- "@data-slot/command@^1.0.1",
+ "@data-slot/command@^1.0.2",
"@lucide/astro",
- "@data-slot/core@^1.0.1"
+ "@data-slot/core@^1.0.2"
],
"registryDependencies": ["@fulldev/dialog"],
"files": [
@@ -474,7 +474,7 @@
"description": "A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/dialog/",
- "dependencies": ["@data-slot/dialog@^1.0.1", "@lucide/astro"],
+ "dependencies": ["@data-slot/dialog@^1.0.2", "@lucide/astro"],
"registryDependencies": ["@fulldev/button"],
"files": [
{
@@ -530,7 +530,7 @@
"description": "Displays a menu to the user, such as a set of actions or functions, triggered by a button.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/dropdown-menu/",
- "dependencies": ["@data-slot/dropdown-menu@^1.0.1", "@lucide/astro"],
+ "dependencies": ["@data-slot/dropdown-menu@^1.0.2", "@lucide/astro"],
"files": [
{
"path": "src/components/ui/dropdown-menu/dropdown-menu.astro",
@@ -725,8 +725,8 @@
"categories": ["ui"],
"docs": "https://ui.full.dev/components/hover-card/",
"dependencies": [
- "@data-slot/hover-card@^1.0.1",
- "@data-slot/core@^1.0.1"
+ "@data-slot/hover-card@^1.0.2",
+ "@data-slot/core@^1.0.2"
],
"files": [
{
@@ -981,10 +981,10 @@
"name": "carousel",
"type": "registry:ui",
"title": "Carousel",
- "description": "A carousel with motion and swipe built using Embla.",
+ "description": "An accessible carousel built on native scrolling with Data Slot.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/carousel/",
- "dependencies": ["embla-carousel", "@lucide/astro"],
+ "dependencies": ["@data-slot/carousel@^1.0.2", "@lucide/astro"],
"registryDependencies": ["@fulldev/button"],
"files": [
{
@@ -1020,7 +1020,7 @@
"description": "A collection of links for navigating websites.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/navigation-menu/",
- "dependencies": ["@data-slot/navigation-menu@^1.0.1", "@lucide/astro"],
+ "dependencies": ["@data-slot/navigation-menu@^1.0.2", "@lucide/astro"],
"files": [
{
"path": "src/components/ui/navigation-menu/navigation-menu.astro",
@@ -1098,7 +1098,7 @@
"description": "Displays rich content in a floating layer, triggered by a button.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/popover/",
- "dependencies": ["@data-slot/popover@^1.0.1"],
+ "dependencies": ["@data-slot/popover@^1.0.2"],
"files": [
{
"path": "src/components/ui/popover/popover.astro",
@@ -1167,7 +1167,7 @@
"description": "A set of checkable buttons, known as radio buttons, where no more than one of the buttons can be checked at a time.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/radio-group/",
- "dependencies": ["@data-slot/radio-group@^1.0.1"],
+ "dependencies": ["@data-slot/radio-group@^1.0.2"],
"files": [
{
"path": "src/components/ui/radio-group/radio-group.astro",
@@ -1209,7 +1209,7 @@
"description": "Displays a list of options for the user to pick from, triggered by a button.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/select/",
- "dependencies": ["@data-slot/select@^1.0.1", "@lucide/astro"],
+ "dependencies": ["@data-slot/select@^1.0.2", "@lucide/astro"],
"files": [
{
"path": "src/components/ui/select/select.astro",
@@ -1304,7 +1304,7 @@
"description": "A sliding panel component that appears from the edge of the screen.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/sheet/",
- "dependencies": ["@data-slot/dialog@^1.0.1", "@lucide/astro"],
+ "dependencies": ["@data-slot/dialog@^1.0.2", "@lucide/astro"],
"registryDependencies": ["@fulldev/button", "@fulldev/dialog"],
"files": [
{
@@ -1352,7 +1352,7 @@
"description": "A composable, themeable, and customizable Astro sidebar component.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/sidebar/",
- "dependencies": ["@data-slot/tooltip@^1.0.1", "@lucide/astro"],
+ "dependencies": ["@data-slot/tooltip@^1.0.2", "@lucide/astro"],
"registryDependencies": [
"@fulldev/layout",
"@fulldev/button",
@@ -1468,7 +1468,7 @@
"description": "An input where the user selects a value from within a given range.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/slider/",
- "dependencies": ["@data-slot/slider@^1.0.1"],
+ "dependencies": ["@data-slot/slider@^1.0.2"],
"files": [
{
"path": "src/components/ui/slider/slider.astro",
@@ -1524,7 +1524,7 @@
"description": "A control that allows the user to toggle between checked and not checked.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/switch/",
- "dependencies": ["@data-slot/switch@^1.0.1"],
+ "dependencies": ["@data-slot/switch@^1.0.2"],
"files": [
{
"path": "src/components/ui/switch/switch.astro",
@@ -1589,7 +1589,7 @@
"description": "A set of layered sections of content, known as tabs, that display one panel of content at a time.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/tabs/",
- "dependencies": ["@data-slot/tabs@^1.0.1"],
+ "dependencies": ["@data-slot/tabs@^1.0.2"],
"files": [
{
"path": "src/components/ui/tabs/tabs.astro",
@@ -1658,7 +1658,7 @@
"description": "A two-state button that can be either on or off.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/toggle/",
- "dependencies": ["@data-slot/toggle@^1.0.1"],
+ "dependencies": ["@data-slot/toggle@^1.0.2"],
"files": [
{
"path": "src/components/ui/toggle/toggle.astro",
@@ -1699,7 +1699,7 @@
"description": "Displays contextual information when a user hovers or focuses a trigger.",
"categories": ["ui"],
"docs": "https://ui.full.dev/components/tooltip/",
- "dependencies": ["@data-slot/tooltip@^1.0.1"],
+ "dependencies": ["@data-slot/tooltip@^1.0.2"],
"files": [
{
"path": "src/components/ui/tooltip/tooltip.astro",
@@ -1794,6 +1794,10 @@
{
"path": "src/components/ui/typography/index.ts",
"type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/typography/typeset.css",
+ "type": "registry:ui"
}
]
},
@@ -1815,6 +1819,345 @@
}
]
},
+ {
+ "name": "drawer",
+ "type": "registry:ui",
+ "title": "Drawer",
+ "description": "A swipeable panel that opens from an edge of the screen.",
+ "categories": ["ui"],
+ "docs": "https://ui.full.dev/components/drawer/",
+ "dependencies": ["@data-slot/drawer@^1.0.2"],
+ "registryDependencies": ["@fulldev/button"],
+ "files": [
+ {
+ "path": "src/components/ui/drawer/drawer-close.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-content.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-description.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-footer.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-header.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-indent-background.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-indent.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-overlay.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-popup.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-portal.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-provider.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-swipe-handle.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-title.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-trigger.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-viewport.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer-virtual-keyboard-provider.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/drawer.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/drawer/index.ts",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "resizable",
+ "type": "registry:ui",
+ "title": "Resizable",
+ "description": "Accessible panel groups with pointer and keyboard resizing.",
+ "categories": ["ui"],
+ "docs": "https://ui.full.dev/components/resizable/",
+ "dependencies": ["@data-slot/resizable@^1.0.2"],
+ "files": [
+ {
+ "path": "src/components/ui/resizable/index.ts",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/resizable/resizable-handle.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/resizable/resizable-panel.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/resizable/resizable.astro",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "toast",
+ "type": "registry:ui",
+ "title": "Toast",
+ "description": "A brief notification that appears without interrupting the user.",
+ "categories": ["ui"],
+ "docs": "https://ui.full.dev/components/toast/",
+ "dependencies": ["@data-slot/toast@^1.0.2", "@lucide/astro"],
+ "registryDependencies": ["@fulldev/button"],
+ "files": [
+ {
+ "path": "src/components/ui/toast/index.ts",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-action.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-close.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-content.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-description.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-icon.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-item.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-template.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-title.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast-viewport.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toast.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toast/toaster.astro",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "toggle-group",
+ "type": "registry:ui",
+ "title": "Toggle Group",
+ "description": "A set of two-state buttons that can be toggled independently or as a single choice.",
+ "categories": ["ui"],
+ "docs": "https://ui.full.dev/components/toggle-group/",
+ "dependencies": ["@data-slot/toggle-group@^1.0.2"],
+ "registryDependencies": ["@fulldev/toggle"],
+ "files": [
+ {
+ "path": "src/components/ui/toggle-group/index.ts",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toggle-group/toggle-group-item.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/toggle-group/toggle-group.astro",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "attachment",
+ "type": "registry:ui",
+ "title": "Attachment",
+ "description": "Displays a file or image attachment with media, metadata, state, and actions.",
+ "categories": ["ui"],
+ "docs": "https://ui.full.dev/components/attachment/",
+ "registryDependencies": ["@fulldev/button"],
+ "files": [
+ {
+ "path": "src/components/ui/attachment/attachment-action.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-actions.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-content.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-description.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-group.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-media.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-title.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment-trigger.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/attachment.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/attachment/index.ts",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "button-group",
+ "type": "registry:ui",
+ "title": "Button Group",
+ "description": "Groups related controls with connected edges and consistent focus behavior.",
+ "categories": ["ui"],
+ "docs": "https://ui.full.dev/components/button-group/",
+ "registryDependencies": ["@fulldev/separator"],
+ "files": [
+ {
+ "path": "src/components/ui/button-group/button-group-separator.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/button-group-text.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/button-group-variants.ts",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/button-group.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/button-group/index.ts",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "pagination",
+ "type": "registry:ui",
+ "title": "Pagination",
+ "description": "Page navigation with previous, next, numbered, and overflow links.",
+ "categories": ["ui"],
+ "docs": "https://ui.full.dev/components/pagination/",
+ "dependencies": ["@lucide/astro"],
+ "registryDependencies": ["@fulldev/button"],
+ "files": [
+ {
+ "path": "src/components/ui/pagination/index.ts",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-content.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-ellipsis.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-item.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-link.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-next.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination-previous.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/pagination/pagination.astro",
+ "type": "registry:ui"
+ }
+ ]
+ },
+ {
+ "name": "aspect-ratio",
+ "type": "registry:ui",
+ "title": "Aspect Ratio",
+ "description": "Displays content within a desired ratio.",
+ "categories": ["ui"],
+ "docs": "https://ui.full.dev/components/aspect-ratio/",
+ "files": [
+ {
+ "path": "src/components/ui/aspect-ratio/aspect-ratio.astro",
+ "type": "registry:ui"
+ },
+ {
+ "path": "src/components/ui/aspect-ratio/index.ts",
+ "type": "registry:ui"
+ }
+ ]
+ },
{
"name": "components",
"type": "registry:item",
@@ -1825,11 +2168,14 @@
"@fulldev/accordion",
"@fulldev/alert",
"@fulldev/alert-dialog",
+ "@fulldev/aspect-ratio",
+ "@fulldev/attachment",
"@fulldev/avatar",
"@fulldev/badge",
"@fulldev/banner",
"@fulldev/breadcrumb",
"@fulldev/button",
+ "@fulldev/button-group",
"@fulldev/card",
"@fulldev/carousel",
"@fulldev/checkbox",
@@ -1837,6 +2183,7 @@
"@fulldev/combobox",
"@fulldev/command",
"@fulldev/dialog",
+ "@fulldev/drawer",
"@fulldev/dropdown-menu",
"@fulldev/empty",
"@fulldev/field",
@@ -1854,10 +2201,12 @@
"@fulldev/marquee",
"@fulldev/native-select",
"@fulldev/navigation-menu",
+ "@fulldev/pagination",
"@fulldev/popover",
"@fulldev/price",
"@fulldev/radio-group",
"@fulldev/rating",
+ "@fulldev/resizable",
"@fulldev/section",
"@fulldev/select",
"@fulldev/separator",
@@ -1871,8 +2220,10 @@
"@fulldev/tabs",
"@fulldev/textarea",
"@fulldev/theme-toggle",
+ "@fulldev/toast",
"@fulldev/toc",
"@fulldev/toggle",
+ "@fulldev/toggle-group",
"@fulldev/tooltip",
"@fulldev/typography",
"@fulldev/video"
diff --git a/registry/init/global.css b/registry/init/global.css
index 54728430b..a1c7b79f4 100644
--- a/registry/init/global.css
+++ b/registry/init/global.css
@@ -115,6 +115,8 @@
}
@theme inline {
+ --font-heading: var(--font-sans);
+
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
diff --git a/src/components/blocks/doc-1.astro b/src/components/blocks/doc-1.astro
index 23967a4a8..b03c1634e 100644
--- a/src/components/blocks/doc-1.astro
+++ b/src/components/blocks/doc-1.astro
@@ -299,6 +299,81 @@ const openLinks = markdownUrl
}
+
+
diff --git a/src/components/ui/carousel/index.ts b/src/components/ui/carousel/index.ts
index 0019f3ccf..7e06994a2 100644
--- a/src/components/ui/carousel/index.ts
+++ b/src/components/ui/carousel/index.ts
@@ -1,8 +1,4 @@
-export type {
- EmblaCarouselType as CarouselApi,
- EmblaOptionsType as CarouselOptions,
- EmblaPluginType as CarouselPlugin,
-} from "embla-carousel"
+export type { CarouselController, CarouselOptions } from "@data-slot/carousel"
export { default as Carousel } from "./carousel.astro"
export { default as CarouselContent } from "./carousel-content.astro"
diff --git a/src/components/ui/combobox/combobox-input.astro b/src/components/ui/combobox/combobox-input.astro
index 4902592a5..7e08527f9 100644
--- a/src/components/ui/combobox/combobox-input.astro
+++ b/src/components/ui/combobox/combobox-input.astro
@@ -4,6 +4,7 @@ import XIcon from "@lucide/astro/icons/x"
import { cn } from "@/lib/utils"
import InputGroupAddon from "@/components/ui/input-group/input-group-addon.astro"
+import InputGroupButton from "@/components/ui/input-group/input-group-button.astro"
import InputGroupInput from "@/components/ui/input-group/input-group-input.astro"
import InputGroup from "@/components/ui/input-group/input-group.astro"
@@ -24,7 +25,12 @@ const {
} = Astro.props
---
-
+
-
+
)
}
diff --git a/src/components/ui/combobox/combobox-trigger.astro b/src/components/ui/combobox/combobox-trigger.astro
index 4a0cac20b..31b8ec535 100644
--- a/src/components/ui/combobox/combobox-trigger.astro
+++ b/src/components/ui/combobox/combobox-trigger.astro
@@ -3,6 +3,7 @@ import type { HTMLAttributes } from "astro/types"
import ChevronDownIcon from "@lucide/astro/icons/chevron-down"
import { cn } from "@/lib/utils"
+import InputGroupButton from "@/components/ui/input-group/input-group-button.astro"
type Props = HTMLAttributes<"button"> & {
showIcon?: boolean
@@ -16,13 +17,12 @@ const {
} = Astro.props
---
-
@@ -31,4 +31,4 @@ const {
)
}
-
+
diff --git a/src/components/ui/drawer/drawer-close.astro b/src/components/ui/drawer/drawer-close.astro
new file mode 100644
index 000000000..aa3235af2
--- /dev/null
+++ b/src/components/ui/drawer/drawer-close.astro
@@ -0,0 +1,13 @@
+---
+import type { ComponentProps } from "astro/types"
+
+import { Button } from "@/components/ui/button"
+
+type Props = ComponentProps
+
+const { ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-content.astro b/src/components/ui/drawer/drawer-content.astro
new file mode 100644
index 000000000..c74ac9885
--- /dev/null
+++ b/src/components/ui/drawer/drawer-content.astro
@@ -0,0 +1,43 @@
+---
+import type { ComponentProps } from "astro/types"
+
+import DrawerOverlay from "./drawer-overlay.astro"
+import DrawerPopup from "./drawer-popup.astro"
+import DrawerPortal from "./drawer-portal.astro"
+import DrawerSwipeHandle from "./drawer-swipe-handle.astro"
+import DrawerViewport from "./drawer-viewport.astro"
+
+type Props = ComponentProps & {
+ showOverlay?: boolean
+ showSwipeHandle?: boolean
+ container?: string
+ keepMounted?: boolean
+ overlayClass?: string
+ viewportClass?: string
+}
+
+const {
+ showOverlay = true,
+ showSwipeHandle = false,
+ container,
+ keepMounted,
+ overlayClass,
+ viewportClass,
+ ...props
+} = Astro.props
+---
+
+
+ {showOverlay && }
+
+
+ {showSwipeHandle && }
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-description.astro b/src/components/ui/drawer/drawer-description.astro
new file mode 100644
index 000000000..3b3deaf43
--- /dev/null
+++ b/src/components/ui/drawer/drawer-description.astro
@@ -0,0 +1,17 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"p">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-footer.astro b/src/components/ui/drawer/drawer-footer.astro
new file mode 100644
index 000000000..1cb17ed7f
--- /dev/null
+++ b/src/components/ui/drawer/drawer-footer.astro
@@ -0,0 +1,17 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-header.astro b/src/components/ui/drawer/drawer-header.astro
new file mode 100644
index 000000000..f35e82a34
--- /dev/null
+++ b/src/components/ui/drawer/drawer-header.astro
@@ -0,0 +1,17 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-indent-background.astro b/src/components/ui/drawer/drawer-indent-background.astro
new file mode 100644
index 000000000..266c269e1
--- /dev/null
+++ b/src/components/ui/drawer/drawer-indent-background.astro
@@ -0,0 +1,11 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-indent.astro b/src/components/ui/drawer/drawer-indent.astro
new file mode 100644
index 000000000..c3d7d9303
--- /dev/null
+++ b/src/components/ui/drawer/drawer-indent.astro
@@ -0,0 +1,11 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-overlay.astro b/src/components/ui/drawer/drawer-overlay.astro
new file mode 100644
index 000000000..cc2f163ff
--- /dev/null
+++ b/src/components/ui/drawer/drawer-overlay.astro
@@ -0,0 +1,21 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, hidden = true, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-popup.astro b/src/components/ui/drawer/drawer-popup.astro
new file mode 100644
index 000000000..8b4d4bae1
--- /dev/null
+++ b/src/components/ui/drawer/drawer-popup.astro
@@ -0,0 +1,36 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"div"> & {
+ initialFocus?: boolean | string
+ finalFocus?: boolean | string
+}
+
+const {
+ class: className,
+ initialFocus,
+ finalFocus,
+ hidden = true,
+ ...props
+} = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-portal.astro b/src/components/ui/drawer/drawer-portal.astro
new file mode 100644
index 000000000..b03e17ede
--- /dev/null
+++ b/src/components/ui/drawer/drawer-portal.astro
@@ -0,0 +1,27 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+type Props = HTMLAttributes<"div"> & {
+ container?: string
+ keepMounted?: boolean
+}
+
+const {
+ class: className,
+ container,
+ keepMounted,
+ hidden = true,
+ ...props
+} = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-provider.astro b/src/components/ui/drawer/drawer-provider.astro
new file mode 100644
index 000000000..9ea699759
--- /dev/null
+++ b/src/components/ui/drawer/drawer-provider.astro
@@ -0,0 +1,11 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-swipe-handle.astro b/src/components/ui/drawer/drawer-swipe-handle.astro
new file mode 100644
index 000000000..402461292
--- /dev/null
+++ b/src/components/ui/drawer/drawer-swipe-handle.astro
@@ -0,0 +1,20 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
diff --git a/src/components/ui/drawer/drawer-title.astro b/src/components/ui/drawer/drawer-title.astro
new file mode 100644
index 000000000..9113dbec1
--- /dev/null
+++ b/src/components/ui/drawer/drawer-title.astro
@@ -0,0 +1,17 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"h2">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-trigger.astro b/src/components/ui/drawer/drawer-trigger.astro
new file mode 100644
index 000000000..0839e26d5
--- /dev/null
+++ b/src/components/ui/drawer/drawer-trigger.astro
@@ -0,0 +1,21 @@
+---
+import type { ComponentProps } from "astro/types"
+
+import { Button } from "@/components/ui/button"
+
+type Props = ComponentProps & {
+ drawerTarget?: string
+ payload?: string
+}
+
+const { drawerTarget, payload, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-viewport.astro b/src/components/ui/drawer/drawer-viewport.astro
new file mode 100644
index 000000000..cc2ae0ba2
--- /dev/null
+++ b/src/components/ui/drawer/drawer-viewport.astro
@@ -0,0 +1,21 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, hidden = true, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer-virtual-keyboard-provider.astro b/src/components/ui/drawer/drawer-virtual-keyboard-provider.astro
new file mode 100644
index 000000000..93d2e2650
--- /dev/null
+++ b/src/components/ui/drawer/drawer-virtual-keyboard-provider.astro
@@ -0,0 +1,11 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/drawer/drawer.astro b/src/components/ui/drawer/drawer.astro
new file mode 100644
index 000000000..f8cbed3e9
--- /dev/null
+++ b/src/components/ui/drawer/drawer.astro
@@ -0,0 +1,60 @@
+---
+import type { HTMLAttributes } from "astro/types"
+import type { DrawerSnapPoint, DrawerSwipeDirection } from "@data-slot/drawer"
+
+type Props = HTMLAttributes<"div"> & {
+ defaultOpen?: boolean
+ modal?: boolean | "trap-focus"
+ disablePointerDismissal?: boolean
+ closeOnEscape?: boolean
+ swipeDirection?: DrawerSwipeDirection
+ snapPoint?: DrawerSnapPoint | null
+ defaultSnapPoint?: DrawerSnapPoint | null
+ triggerId?: string | null
+ defaultTriggerId?: string | null
+}
+
+const {
+ class: className,
+ defaultOpen,
+ modal,
+ disablePointerDismissal,
+ closeOnEscape,
+ swipeDirection,
+ snapPoint,
+ defaultSnapPoint,
+ triggerId,
+ defaultTriggerId,
+ ...props
+} = Astro.props
+---
+
+
+
+
+
+
diff --git a/src/components/ui/drawer/index.ts b/src/components/ui/drawer/index.ts
new file mode 100644
index 000000000..618b0e7a5
--- /dev/null
+++ b/src/components/ui/drawer/index.ts
@@ -0,0 +1,28 @@
+export { default as Drawer } from "./drawer.astro"
+export { default as DrawerTrigger } from "./drawer-trigger.astro"
+export { default as DrawerClose } from "./drawer-close.astro"
+export { default as DrawerPortal } from "./drawer-portal.astro"
+export { default as DrawerOverlay } from "./drawer-overlay.astro"
+export { default as DrawerBackdrop } from "./drawer-overlay.astro"
+export { default as DrawerViewport } from "./drawer-viewport.astro"
+export { default as DrawerPopup } from "./drawer-popup.astro"
+export { default as DrawerContent } from "./drawer-content.astro"
+export { default as DrawerSwipeHandle } from "./drawer-swipe-handle.astro"
+export { default as DrawerHeader } from "./drawer-header.astro"
+export { default as DrawerFooter } from "./drawer-footer.astro"
+export { default as DrawerTitle } from "./drawer-title.astro"
+export { default as DrawerDescription } from "./drawer-description.astro"
+export { default as DrawerProvider } from "./drawer-provider.astro"
+export { default as DrawerIndent } from "./drawer-indent.astro"
+export { default as DrawerIndentBackground } from "./drawer-indent-background.astro"
+export { default as DrawerVirtualKeyboardProvider } from "./drawer-virtual-keyboard-provider.astro"
+
+export type {
+ DrawerChangeDetails,
+ DrawerChangeReason,
+ DrawerController,
+ DrawerOptions,
+ DrawerSnapChangeDetails,
+ DrawerSnapPoint,
+ DrawerSwipeDirection,
+} from "@data-slot/drawer"
diff --git a/src/components/ui/navigation-menu/navigation-menu.astro b/src/components/ui/navigation-menu/navigation-menu.astro
index f14bb8b17..05bff7abb 100644
--- a/src/components/ui/navigation-menu/navigation-menu.astro
+++ b/src/components/ui/navigation-menu/navigation-menu.astro
@@ -27,7 +27,7 @@ const {
openOnFocus,
side = "bottom",
align = "start",
- sideOffset = 0,
+ sideOffset = 8,
alignOffset = 0,
positionMethod = "absolute",
safeTriangle,
@@ -56,7 +56,7 @@ const {
)}
>
-
+
diff --git a/src/components/ui/slider/slider.astro b/src/components/ui/slider/slider.astro
index 0d0778ada..a31db0912 100644
--- a/src/components/ui/slider/slider.astro
+++ b/src/components/ui/slider/slider.astro
@@ -25,7 +25,7 @@ const {
step,
largeStep,
orientation = "horizontal",
- thumbAlignment = "center",
+ thumbAlignment = "edge",
disabled,
...props
} = Astro.props
diff --git a/src/components/ui/toast/index.ts b/src/components/ui/toast/index.ts
new file mode 100644
index 000000000..31ac5659d
--- /dev/null
+++ b/src/components/ui/toast/index.ts
@@ -0,0 +1,26 @@
+export { default as Toast } from "./toast.astro"
+export { default as ToastTemplate } from "./toast-template.astro"
+export { default as ToastViewport } from "./toast-viewport.astro"
+export { default as ToastItem } from "./toast-item.astro"
+export { default as ToastContent } from "./toast-content.astro"
+export { default as ToastIcon } from "./toast-icon.astro"
+export { default as ToastTitle } from "./toast-title.astro"
+export { default as ToastDescription } from "./toast-description.astro"
+export { default as ToastAction } from "./toast-action.astro"
+export { default as ToastClose } from "./toast-close.astro"
+export { default as Toaster } from "./toaster.astro"
+
+export type {
+ ToastActionEvent,
+ ToastClearableField,
+ ToastController,
+ ToastOptions,
+ ToastPosition,
+ ToastPromiseErrorValue,
+ ToastPromiseHandle,
+ ToastPromiseOptions,
+ ToastPromiseState,
+ ToastPromiseStateValue,
+ ToastShowOptions,
+ ToastUpdateOptions,
+} from "@data-slot/toast"
diff --git a/src/components/ui/toast/toast-action.astro b/src/components/ui/toast/toast-action.astro
new file mode 100644
index 000000000..689ccd1f7
--- /dev/null
+++ b/src/components/ui/toast/toast-action.astro
@@ -0,0 +1,25 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+import { buttonVariants } from "@/components/ui/button"
+
+type Props = HTMLAttributes<"button">
+
+const {
+ class: className,
+ hidden = true,
+ type = "button",
+ ...props
+} = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/toast/toast-close.astro b/src/components/ui/toast/toast-close.astro
new file mode 100644
index 000000000..8755bcadd
--- /dev/null
+++ b/src/components/ui/toast/toast-close.astro
@@ -0,0 +1,27 @@
+---
+import type { ComponentProps } from "astro/types"
+import XIcon from "@lucide/astro/icons/x"
+
+import { cn } from "@/lib/utils"
+import { Button } from "@/components/ui/button"
+
+type Props = ComponentProps
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
+
+
diff --git a/src/components/ui/toast/toast-content.astro b/src/components/ui/toast/toast-content.astro
new file mode 100644
index 000000000..05bcaaec5
--- /dev/null
+++ b/src/components/ui/toast/toast-content.astro
@@ -0,0 +1,20 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/toast/toast-description.astro b/src/components/ui/toast/toast-description.astro
new file mode 100644
index 000000000..dc9b8a555
--- /dev/null
+++ b/src/components/ui/toast/toast-description.astro
@@ -0,0 +1,18 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, hidden = true, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/toast/toast-icon.astro b/src/components/ui/toast/toast-icon.astro
new file mode 100644
index 000000000..afb078f31
--- /dev/null
+++ b/src/components/ui/toast/toast-icon.astro
@@ -0,0 +1,37 @@
+---
+import type { HTMLAttributes } from "astro/types"
+import CircleCheckIcon from "@lucide/astro/icons/circle-check"
+import InfoIcon from "@lucide/astro/icons/info"
+import LoaderIcon from "@lucide/astro/icons/loader-circle"
+import OctagonXIcon from "@lucide/astro/icons/octagon-x"
+import TriangleAlertIcon from "@lucide/astro/icons/triangle-alert"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"span">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/toast/toast-item.astro b/src/components/ui/toast/toast-item.astro
new file mode 100644
index 000000000..f89258aa4
--- /dev/null
+++ b/src/components/ui/toast/toast-item.astro
@@ -0,0 +1,28 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"li">
+
+const { class: className, ...props } = Astro.props
+---
+
+*]:opacity-0",
+ className
+ )}
+ {...props}
+>
+
+
diff --git a/src/components/ui/toast/toast-template.astro b/src/components/ui/toast/toast-template.astro
new file mode 100644
index 000000000..ae8a15a18
--- /dev/null
+++ b/src/components/ui/toast/toast-template.astro
@@ -0,0 +1,11 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+type Props = HTMLAttributes<"div">
+
+const { ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/toast/toast-title.astro b/src/components/ui/toast/toast-title.astro
new file mode 100644
index 000000000..e4936fdd3
--- /dev/null
+++ b/src/components/ui/toast/toast-title.astro
@@ -0,0 +1,17 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"div">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/toast/toast-viewport.astro b/src/components/ui/toast/toast-viewport.astro
new file mode 100644
index 000000000..b5364773d
--- /dev/null
+++ b/src/components/ui/toast/toast-viewport.astro
@@ -0,0 +1,20 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+
+type Props = HTMLAttributes<"ol">
+
+const { class: className, ...props } = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/toast/toast.astro b/src/components/ui/toast/toast.astro
new file mode 100644
index 000000000..2b44eace8
--- /dev/null
+++ b/src/components/ui/toast/toast.astro
@@ -0,0 +1,51 @@
+---
+import type { HTMLAttributes } from "astro/types"
+import type { ToastPosition } from "@data-slot/toast"
+
+type Props = HTMLAttributes<"div"> & {
+ limit?: number
+ duration?: number
+ position?: ToastPosition
+ pauseOnHover?: boolean
+ pauseOnFocus?: boolean
+ portal?: boolean
+}
+
+const {
+ class: className,
+ limit,
+ duration,
+ position,
+ pauseOnHover,
+ pauseOnFocus,
+ portal,
+ ...props
+} = Astro.props
+---
+
+
+
+
+
+
diff --git a/src/components/ui/toast/toaster.astro b/src/components/ui/toast/toaster.astro
new file mode 100644
index 000000000..fb31280e2
--- /dev/null
+++ b/src/components/ui/toast/toaster.astro
@@ -0,0 +1,37 @@
+---
+import type { ComponentProps } from "astro/types"
+
+import ToastAction from "./toast-action.astro"
+import ToastClose from "./toast-close.astro"
+import ToastContent from "./toast-content.astro"
+import ToastDescription from "./toast-description.astro"
+import ToastIcon from "./toast-icon.astro"
+import ToastItem from "./toast-item.astro"
+import ToastTemplate from "./toast-template.astro"
+import ToastTitle from "./toast-title.astro"
+import ToastViewport from "./toast-viewport.astro"
+import Toast from "./toast.astro"
+
+type Props = ComponentProps & {
+ viewportClass?: string
+}
+
+const { viewportClass, ...props } = Astro.props
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/toggle-group/index.ts b/src/components/ui/toggle-group/index.ts
new file mode 100644
index 000000000..fb3624dda
--- /dev/null
+++ b/src/components/ui/toggle-group/index.ts
@@ -0,0 +1,2 @@
+export { default as ToggleGroup } from "./toggle-group.astro"
+export { default as ToggleGroupItem } from "./toggle-group-item.astro"
diff --git a/src/components/ui/toggle-group/toggle-group-item.astro b/src/components/ui/toggle-group/toggle-group-item.astro
new file mode 100644
index 000000000..d3b4b9b42
--- /dev/null
+++ b/src/components/ui/toggle-group/toggle-group-item.astro
@@ -0,0 +1,44 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+import {
+ toggleVariants,
+ type ToggleVariantProps,
+} from "@/components/ui/toggle/toggle-variants"
+
+type Props = HTMLAttributes<"button"> &
+ ToggleVariantProps & {
+ value: string
+ disabled?: boolean
+ }
+
+const {
+ class: className,
+ value,
+ disabled,
+ variant = "default",
+ size = "default",
+ type = "button",
+ ...props
+} = Astro.props
+---
+
+
+
+
diff --git a/src/components/ui/toggle-group/toggle-group.astro b/src/components/ui/toggle-group/toggle-group.astro
new file mode 100644
index 000000000..8e8386294
--- /dev/null
+++ b/src/components/ui/toggle-group/toggle-group.astro
@@ -0,0 +1,74 @@
+---
+import type { HTMLAttributes } from "astro/types"
+
+import { cn } from "@/lib/utils"
+import type { ToggleVariantProps } from "@/components/ui/toggle/toggle-variants"
+
+type Props = HTMLAttributes<"div"> &
+ ToggleVariantProps & {
+ defaultValue?: string | string[]
+ multiple?: boolean
+ orientation?: "horizontal" | "vertical"
+ loop?: boolean
+ disabled?: boolean
+ spacing?: number
+ }
+
+const {
+ class: className,
+ style,
+ defaultValue,
+ multiple,
+ orientation = "horizontal",
+ loop,
+ disabled,
+ variant,
+ size,
+ spacing = 2,
+ ...props
+} = Astro.props
+
+const serializedDefaultValue = Array.isArray(defaultValue)
+ ? defaultValue.join(" ")
+ : defaultValue
+
+const resolvedStyle =
+ typeof style === "string"
+ ? `--gap: ${spacing}; ${style}`
+ : { "--gap": spacing, ...(style ?? {}) }
+---
+
+[data-slot=toggle-group-item]:first-child]:rounded-l-md [&[data-orientation=horizontal][data-spacing='0']>[data-slot=toggle-group-item]:last-child]:rounded-r-md [&[data-orientation=horizontal][data-spacing='0'][data-variant=outline]>[data-slot=toggle-group-item]:not(:first-child)]:border-l-0 [&[data-orientation=vertical][data-spacing='0']>[data-slot=toggle-group-item]:first-child]:rounded-t-md [&[data-orientation=vertical][data-spacing='0']>[data-slot=toggle-group-item]:last-child]:rounded-b-md [&[data-orientation=vertical][data-spacing='0'][data-variant=outline]>[data-slot=toggle-group-item]:not(:first-child)]:border-t-0 [&[data-spacing='0']>[data-slot=toggle-group-item]]:rounded-none [&[data-spacing='0']>[data-slot=toggle-group-item]]:px-2 [&[data-spacing='0']>[data-slot=toggle-group-item]]:shadow-none [&[data-spacing='0']>[data-slot=toggle-group-item]:has([data-icon=inline-end])]:pr-1.5 [&[data-spacing='0']>[data-slot=toggle-group-item]:has([data-icon=inline-start])]:pl-1.5",
+ className
+ )}
+ {...props}
+>
+
+
+
+
diff --git a/src/components/ui/typography/typeset.css b/src/components/ui/typography/typeset.css
new file mode 100644
index 000000000..9f5f2c76b
--- /dev/null
+++ b/src/components/ui/typography/typeset.css
@@ -0,0 +1,441 @@
+/*
+ * shadcn/typeset
+ * https://ui.shadcn.com/docs/typeset.
+ */
+
+@layer components {
+ .typeset {
+ --typeset-font-body: inherit;
+ --typeset-font-heading: var(--font-heading);
+ --typeset-font-mono: var(--font-mono);
+ --typeset-size: 1em;
+ --typeset-leading: 1.75;
+ --typeset-flow: 1.25em;
+ }
+}
+
+@layer components {
+ .typeset {
+ font-family: var(--typeset-font-body);
+ font-size: calc(var(--typeset-size) * 1.125);
+ line-height: var(--typeset-leading);
+ color: var(--color-foreground, currentColor);
+ overflow-wrap: break-word;
+ margin-trim: block-start;
+
+ @media (min-width: 48rem), print {
+ font-size: var(--typeset-size);
+ }
+
+ --typeset-muted: var(
+ --color-muted-foreground,
+ color-mix(in oklab, currentColor 60%, transparent)
+ );
+ --typeset-rule: var(
+ --color-border,
+ color-mix(in oklab, currentColor 20%, transparent)
+ );
+ }
+
+ .typeset
+ *:not(
+ :where(
+ .not-typeset,
+ [data-not-typeset],
+ .not-typeset *,
+ [data-not-typeset] *
+ )
+ ) {
+ &:where(p) {
+ margin-block-start: var(--typeset-flow);
+ margin-block-end: 0;
+ }
+ &:where(h1, h2, h3, h4, h5, h6) {
+ color: var(--color-foreground, currentColor);
+ font-family: var(--typeset-font-heading);
+ font-weight: 600;
+ margin-block-end: 0;
+ }
+ &:where(h1) {
+ font-size: 1.75em;
+ line-height: 1.3;
+ margin-block-start: var(--typeset-flow);
+ }
+ &:where(h2) {
+ font-size: 1.25em;
+ line-height: 1.4;
+ margin-block-start: calc(var(--typeset-flow) * 1.4);
+ }
+ &:where(h3) {
+ font-size: 1.125em;
+ line-height: 1.45;
+ margin-block-start: var(--typeset-flow);
+ }
+ &:where(h4) {
+ font-size: 1em;
+ line-height: 1.5;
+ margin-block-start: var(--typeset-flow);
+ }
+ &:where(h5) {
+ font-size: 0.875em;
+ line-height: 1.5;
+ font-weight: 500;
+ color: var(--typeset-muted);
+ margin-block-start: calc(var(--typeset-flow) / 0.875);
+ }
+ &:where(h6) {
+ font-size: 0.8125em;
+ line-height: 1.5;
+ font-weight: 500;
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--typeset-muted);
+ margin-block-start: calc(var(--typeset-flow) / 0.8125);
+ }
+ &:where([id]) {
+ scroll-margin-block-start: var(--typeset-flow);
+ }
+ &:where(h1 + *, h2 + *, h3 + *, h4 + *, h5 + *, h6 + *) {
+ margin-block-start: 1em;
+ }
+ &:where(:is(h1, h2, h3, h4) :is(code)) {
+ font-size: 0.9em;
+ }
+ &:where(a) {
+ color: inherit;
+ font-weight: 500;
+ text-decoration-line: underline;
+ text-decoration-color: color-mix(in oklab, currentColor 30%, transparent);
+ }
+ &:where(a:hover) {
+ text-decoration-color: currentColor;
+ }
+ &:where(a:focus-visible) {
+ outline: 2px solid var(--color-ring, currentColor);
+ outline-offset: 2px;
+ border-radius: 0.125em;
+ }
+ &:where(:is(h1, h2, h3, h4, h5, h6) :is(a)) {
+ font-weight: inherit;
+ }
+ &:where(strong, b) {
+ font-weight: 600;
+ }
+ &:where(:is(h1, h2, h3, h4) :is(strong, b)) {
+ font-weight: 600;
+ }
+ &:where(mark) {
+ background-color: color-mix(
+ in oklab,
+ oklch(0.86 0.17 95) 40%,
+ transparent
+ );
+ color: inherit;
+ padding: 0.05em 0.15em;
+ border-radius: 0.2em;
+ }
+ &:where(abbr[title]) {
+ text-decoration-line: underline;
+ text-decoration-style: dotted;
+ text-underline-offset: 0.2em;
+ cursor: help;
+ }
+ &:where(del, s) {
+ color: var(--typeset-muted);
+ text-decoration-line: line-through;
+ }
+ &:where(sup, sub) {
+ font-size: 0.75em;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+ }
+ &:where(sup) {
+ top: -0.5em;
+ }
+ &:where(sub) {
+ bottom: -0.25em;
+ }
+ &:where(sup a) {
+ text-decoration-line: none;
+ font-weight: 500;
+ }
+ &:where(ul) {
+ list-style-type: disc;
+ }
+ &:where(ol) {
+ list-style-type: decimal;
+ }
+ &:where(ul ul) {
+ list-style-type: circle;
+ }
+ &:where(ul ul ul) {
+ list-style-type: square;
+ }
+ &:where(ol[type="a" i]) {
+ list-style-type: lower-alpha;
+ }
+ &:where(ol[type="i" i]) {
+ list-style-type: lower-roman;
+ }
+ &:where(ol[type="A" s]) {
+ list-style-type: upper-alpha;
+ }
+ &:where(ol[type="I" s]) {
+ list-style-type: upper-roman;
+ }
+ &:where(ul, ol) {
+ margin-block-start: var(--typeset-flow);
+ margin-block-end: 0;
+ padding-inline-start: 1.5em;
+ }
+ &:where(li) {
+ margin-block-start: 0.5em;
+ padding-inline-start: 0.4em;
+ }
+ &:where(li > p, li > ul, li > ol) {
+ margin-block-start: 0.5em;
+ }
+ &:where(ul > li)::marker,
+ &:where(ol > li)::marker {
+ color: var(--typeset-muted);
+ }
+ &:where(ul.contains-task-list) {
+ list-style-type: none;
+ padding-inline-start: 0.25em;
+ }
+ &:where(li.task-list-item > input[type="checkbox"]) {
+ margin-inline-end: 0.5em;
+ vertical-align: -0.1em;
+ accent-color: var(--color-primary, currentColor);
+ }
+ &:where(details) {
+ margin-block-start: var(--typeset-flow);
+ margin-block-end: 0;
+ }
+ &:where(summary) {
+ cursor: pointer;
+ font-weight: 500;
+ }
+ &:where(summary)::marker {
+ color: var(--typeset-muted);
+ }
+ &:where(kbd) {
+ font-family: inherit;
+ font-size: 0.85em;
+ font-weight: 500;
+ border: 1px solid var(--typeset-rule);
+ border-block-end-width: 2px;
+ border-radius: min(calc(var(--radius, 0.5em) * 0.6), 0.35em);
+ padding: 0.0625em 0.35em;
+ }
+ &:where(dl) {
+ margin-block-start: var(--typeset-flow);
+ margin-block-end: 0;
+ }
+ &:where(dt) {
+ font-weight: 500;
+ margin-block-start: 1em;
+ }
+ &:where(dt + dt) {
+ margin-block-start: 0.25em;
+ }
+ &:where(dd) {
+ margin-block-start: 0.25em;
+ margin-inline-start: 0;
+ padding-inline-start: 1em;
+ color: var(--typeset-muted);
+ }
+ &:where(:not(pre) > code) {
+ background-color: var(
+ --color-muted,
+ color-mix(in oklab, currentColor 8%, transparent)
+ );
+ font-family: var(--typeset-font-mono);
+ font-size: 0.85em;
+ border-radius: min(calc(var(--radius, 0.5em) * 0.6), 0.35em);
+ padding: 0.125em 0.3em;
+ }
+ &:where(pre) {
+ background-color: var(
+ --color-muted,
+ color-mix(in oklab, currentColor 8%, transparent)
+ );
+ font-family: var(--typeset-font-mono);
+ font-size: 0.875em;
+ line-height: 1.5;
+ tab-size: 2;
+ direction: ltr;
+ border-radius: var(--radius, 0.5em);
+ padding: 0.75em 1em;
+ overflow-x: auto;
+ margin-block-start: calc(var(--typeset-flow) / 0.875);
+ margin-block-end: 0;
+ }
+ &:where(pre code) {
+ background-color: transparent;
+ font-family: inherit;
+ font-size: inherit;
+ padding: 0;
+ border-radius: 0;
+ }
+ &:where(blockquote) {
+ border-inline-start: 2px solid var(--typeset-rule);
+ padding-inline-start: 1em;
+ margin-block-start: var(--typeset-flow);
+ margin-block-end: 0;
+ margin-inline: 0;
+ }
+ &:where(hr) {
+ border: 0;
+ border-block-start: 1px solid var(--typeset-rule);
+ margin-block-start: calc(var(--typeset-flow) * 2.4);
+ margin-block-end: 0;
+ }
+ &:where(hr + h1, hr + h2, hr + h3, hr + h4) {
+ margin-block-start: var(--typeset-flow);
+ }
+ &:where(.footnotes, [data-footnotes]) {
+ margin-block-start: calc(var(--typeset-flow) * 2);
+ border-block-start: 1px solid var(--typeset-rule);
+ padding-block-start: var(--typeset-flow);
+ font-size: 0.875em;
+ color: var(--typeset-muted);
+ }
+ &:where(math[display="block"]) {
+ margin-block-start: var(--typeset-flow);
+ margin-block-end: 0;
+ overflow-x: auto;
+ overflow-y: hidden;
+ padding-block: 0.25em;
+ }
+ &:where(img, video) {
+ border-radius: var(--radius, 0.5em);
+ max-width: 100%;
+ height: auto;
+ margin-block-start: var(--typeset-flow);
+ margin-block-end: 0;
+ }
+ &:where(p img) {
+ margin-block-start: 0;
+ }
+ &:where(figure) {
+ margin-block-start: var(--typeset-flow);
+ margin-block-end: 0;
+ margin-inline: 0;
+ }
+ &:where(figcaption, caption) {
+ color: var(--typeset-muted);
+ font-size: 0.875em;
+ text-align: center;
+ margin-block-start: calc(0.75em / 0.875);
+ }
+ &:where(caption) {
+ caption-side: bottom;
+ }
+ &:where(table) {
+ max-width: 100%;
+ font-size: 1em;
+ line-height: 1.5;
+ font-variant-numeric: tabular-nums;
+ border-collapse: separate;
+ border-spacing: 0;
+ border-block-end: 1px solid var(--typeset-rule);
+ margin-block-start: var(--typeset-flow);
+ margin-block-end: 0;
+ }
+ &:where(.typeset-scroll) {
+ overflow-x: auto;
+ margin-block-start: var(--typeset-flow);
+ }
+ &:where(.typeset-scroll > *) {
+ margin-block-start: 0;
+ }
+ &:where(.typeset-scroll table) {
+ width: max-content;
+ max-width: none;
+ }
+ &:where(thead th) {
+ font-weight: 500;
+ text-align: start;
+ white-space: nowrap;
+ padding: 0.65em 1em;
+ }
+ &:where(:is(tbody, tfoot) :is(td, th)) {
+ padding: 0.75em 1em;
+ text-align: start;
+ vertical-align: top;
+ border-block-start: 1px solid var(--typeset-rule);
+ }
+ &:where(tbody th, tfoot th) {
+ font-weight: 500;
+ }
+ &:where(th:first-child, td:first-child) {
+ padding-inline-start: 0;
+ }
+ &:where(th[align="center"], td[align="center"]) {
+ text-align: center;
+ }
+ &:where(th[align="right"], td[align="right"]) {
+ text-align: end;
+ }
+ &:where(li > blockquote, li > table, li > figure) {
+ margin-block-start: 0.5em;
+ }
+ &:where(li > pre) {
+ margin-block-start: calc(0.5em / 0.875);
+ }
+ @media print {
+ &:where(pre, table, blockquote, figure) {
+ break-inside: avoid;
+ }
+ &:where(h1, h2, h3, h4) {
+ break-after: avoid;
+ }
+ }
+ @media (forced-colors: active) {
+ &:where(:not(pre) > code) {
+ border: 1px solid;
+ }
+ }
+ }
+
+ .typeset
+ > :where(:first-child):not(
+ :where(
+ .not-typeset,
+ [data-not-typeset],
+ .not-typeset *,
+ [data-not-typeset] *
+ )
+ ),
+ .typeset
+ > :where(:first-child)
+ > :where(:first-child):not(
+ :where(
+ .not-typeset,
+ [data-not-typeset],
+ .not-typeset *,
+ [data-not-typeset] *
+ )
+ ),
+ .typeset
+ :where(
+ li > :first-child,
+ blockquote > :first-child,
+ td > :first-child,
+ th > :first-child,
+ dd > :first-child,
+ figure > :first-child,
+ figure > picture > img
+ ):not(
+ :where(
+ .not-typeset,
+ [data-not-typeset],
+ .not-typeset *,
+ [data-not-typeset] *
+ )
+ ) {
+ margin-block-start: 0;
+ }
+}
diff --git a/src/components/ui/typography/typography-a.astro b/src/components/ui/typography/typography-a.astro
index 5165de605..2e6f703d9 100644
--- a/src/components/ui/typography/typography-a.astro
+++ b/src/components/ui/typography/typography-a.astro
@@ -9,29 +9,20 @@ type Props = HTMLAttributes<"a"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-sm" : size === "lg" ? "text-lg" : "text-base"
---
-
+
-
-
diff --git a/src/components/ui/typography/typography-blockquote.astro b/src/components/ui/typography/typography-blockquote.astro
index bdf970c0c..d037b53d4 100644
--- a/src/components/ui/typography/typography-blockquote.astro
+++ b/src/components/ui/typography/typography-blockquote.astro
@@ -9,35 +9,16 @@ type Props = HTMLAttributes<"blockquote"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-sm" : size === "lg" ? "text-lg" : "text-base"
---
-
-
diff --git a/src/components/ui/typography/typography-h1.astro b/src/components/ui/typography/typography-h1.astro
index 40624f207..22ce1b64f 100644
--- a/src/components/ui/typography/typography-h1.astro
+++ b/src/components/ui/typography/typography-h1.astro
@@ -9,33 +9,20 @@ type Props = HTMLAttributes<"h1"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-3xl" : size === "lg" ? "text-5xl" : "text-4xl"
---
-
+
-
-
diff --git a/src/components/ui/typography/typography-h2.astro b/src/components/ui/typography/typography-h2.astro
index 788756a40..e4641069d 100644
--- a/src/components/ui/typography/typography-h2.astro
+++ b/src/components/ui/typography/typography-h2.astro
@@ -9,38 +9,20 @@ type Props = HTMLAttributes<"h2"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-2xl" : size === "lg" ? "text-4xl" : "text-3xl"
---
-
+
-
-
diff --git a/src/components/ui/typography/typography-h3.astro b/src/components/ui/typography/typography-h3.astro
index a2824c668..f6d452326 100644
--- a/src/components/ui/typography/typography-h3.astro
+++ b/src/components/ui/typography/typography-h3.astro
@@ -9,33 +9,16 @@ type Props = HTMLAttributes<"h3"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-xl" : size === "lg" ? "text-3xl" : "text-2xl"
---
-
+
-
-
diff --git a/src/components/ui/typography/typography-h4.astro b/src/components/ui/typography/typography-h4.astro
index 65c4868a7..bc0c00ea5 100644
--- a/src/components/ui/typography/typography-h4.astro
+++ b/src/components/ui/typography/typography-h4.astro
@@ -9,33 +9,16 @@ type Props = HTMLAttributes<"h4"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-lg" : size === "lg" ? "text-2xl" : "text-xl"
---
-
+
-
-
diff --git a/src/components/ui/typography/typography-inline-code.astro b/src/components/ui/typography/typography-inline-code.astro
index c635b7524..223afe654 100644
--- a/src/components/ui/typography/typography-inline-code.astro
+++ b/src/components/ui/typography/typography-inline-code.astro
@@ -9,39 +9,20 @@ type Props = HTMLAttributes<"code"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-xs" : size === "lg" ? "text-base" : "text-sm"
---
-
-
diff --git a/src/components/ui/typography/typography-lead.astro b/src/components/ui/typography/typography-lead.astro
index 41839b98c..115c4531a 100644
--- a/src/components/ui/typography/typography-lead.astro
+++ b/src/components/ui/typography/typography-lead.astro
@@ -9,38 +9,16 @@ type Props = HTMLAttributes<"p"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-base" : size === "lg" ? "text-xl" : "text-lg"
---
-
-
diff --git a/src/components/ui/typography/typography-list-item.astro b/src/components/ui/typography/typography-list-item.astro
index 996264041..17ccb89b9 100644
--- a/src/components/ui/typography/typography-list-item.astro
+++ b/src/components/ui/typography/typography-list-item.astro
@@ -9,36 +9,16 @@ type Props = HTMLAttributes<"li"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-sm" : size === "lg" ? "text-lg" : "text-base"
---
-
-
diff --git a/src/components/ui/typography/typography-list.astro b/src/components/ui/typography/typography-list.astro
index 0d1e66f4e..e7d3ff5d5 100644
--- a/src/components/ui/typography/typography-list.astro
+++ b/src/components/ui/typography/typography-list.astro
@@ -1,5 +1,5 @@
---
-import type { HTMLTag, Polymorphic } from "astro/types"
+import type { Polymorphic } from "astro/types"
import { cn } from "@/lib/utils"
@@ -12,52 +12,22 @@ const {
size = "default",
...props
} = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-sm" : size === "lg" ? "text-lg" : "text-base"
---
-
-
diff --git a/src/components/ui/typography/typography-p.astro b/src/components/ui/typography/typography-p.astro
index f6c1b7271..6015b3613 100644
--- a/src/components/ui/typography/typography-p.astro
+++ b/src/components/ui/typography/typography-p.astro
@@ -9,35 +9,16 @@ type Props = HTMLAttributes<"p"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-sm" : size === "lg" ? "text-lg" : "text-base"
---
-
+
-
-
diff --git a/src/components/ui/typography/typography-table-cell.astro b/src/components/ui/typography/typography-table-cell.astro
index 00bdd80cb..8d035e878 100644
--- a/src/components/ui/typography/typography-table-cell.astro
+++ b/src/components/ui/typography/typography-table-cell.astro
@@ -9,52 +9,21 @@ type Props = HTMLAttributes<"td"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-sm" : size === "lg" ? "text-lg" : "text-base"
---
-
-
diff --git a/src/components/ui/typography/typography-table-head.astro b/src/components/ui/typography/typography-table-head.astro
index 6d9aea42a..dfdfcbdbd 100644
--- a/src/components/ui/typography/typography-table-head.astro
+++ b/src/components/ui/typography/typography-table-head.astro
@@ -9,47 +9,21 @@ type Props = HTMLAttributes<"th"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-sm" : size === "lg" ? "text-lg" : "text-base"
---
-
-
diff --git a/src/components/ui/typography/typography-table-row.astro b/src/components/ui/typography/typography-table-row.astro
index 32b6dec0b..ed2671c8a 100644
--- a/src/components/ui/typography/typography-table-row.astro
+++ b/src/components/ui/typography/typography-table-row.astro
@@ -9,35 +9,16 @@ type Props = HTMLAttributes<"tr"> & {
}
const { class: className, size = "default", ...props } = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-sm" : size === "lg" ? "text-lg" : "text-base"
---
-
-
diff --git a/src/components/ui/typography/typography-table.astro b/src/components/ui/typography/typography-table.astro
index f3c88505c..a5260c601 100644
--- a/src/components/ui/typography/typography-table.astro
+++ b/src/components/ui/typography/typography-table.astro
@@ -15,45 +15,25 @@ const {
size = "default",
...props
} = Astro.props
+
+const sizeClass =
+ size === "sm" ? "text-sm" : size === "lg" ? "text-lg" : "text-base"
---
-
-
diff --git a/src/components/ui/typography/typography.astro b/src/components/ui/typography/typography.astro
index c52c7b1fa..c8fd754c6 100644
--- a/src/components/ui/typography/typography.astro
+++ b/src/components/ui/typography/typography.astro
@@ -1,6 +1,8 @@
---
import type { HTMLTag, Polymorphic } from "astro/types"
+import "./typeset.css"
+
import { cn } from "@/lib/utils"
type Size = "sm" | "default" | "lg"
@@ -12,295 +14,20 @@ const {
size = "default",
...props
} = Astro.props
+
+const sizeClass =
+ size === "sm"
+ ? "[--typeset-flow:1.125em] [--typeset-leading:1.7] [--typeset-size:0.875rem]"
+ : size === "lg"
+ ? "[--typeset-flow:1.5em] [--typeset-leading:1.8] [--typeset-size:1.125rem]"
+ : "[--typeset-flow:1.25em] [--typeset-leading:1.75] [--typeset-size:1rem]"
---
-
-
diff --git a/src/content/globals/en.yaml b/src/content/globals/en.yaml
index c488aec28..725ac508c 100644
--- a/src/content/globals/en.yaml
+++ b/src/content/globals/en.yaml
@@ -41,6 +41,10 @@ sidebar:
href: /components/alert-dialog/
- label: Alert
href: /components/alert/
+ - label: Aspect Ratio
+ href: /components/aspect-ratio/
+ - label: Attachment
+ href: /components/attachment/
- label: Avatar
href: /components/avatar/
- label: Badge
@@ -49,6 +53,8 @@ sidebar:
href: /components/banner/
- label: Breadcrumb
href: /components/breadcrumb/
+ - label: Button Group
+ href: /components/button-group/
- label: Button
href: /components/button/
- label: Card
@@ -65,6 +71,8 @@ sidebar:
href: /components/command/
- label: Dialog
href: /components/dialog/
+ - label: Drawer
+ href: /components/drawer/
- label: Dropdown Menu
href: /components/dropdown-menu/
- label: Empty
@@ -99,6 +107,8 @@ sidebar:
href: /components/native-select/
- label: Navigation Menu
href: /components/navigation-menu/
+ - label: Pagination
+ href: /components/pagination/
- label: Popover
href: /components/popover/
- label: Price
@@ -107,6 +117,8 @@ sidebar:
href: /components/radio-group/
- label: Rating
href: /components/rating/
+ - label: Resizable
+ href: /components/resizable/
- label: Section
href: /components/section/
- label: Select
@@ -133,8 +145,12 @@ sidebar:
href: /components/textarea/
- label: Theme Toggle
href: /components/theme-toggle/
+ - label: Toast
+ href: /components/toast/
- label: Toc
href: /components/toc/
+ - label: Toggle Group
+ href: /components/toggle-group/
- label: Toggle
href: /components/toggle/
- label: Tooltip
diff --git a/src/content/pages/components/aspect-ratio.mdx b/src/content/pages/components/aspect-ratio.mdx
new file mode 100644
index 000000000..dc7811b5a
--- /dev/null
+++ b/src/content/pages/components/aspect-ratio.mdx
@@ -0,0 +1,118 @@
+---
+type: doc
+title: Aspect Ratio
+description: Displays content within a desired ratio.
+---
+
+```astro live props={{ name: 'aspect-ratio' }}
+---
+import { AspectRatio } from "@/components/ui/aspect-ratio"
+---
+
+
+
+ 16:9
+
+
+```
+
+## Installation
+
+```bash
+npx shadcn@latest add @fulldev/aspect-ratio
+```
+
+## Usage
+
+```astro
+---
+import { AspectRatio } from "@/components/ui/aspect-ratio"
+---
+
+
+
+
+```
+
+## Examples
+
+### Common Ratios
+
+The ratio is width divided by height.
+
+```astro live
+---
+import { AspectRatio } from "@/components/ui/aspect-ratio"
+---
+
+
+```
+
+### Image
+
+The child controls its own crop. Use `object-cover` to fill the available area.
+
+```astro live
+---
+import { AspectRatio } from "@/components/ui/aspect-ratio"
+---
+
+
+
+
+```
+
+## API Reference
+
+| Prop | Type | Default | Description |
+| ------- | -------- | -------- | ------------------------------------------ |
+| `ratio` | `number` | required | Width divided by height, such as `16 / 9`. |
+
+`class`, `style`, and other div attributes are forwarded. String and object style values are merged with the internal ratio variable.
+
+See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/aspect-ratio) for the component source.
diff --git a/src/content/pages/components/attachment.mdx b/src/content/pages/components/attachment.mdx
new file mode 100644
index 000000000..d4a7aa411
--- /dev/null
+++ b/src/content/pages/components/attachment.mdx
@@ -0,0 +1,227 @@
+---
+type: doc
+title: Attachment
+description: Displays a file or image attachment with media, metadata, state, and actions.
+---
+
+```astro live props={{ name: 'attachment' }}
+---
+import DownloadIcon from "@lucide/astro/icons/download"
+import FileTextIcon from "@lucide/astro/icons/file-text"
+
+import {
+ Attachment,
+ AttachmentAction,
+ AttachmentActions,
+ AttachmentContent,
+ AttachmentDescription,
+ AttachmentMedia,
+ AttachmentTitle,
+} from "@/components/ui/attachment"
+---
+
+
+
+
+ LICENCE
+ Text document
+
+
+
+
+
+
+
+```
+
+## Installation
+
+```bash
+npx shadcn@latest add @fulldev/attachment
+```
+
+## Usage
+
+```astro
+---
+import FileIcon from "@lucide/astro/icons/file"
+
+import {
+ Attachment,
+ AttachmentContent,
+ AttachmentDescription,
+ AttachmentMedia,
+ AttachmentTitle,
+} from "@/components/ui/attachment"
+---
+
+
+
+
+ report.pdf
+ 2.4 MB
+
+
+```
+
+Attachment is a presentation component. It does not select, upload, remove, or persist files.
+
+## Examples
+
+### Sizes
+
+```astro live
+---
+import FileTextIcon from "@lucide/astro/icons/file-text"
+
+import {
+ Attachment,
+ AttachmentContent,
+ AttachmentDescription,
+ AttachmentMedia,
+ AttachmentTitle,
+} from "@/components/ui/attachment"
+---
+
+
+
+
+ notes.txt
+
+
+
+ brief.txt 18 KB
+
+
+
+ proposal.txt 42 KB
+
+
+```
+
+### Vertical Group
+
+```astro live
+---
+import FileIcon from "@lucide/astro/icons/file"
+import ImageIcon from "@lucide/astro/icons/image"
+
+import {
+ Attachment,
+ AttachmentContent,
+ AttachmentDescription,
+ AttachmentGroup,
+ AttachmentMedia,
+ AttachmentTitle,
+} from "@/components/ui/attachment"
+---
+
+
+
+
+ cover.jpg 1.8 MB
+
+
+
+ outline.pdf 320 KB
+
+
+```
+
+### States
+
+States provide visual status only. Your application owns the upload lifecycle and supplies truthful status text.
+
+```astro live
+---
+import FileIcon from "@lucide/astro/icons/file"
+
+import {
+ Attachment,
+ AttachmentContent,
+ AttachmentDescription,
+ AttachmentMedia,
+ AttachmentTitle,
+} from "@/components/ui/attachment"
+---
+
+
+
+
+ queued.csv Ready
+
+
+
+ report.csv Processing
+
+
+
+ archive.zip File is too large
+
+
+```
+
+### Native File Input
+
+Use a native file input to let someone choose files. Rendering selected files as attachments requires application state and is separate from this static component.
+
+```astro live
+---
+import { Input } from "@/components/ui/input"
+import { Label } from "@/components/ui/label"
+---
+
+
+ Choose files
+
+
+```
+
+## API Reference
+
+### Attachment
+
+| Prop | Type | Default | Description |
+| ------------- | ------------------------------------------------------------ | -------------- | ------------------------------- |
+| `state` | `"idle" \| "uploading" \| "processing" \| "error" \| "done"` | `"done"` | Visual file state. |
+| `size` | `"xs" \| "sm" \| "default"` | `"default"` | Controls spacing and type size. |
+| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Controls card layout. |
+
+`AttachmentMedia` accepts `variant="icon" | "image"`. `AttachmentAction` uses the Button API and supports `as`. `AttachmentTrigger` is polymorphic and covers the card, so give it visible or screen-reader-only link text. All parts forward native attributes.
+
+See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/attachment) for the component source.
diff --git a/src/content/pages/components/button-group.mdx b/src/content/pages/components/button-group.mdx
new file mode 100644
index 000000000..9a27cc65a
--- /dev/null
+++ b/src/content/pages/components/button-group.mdx
@@ -0,0 +1,166 @@
+---
+type: doc
+title: Button Group
+description: Groups related controls with connected edges and consistent focus behavior.
+---
+
+```astro live props={{ name: 'button-group' }}
+---
+import ArchiveIcon from "@lucide/astro/icons/archive"
+import MailIcon from "@lucide/astro/icons/mail"
+import TrashIcon from "@lucide/astro/icons/trash-2"
+
+import { Button } from "@/components/ui/button"
+import { ButtonGroup } from "@/components/ui/button-group"
+---
+
+
+ Archive
+ Mark unread
+
+
+```
+
+## Installation
+
+```bash
+npx shadcn@latest add @fulldev/button-group
+```
+
+## Usage
+
+```astro
+---
+import { Button } from "@/components/ui/button"
+import { ButtonGroup } from "@/components/ui/button-group"
+---
+
+
+ Save
+ Publish
+
+```
+
+Give each group an accessible name with `aria-label` or `aria-labelledby`.
+
+## Examples
+
+### Sizes
+
+Button sizes continue to work inside a group.
+
+```astro live
+---
+import { Button } from "@/components/ui/button"
+import { ButtonGroup } from "@/components/ui/button-group"
+---
+
+
+
+ List
+ Grid
+
+
+ List
+ Grid
+
+
+```
+
+### Vertical
+
+```astro live
+---
+import CopyIcon from "@lucide/astro/icons/copy"
+import SearchIcon from "@lucide/astro/icons/search"
+import SettingsIcon from "@lucide/astro/icons/settings"
+
+import { Button } from "@/components/ui/button"
+import { ButtonGroup } from "@/components/ui/button-group"
+---
+
+
+
+
+
+
+```
+
+### With Text
+
+`ButtonGroupText` is polymorphic. Render it as a label when it describes a form control.
+
+```astro live
+---
+import { ButtonGroup, ButtonGroupText } from "@/components/ui/button-group"
+import { Input } from "@/components/ui/input"
+---
+
+
+ full.dev/
+
+
+```
+
+### Nested Groups
+
+Nested groups keep a gap between related sets while preserving connected controls inside each set.
+
+```astro live
+---
+import ChevronLeftIcon from "@lucide/astro/icons/chevron-left"
+import ChevronRightIcon from "@lucide/astro/icons/chevron-right"
+
+import { Button } from "@/components/ui/button"
+import { ButtonGroup } from "@/components/ui/button-group"
+---
+
+
+
+ 1
+ 2
+ 3
+
+
+
+
+
+
+```
+
+## API Reference
+
+### ButtonGroup
+
+| Prop | Type | Default | Description |
+| ------------- | ---------------------------- | -------------- | ---------------------------------------- |
+| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Controls the layout and connected edges. |
+| `as` | `HTMLTag` | `"div"` | Changes the rendered element. |
+
+### ButtonGroupText
+
+Accepts `as` and the attributes for that HTML element.
+
+### ButtonGroupSeparator
+
+Uses the Separator API. Its `orientation` defaults to `"vertical"`.
+
+See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/button-group) for the component source.
diff --git a/src/content/pages/components/carousel.mdx b/src/content/pages/components/carousel.mdx
index 1edbb6f27..2f8ad463c 100644
--- a/src/content/pages/components/carousel.mdx
+++ b/src/content/pages/components/carousel.mdx
@@ -1,7 +1,7 @@
---
type: doc
title: Carousel
-description: A carousel with motion and swipe built using Embla.
+description: An accessible carousel built on native scrolling with Data Slot.
---
```astro live props={{ name: 'carousel' }}
@@ -15,43 +15,29 @@ import {
} from "@/components/ui/carousel"
---
-
+
-
+
1
-
+
2
-
+
3
-
-
- 4
-
-
-
-
- 5
-
-
@@ -60,9 +46,14 @@ import {
## About
-The carousel is built with
-[Embla Carousel](https://www.embla-carousel.com/) for motion and swipe. The
-Astro components follow the same composition as shadcn/ui.
+The carousel uses the
+[@data-slot/carousel](https://github.com/bejamas/data-slot/tree/main/packages/carousel)
+primitive. It supports native scrolling, keyboard navigation, optional pointer
+dragging, looped navigation, and programmatic navigation through DOM events.
+
+The carousel shows one slide at a time. `CarouselItem` components must be direct
+children of `CarouselContent`. Inactive slides are marked with `aria-hidden` and
+`inert` so their content leaves the accessibility tree and tab order.
## Installation
@@ -75,7 +66,7 @@ npx shadcn@latest add @fulldev/carousel
Manual install:
```bash
-npm install embla-carousel
+npm install @data-slot/carousel
```
Then copy the component files into `src/components/ui/carousel` and update the
@@ -83,7 +74,8 @@ imports to match your project structure.
## Usage
-```ts
+```astro
+---
import {
Carousel,
CarouselContent,
@@ -91,9 +83,8 @@ import {
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel"
-```
+---
-```astro
...
@@ -107,8 +98,6 @@ import {
## Composition
-Use the following composition to build a `Carousel`:
-
```text
Carousel
├── CarouselContent
@@ -118,12 +107,16 @@ Carousel
└── CarouselNext
```
-## Examples
+## Options
-### Sizes
+Pass Data Slot options directly to `Carousel`.
-To set the size of the items, use the `basis` utility classes on
-` `.
+| Prop | Type | Default | Description |
+| -------------- | ---------------------------- | -------------- | ----------------------------------------------------- |
+| `defaultIndex` | `number` | `0` | Initial active slide index. |
+| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Navigation and scrolling axis. |
+| `drag` | `boolean` | `false` | Enables pointer drag and swipe navigation. |
+| `loop` | `boolean` | `false` | Wraps previous, next, keyboard, and event navigation. |
```astro live
---
@@ -136,75 +129,30 @@ import {
} from "@/components/ui/carousel"
---
-
+
-
-
- 1
-
-
-
-
- 2
-
-
-
-
- 3
-
-
-
-
- 4
-
-
-
-
- 5
-
-
+ First slide
+ Second slide
+ Third slide
```
-```astro
-
-
-
- ...
- ...
- ...
-
-
-```
-
-```astro
-
-
-
- ...
- ...
- ...
-
-
-```
-
-### Spacing
+### Vertical
-To set spacing between items, use matching negative margin classes on
-` ` and padding classes on ` `.
+Give a vertical `CarouselContent` an explicit height so each item can fill its
+viewport.
```astro live
---
@@ -217,64 +165,58 @@ import {
} from "@/components/ui/carousel"
---
-
-
-
-
- Slide 1
-
-
-
-
- Slide 2
-
-
-
-
- Slide 3
-
-
-
-
- Slide 4
-
-
+
+
+ First slide
+ Second slide
+ Third slide
```
-```astro
-
-
- ...
- ...
- ...
-
-
+## Events
+
+Listen for `carousel:change` on the root to react to a new active slide.
+
+```ts
+const carousel = document.querySelector('[data-slot="carousel"]')
+
+carousel?.addEventListener("carousel:change", (event) => {
+ const { index } = (event as CustomEvent<{ index: number }>).detail
+ console.log(index)
+})
```
-```astro
-
-
- ...
- ...
- ...
-
-
+Dispatch `carousel:set` on the root to select an index or move by one slide.
+
+```ts
+carousel?.dispatchEvent(
+ new CustomEvent("carousel:set", { detail: { index: 2 } })
+)
+
+carousel?.dispatchEvent(
+ new CustomEvent("carousel:set", { detail: { action: "next" } })
+)
```
-## API Reference
+The root exposes its current index as `data-index`. Each item exposes
+`data-state="active"` or `data-state="inactive"`. Data Slot also keeps the
+previous and next controls' `disabled` and `aria-disabled` states in sync.
-See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/carousel) for more information on props.
+## API Reference
-See the [Embla docs](https://www.embla-carousel.com/) for more information on interactivity.
+See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/carousel)
+for component props and the
+[@data-slot/carousel README](https://github.com/bejamas/data-slot/tree/main/packages/carousel)
+for controller methods, events, keyboard behavior, and accessibility details.
diff --git a/src/content/pages/components/drawer.mdx b/src/content/pages/components/drawer.mdx
new file mode 100644
index 000000000..9623b0a8c
--- /dev/null
+++ b/src/content/pages/components/drawer.mdx
@@ -0,0 +1,314 @@
+---
+type: doc
+title: Drawer
+description: A swipeable panel that opens from an edge of the screen.
+---
+
+```astro live props={{ name: 'drawer' }}
+---
+import { Button } from "@/components/ui/button"
+import {
+ Drawer,
+ DrawerClose,
+ DrawerContent,
+ DrawerDescription,
+ DrawerFooter,
+ DrawerHeader,
+ DrawerTitle,
+ DrawerTrigger,
+} from "@/components/ui/drawer"
+---
+
+
+ Open drawer
+
+
+ Edit profile
+
+ Make changes to your profile and save when you are done.
+
+
+
+
+ Save changes
+ Cancel
+
+
+
+```
+
+## Installation
+
+```bash
+npx shadcn@latest add @fulldev/drawer
+```
+
+## Usage
+
+```ts
+import {
+ Drawer,
+ DrawerClose,
+ DrawerContent,
+ DrawerDescription,
+ DrawerFooter,
+ DrawerHeader,
+ DrawerTitle,
+ DrawerTrigger,
+} from "@/components/ui/drawer"
+```
+
+```astro
+
+ Open
+
+
+ Drawer title
+ Drawer description
+
+ Drawer content
+
+ Close
+
+
+
+```
+
+## Composition
+
+`DrawerContent` renders the required portal, backdrop, viewport, popup, and
+inner content structure. Use the lower-level exports when you need to customize
+that structure. Its inner content wrapper scrolls vertically when the panel
+contains more content than the available viewport.
+
+```text
+Drawer
+├── DrawerTrigger
+└── DrawerContent
+ ├── DrawerSwipeHandle
+ ├── DrawerHeader
+ │ ├── DrawerTitle
+ │ └── DrawerDescription
+ ├── content
+ └── DrawerFooter
+ └── DrawerClose
+```
+
+## Examples
+
+### Directions
+
+The swipe direction also chooses the edge where the drawer opens.
+
+```astro live
+---
+import {
+ Drawer,
+ DrawerClose,
+ DrawerContent,
+ DrawerDescription,
+ DrawerFooter,
+ DrawerHeader,
+ DrawerTitle,
+ DrawerTrigger,
+} from "@/components/ui/drawer"
+
+const directions = ["down", "up", "left", "right"] as const
+---
+
+
+ {
+ directions.map((direction) => (
+
+
+ {direction}
+
+
+
+ {direction} drawer
+
+ Swipe {direction} or use the close button.
+
+
+
+
+ Close
+
+
+
+ ))
+ }
+
+```
+
+### Nested
+
+Place a complete `Drawer` inside another drawer's content. Escape closes only
+the front drawer, then returns focus and interaction to its parent.
+
+```astro live
+---
+import {
+ Drawer,
+ DrawerClose,
+ DrawerContent,
+ DrawerDescription,
+ DrawerFooter,
+ DrawerHeader,
+ DrawerTitle,
+ DrawerTrigger,
+} from "@/components/ui/drawer"
+---
+
+
+ Open project settings
+
+
+ Project settings
+
+ Review the project or open its advanced settings.
+
+
+
+
+
+ Open advanced settings
+
+
+ Advanced settings
+
+ This drawer is nested inside the project settings drawer.
+
+
+
+
+ Close advanced settings
+
+
+
+ Close project settings
+
+
+
+```
+
+### Non-modal
+
+Pair a non-modal drawer with `showOverlay={false}` so controls outside the
+drawer remain visible and interactive.
+
+```astro live
+---
+import { Button } from "@/components/ui/button"
+import {
+ Drawer,
+ DrawerClose,
+ DrawerContent,
+ DrawerDescription,
+ DrawerFooter,
+ DrawerHeader,
+ DrawerTitle,
+ DrawerTrigger,
+} from "@/components/ui/drawer"
+---
+
+
+
+ Open non-modal drawer
+
+
+ Quick settings
+
+ The rest of the page stays available while this drawer is open.
+
+
+
+
+ Close
+
+
+
+
Outside action
+
+```
+
+`modal="trap-focus"` keeps keyboard focus inside the drawer without making the
+rest of the page inert. Also set `showOverlay={false}` when outside pointer
+interaction should remain available.
+
+### Snap point
+
+One optional snap point controls how much of the panel is visible when open. A
+fraction uses the viewport size. Pixel numbers and `px` or `rem` strings are
+also supported.
+
+```astro live
+---
+import {
+ Drawer,
+ DrawerClose,
+ DrawerContent,
+ DrawerDescription,
+ DrawerFooter,
+ DrawerHeader,
+ DrawerTitle,
+ DrawerTrigger,
+} from "@/components/ui/drawer"
+---
+
+
+ Open at 60%
+
+
+ Review changes
+
+ This drawer opens at sixty percent of the viewport height.
+
+
+
+
+ Close
+
+
+
+```
+
+## Props and events
+
+`Drawer` accepts `defaultOpen`, `modal`, `disablePointerDismissal`,
+`closeOnEscape`, `swipeDirection`, `snapPoint`, `defaultSnapPoint`, `triggerId`,
+and `defaultTriggerId`. `DrawerContent` accepts `showOverlay`,
+`showSwipeHandle`, `container`, `keepMounted`, `initialFocus`, and `finalFocus`.
+
+Use the `drawer:open`, `drawer:close`, `drawer:toggle`, and `drawer:set` DOM events
+for imperative changes. The root emits cancelable `drawer:beforechange` and
+`drawer:beforesnapchange` events, followed by `drawer:change`,
+`drawer:change-complete`, and `drawer:snapchange`.
+
+```js
+const drawer = document.querySelector('[data-slot="drawer"]')
+
+drawer?.dispatchEvent(
+ new CustomEvent("drawer:set", {
+ detail: { open: true, snapPoint: "24rem" },
+ })
+)
+```
+
+## API Reference
+
+See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/drawer) for component props.
+See the [data-slot docs](https://github.com/bejamas/data-slot/blob/main/packages/drawer/README.md) for controllers, events, focus management, detached triggers, nested drawers, and keyboard-aware viewports.
diff --git a/src/content/pages/components/navigation-menu.mdx b/src/content/pages/components/navigation-menu.mdx
index 9d0d49ba0..2072ccdab 100644
--- a/src/content/pages/components/navigation-menu.mdx
+++ b/src/content/pages/components/navigation-menu.mdx
@@ -49,7 +49,7 @@ const components = [
Getting started
-
+
+
+
+ 1
+ 2
+ 3
+
+
+
+
+```
+
+## Installation
+
+```bash
+npx shadcn@latest add @fulldev/pagination
+```
+
+## Usage
+
+```astro
+---
+import {
+ Pagination,
+ PaginationContent,
+ PaginationItem,
+ PaginationLink,
+} from "@/components/ui/pagination"
+---
+
+
+
+ 1
+ 2
+
+
+```
+
+Pagination uses normal links, so navigation works without JavaScript. `isActive` sets `aria-current="page"`.
+
+## Examples
+
+### Disabled Boundary
+
+A disabled link has no `href`, is removed from the tab order, and receives `aria-disabled="true"`.
+
+```astro live
+---
+import {
+ Pagination,
+ PaginationContent,
+ PaginationItem,
+ PaginationNext,
+ PaginationPrevious,
+} from "@/components/ui/pagination"
+---
+
+
+
+
+
+
+
+```
+
+### Compact
+
+```astro live
+---
+import {
+ Pagination,
+ PaginationContent,
+ PaginationItem,
+ PaginationLink,
+} from "@/components/ui/pagination"
+---
+
+
+
+ 1
+ 2
+ 3
+ 4
+
+
+```
+
+### RTL
+
+Directional icons mirror when the document or a containing element uses `dir="rtl"`.
+
+```astro live
+---
+import {
+ Pagination,
+ PaginationContent,
+ PaginationItem,
+ PaginationNext,
+ PaginationPrevious,
+} from "@/components/ui/pagination"
+---
+
+
+```
+
+## Composition
+
+```text
+Pagination
+└── PaginationContent
+ ├── PaginationItem
+ │ └── PaginationPrevious
+ ├── PaginationItem
+ │ └── PaginationLink
+ ├── PaginationItem
+ │ └── PaginationEllipsis
+ └── PaginationItem
+ └── PaginationNext
+```
+
+## API Reference
+
+### PaginationLink
+
+| Prop | Type | Default | Description |
+| ---------- | ------------- | -------- | ---------------------------------------------------- |
+| `href` | `string` | optional | Link destination. |
+| `isActive` | `boolean` | `false` | Marks the current page and uses the outline variant. |
+| `disabled` | `boolean` | `false` | Removes navigation and tab focus. |
+| `size` | `Button` size | `"icon"` | Controls link dimensions. |
+
+`PaginationPrevious` and `PaginationNext` accept the same link attributes plus a `text` prop. All components forward their native element attributes.
+
+See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/pagination) for the component source.
diff --git a/src/content/pages/components/resizable.mdx b/src/content/pages/components/resizable.mdx
new file mode 100644
index 000000000..80d8cd51e
--- /dev/null
+++ b/src/content/pages/components/resizable.mdx
@@ -0,0 +1,219 @@
+---
+type: doc
+title: Resizable
+description: Accessible panel groups with pointer and keyboard resizing.
+---
+
+```astro live props={{ name: 'resizable' }}
+---
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/components/ui/resizable"
+---
+
+
+
+ Sidebar
+
+
+
+ Content
+
+
+```
+
+## Installation
+
+```bash
+npx shadcn@latest add @fulldev/resizable
+```
+
+## Usage
+
+```astro
+---
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/components/ui/resizable"
+---
+
+
+ Sidebar
+
+ Content
+
+```
+
+A group needs one handle between each pair of panels. Give every handle an accessible label. Drag a handle with a pointer, or focus it and use the arrow keys.
+
+## Examples
+
+### Vertical
+
+Use `direction="vertical"` for rows. The handle responds to the up and down arrow keys.
+
+```astro live
+---
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/components/ui/resizable"
+---
+
+
+
+ Header
+
+
+
+ Body
+
+
+```
+
+### Collapsible
+
+Focus the handle and press `Enter` to collapse or restore the first panel. Dragging through the minimum size also collapses it.
+
+```astro live
+---
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/components/ui/resizable"
+---
+
+
+
+ Collapsible sidebar
+
+
+
+ Main content
+
+
+```
+
+### Nested
+
+Each group owns only its direct panels and handles, so a panel can safely contain another resizable group.
+
+```astro live
+---
+import {
+ ResizableHandle,
+ ResizablePanel,
+ ResizablePanelGroup,
+} from "@/components/ui/resizable"
+---
+
+
+
+ Navigation
+
+
+
+
+
+ Editor
+
+
+
+ Console
+
+
+
+
+```
+
+## Keyboard Controls
+
+| Key | Action |
+| --------------------- | ------------------------------------------------------------ |
+| Arrow keys | Resize by `keyboardResizeBy` in the group direction. |
+| `Shift` + arrow | Resize to the available limit. |
+| `Home` / `End` | Minimize or maximize the panel before the handle. |
+| `Enter` | Collapse or restore the collapsible panel before the handle. |
+| `F6` / `Shift` + `F6` | Focus the next or previous handle in the group. |
+
+## API Reference
+
+### ResizablePanelGroup
+
+`Resizable` is an alias for `ResizablePanelGroup`.
+
+| Prop | Type | Default | Description |
+| ------------------ | ---------------------------- | -------------- | -------------------------------------- |
+| `direction` | `"horizontal" \| "vertical"` | `"horizontal"` | Sets the layout and resize axis. |
+| `keyboardResizeBy` | `number` | `10` | Percentage moved by an arrow keypress. |
+
+### ResizablePanel
+
+All sizes are percentages between 0 and 100.
+
+| Prop | Type | Default | Description |
+| --------------- | --------- | ---------- | ------------------------------------------- |
+| `defaultSize` | `number` | even split | Initial panel size. |
+| `minSize` | `number` | `0` | Minimum expanded size. |
+| `maxSize` | `number` | `100` | Maximum size. |
+| `collapsible` | `boolean` | `false` | Allows the panel to use its collapsed size. |
+| `collapsedSize` | `number` | `0` | Size used while collapsed. |
+
+### ResizableHandle
+
+| Prop | Type | Default | Description |
+| ------------ | --------- | ------- | ---------------------------------------- |
+| `withHandle` | `boolean` | `false` | Shows a visible grip on the separator. |
+| `disabled` | `boolean` | `false` | Blocks keyboard resizing on this handle. |
+
+The root emits `resizable:change` with `{ layout: number[] }` and `resizable:dragging` with `{ dragging: boolean }`. Dispatch `resizable:set` with `{ layout: number[] }` to set a layout from client code.
+
+See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/resizable) for the component source.
+See the [data-slot docs](https://github.com/bejamas/data-slot/blob/main/packages/resizable/README.md) for constraints, controller methods, and event details.
diff --git a/src/content/pages/components/select.mdx b/src/content/pages/components/select.mdx
index 94d8cd4f2..d891c3a8e 100644
--- a/src/content/pages/components/select.mdx
+++ b/src/content/pages/components/select.mdx
@@ -96,8 +96,11 @@ Select
Use the `position` prop on `SelectContent` to control alignment. When
`position="item-aligned"` (default), the popup positions so the selected item
-appears over the trigger. When `position="popper"`, the popup aligns to the
-trigger edge.
+appears over the trigger. When `position="popper"`, Data Slot positions the
+popup against the trigger with its default collision handling. Set `side`,
+`align`, `sideOffset`, `alignOffset`, `avoidCollisions`, or
+`collisionPadding` on `Select` or `SelectContent` when you need a different
+placement.
```astro live
---
diff --git a/src/content/pages/components/slider.mdx b/src/content/pages/components/slider.mdx
index 3063598aa..6e9bde1d8 100644
--- a/src/content/pages/components/slider.mdx
+++ b/src/content/pages/components/slider.mdx
@@ -9,13 +9,7 @@ description: An input where the user selects a value from within a given range.
import { Slider } from "@/components/ui/slider"
---
-
+
```
## Installation
@@ -36,6 +30,10 @@ import { Slider } from "@/components/ui/slider"
```
+Thumbs use `thumbAlignment="edge"` by default, so they stay within the track at
+the minimum and maximum. Use `thumbAlignment="center"` to center them over the
+track endpoints. A single value renders one thumb; a pair renders a range.
+
## Examples
### Range
@@ -47,13 +45,7 @@ Use an array with two values for a range slider.
import { Slider } from "@/components/ui/slider"
---
-
+
```
### Vertical
@@ -71,7 +63,6 @@ import { Slider } from "@/components/ui/slider"
defaultValue={60}
max={100}
step={5}
- thumbAlignment="edge"
class="h-full"
/>
@@ -86,12 +77,7 @@ Use the `disabled` prop to disable the slider.
import { Slider } from "@/components/ui/slider"
---
-
+
```
## API Reference
diff --git a/src/content/pages/components/toast.mdx b/src/content/pages/components/toast.mdx
new file mode 100644
index 000000000..9ce336d51
--- /dev/null
+++ b/src/content/pages/components/toast.mdx
@@ -0,0 +1,202 @@
+---
+type: doc
+title: Toast
+description: A brief notification that appears without interrupting the user.
+---
+
+```astro live props={{ name: 'toast' }}
+---
+import { Button } from "@/components/ui/button"
+import { Toaster } from "@/components/ui/toast"
+---
+
+
+ Show toast
+ Toast with action
+
+
+
+
+
+```
+
+## Installation
+
+```bash
+npx shadcn@latest add @fulldev/toast
+```
+
+## Usage
+
+Place one `Toaster` in the page shell or layout. Give it an ID when commands
+need a stable target.
+
+```astro
+---
+import { Toaster } from "@/components/ui/toast"
+---
+
+
+```
+
+Show a notification by dispatching a `toast:show` event on that root.
+
+```js
+const toaster = document.getElementById("notifications")
+
+toaster?.dispatchEvent(
+ new CustomEvent("toast:show", {
+ detail: {
+ title: "Changes saved",
+ description: "All updates are synced.",
+ type: "success",
+ },
+ })
+)
+```
+
+When Astro's `ClientRouter` can replace the page containing your trigger,
+reconnect page-specific event handlers on `astro:page-load`. Keep a toaster in
+the shared layout when the notification API should remain available across
+route changes. Active notifications are reset during a route swap; persist any
+notification data in your own application state when it must survive.
+
+## Options
+
+`Toaster` accepts these runtime options as props:
+
+- `limit`: maximum visible notifications, default `3`
+- `duration`: automatic dismissal delay in milliseconds, default `5000`; use
+ `0` for persistent notifications
+- `position`: `top-left`, `top-center`, `top-right`, `bottom-left`,
+ `bottom-center`, or `bottom-right`
+- `pauseOnHover` and `pauseOnFocus`: pause active timers during interaction
+- `portal`: move the viewport to `document.body`
+
+Toast data accepts `id`, `title`, `description`, `type`, `duration`, `action`,
+`dismissible`, `closeButtonAriaLabel`, and `testId`. `title` is required. Types
+are `default`, `success`, `error`, `warning`, `info`, and `loading`.
+
+## Commands
+
+The root listens for framework-neutral DOM events.
+
+```js
+// Show and keep a stable ID for later updates.
+toaster.dispatchEvent(
+ new CustomEvent("toast:show", {
+ detail: { id: "upload", title: "Uploading", type: "loading", duration: 0 },
+ })
+)
+
+// Patch an active toast.
+toaster.dispatchEvent(
+ new CustomEvent("toast:update", {
+ detail: { id: "upload", title: "Upload complete", type: "success" },
+ })
+)
+
+// Dismiss one toast or clear all active toasts.
+toaster.dispatchEvent(
+ new CustomEvent("toast:dismiss", { detail: { id: "upload" } })
+)
+toaster.dispatchEvent(new CustomEvent("toast:clear"))
+```
+
+The root emits `toast:change` with `{ id, action: "show" | "dismiss" }` and
+`toast:action` with `{ id, value }`. Listen for `toast:action` to handle action
+buttons.
+
+```js
+toaster.addEventListener("toast:action", (event) => {
+ if (event.detail.value === "undo-event") {
+ // Undo the operation here.
+ }
+})
+```
+
+For controller access, import `createToast` from `@data-slot/toast`. Its
+`show`, `update`, `promise`, `dismiss`, and `dismissAll` methods use the same
+data model. The Astro `Toast` component already initializes roots, so create a
+controller directly only when you own initialization yourself.
+
+## Custom template
+
+`Toaster` includes the standard template and viewport. Use the lower-level
+parts when you need different markup or classes.
+
+```astro
+---
+import {
+ Toast,
+ ToastAction,
+ ToastClose,
+ ToastContent,
+ ToastDescription,
+ ToastIcon,
+ ToastItem,
+ ToastTemplate,
+ ToastTitle,
+ ToastViewport,
+} from "@/components/ui/toast"
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## API Reference
+
+See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/toast) for component props.
+See the [data-slot docs](https://github.com/bejamas/data-slot/blob/main/packages/toast/README.md) for controller methods, promise notifications, timers, stacking, swipe dismissal, and events.
diff --git a/src/content/pages/components/toggle-group.mdx b/src/content/pages/components/toggle-group.mdx
new file mode 100644
index 000000000..64f85f9f7
--- /dev/null
+++ b/src/content/pages/components/toggle-group.mdx
@@ -0,0 +1,234 @@
+---
+type: doc
+title: Toggle Group
+description: A set of two-state buttons that can be toggled independently or as a single choice.
+---
+
+```astro live props={{ name: 'toggle-group' }}
+---
+import TextAlignCenterIcon from "@lucide/astro/icons/text-align-center"
+import TextAlignEndIcon from "@lucide/astro/icons/text-align-end"
+import TextAlignStartIcon from "@lucide/astro/icons/text-align-start"
+
+import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
+---
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## Installation
+
+```bash
+npx shadcn@latest add @fulldev/toggle-group
+```
+
+## Usage
+
+```astro
+---
+import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
+---
+
+
+ Left
+ Center
+ Right
+
+```
+
+## Examples
+
+### Multiple
+
+Use `multiple` with an array or a space-separated string to select more than one item.
+
+```astro live
+---
+import BoldIcon from "@lucide/astro/icons/bold"
+import ItalicIcon from "@lucide/astro/icons/italic"
+import UnderlineIcon from "@lucide/astro/icons/underline"
+
+import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
+---
+
+
+
+
+
+
+```
+
+### Variants and Sizes
+
+Set `variant` and `size` on the group to style every item. Set `spacing={0}` to join outlined items.
+
+```astro live
+---
+import BoldIcon from "@lucide/astro/icons/bold"
+import ItalicIcon from "@lucide/astro/icons/italic"
+import UnderlineIcon from "@lucide/astro/icons/underline"
+
+import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
+---
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### Vertical
+
+The arrow keys follow the group orientation. `Home` and `End` move to the first and last enabled items.
+
+```astro live
+---
+import ListIcon from "@lucide/astro/icons/list"
+import ListOrderedIcon from "@lucide/astro/icons/list-ordered"
+import ListTodoIcon from "@lucide/astro/icons/list-todo"
+
+import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
+---
+
+
+
+
+
+
+```
+
+### Disabled
+
+Disable the whole group or a single item.
+
+```astro live
+---
+import BoldIcon from "@lucide/astro/icons/bold"
+import ItalicIcon from "@lucide/astro/icons/italic"
+import UnderlineIcon from "@lucide/astro/icons/underline"
+
+import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
+---
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## API Reference
+
+### ToggleGroup
+
+| Prop | Type | Default | Description |
+| -------------- | ---------------------------- | -------------- | -------------------------------------------- |
+| `defaultValue` | `string \| string[]` | `[]` | Initial selected value or values. |
+| `multiple` | `boolean` | `false` | Allows multiple selected items. |
+| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Sets arrow-key navigation direction. |
+| `loop` | `boolean` | `true` | Wraps keyboard focus at either end. |
+| `disabled` | `boolean` | `false` | Blocks interaction for the whole group. |
+| `variant` | `"default" \| "outline"` | item default | Applies a visual variant to every item. |
+| `size` | `"sm" \| "default" \| "lg"` | item default | Applies a size to every item. |
+| `spacing` | `number` | `2` | Gap between items in Tailwind spacing units. |
+
+### ToggleGroupItem
+
+| Prop | Type | Default | Description |
+| ---------- | --------------------------- | ----------- | --------------------------------------------- |
+| `value` | `string` | required | Unique value for the item. |
+| `disabled` | `boolean` | `false` | Disables the item. |
+| `variant` | `"default" \| "outline"` | `"default"` | Item variant when the group does not set one. |
+| `size` | `"sm" \| "default" \| "lg"` | `"default"` | Item size when the group does not set one. |
+
+The root emits `toggle-group:change` with `{ value: string[] }`. Dispatch `toggle-group:set` with `{ value: string | string[] }` to update it from client code.
+
+See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/toggle-group) for the component source.
+See the [data-slot docs](https://github.com/bejamas/data-slot/blob/main/packages/toggle-group/README.md) for controller methods and full keyboard behavior.
diff --git a/src/content/pages/components/typography.mdx b/src/content/pages/components/typography.mdx
index 521c8ac24..9571a296e 100644
--- a/src/content/pages/components/typography.mdx
+++ b/src/content/pages/components/typography.mdx
@@ -55,6 +55,14 @@ import {
npx shadcn@latest add @fulldev/typography
```
+## Typeset
+
+`Typography` uses the recommended
+[shadcn Typeset](https://ui.shadcn.com/docs/typeset) stylesheet. Typeset applies
+one readable scale and vertical rhythm to semantic HTML, including headings,
+paragraphs, links, lists, code, blockquotes, media, and tables. It also supports
+task lists, footnotes, definition lists, keyboard keys, and print styles.
+
## Usage
Use `Typography` as a wrapper around rendered content, markdown output, or
@@ -63,11 +71,11 @@ Use the individual typography components when you want explicit primitives in a
component example or custom layout.
Every typography component accepts `size="sm"`, `size="default"`, or
-`size="lg"`. The default size keeps body text at the base font size.
-On the `Typography` wrapper, `size` only scales the wrapper-level heading and
-lead styles. Regular child prose such as paragraphs, lists, blockquotes, code,
-small text, and tables keeps its normal default size. Use the individual
-components' own `size` prop when those elements need to change size.
+`size="lg"`. On `Typography`, the size preset changes the body size, line
+height, and flow spacing together so the whole document keeps a consistent
+rhythm. The default preset uses a `1rem` body size, `1.75` line height, and
+`1.25em` flow spacing. Use the individual components' size prop when a
+standalone element needs a different size.
```ts
import {
@@ -96,7 +104,7 @@ The `Typography` wrapper styles supported child elements directly. Headings,
paragraphs, links, blockquotes, lists, tables, inline code, and preformatted code
can be regular HTML.
-```astro live
+```astro live props={{ name: 'typography' }}
---
import { Typography } from "@/components/ui/typography"
---
@@ -123,8 +131,28 @@ import { Typography } from "@/components/ui/typography"
```
+## Opt out
+
+Add `data-not-typeset` or `class="not-typeset"` to an embedded interface that
+should keep its component styles. The opt-out includes every descendant, so put
+it on the smallest wrapper that owns the interface. A nested `Typography`
+cannot reactivate Typeset inside an opted-out subtree.
+
+```astro
+
+ This paragraph uses Typeset.
+
+
+
+
+
+```
+
## Child components
+The standalone parts render their semantic element with Tailwind classes. They
+preserve the same `size` props without depending on a `Typography` ancestor.
+
### TypographyH1
```astro live
@@ -284,6 +312,8 @@ import { TypographyLead } from "@/components/ui/typography"
headings, paragraphs, lists, tables, and inline code.
- Use the individual typography primitives when you want explicit semantic
composition inside a component example or a custom layout.
+- Wrap wide tables or other wide content in `class="typeset-scroll"` to retain
+ native table semantics with horizontal overflow.
## API Reference
diff --git a/src/content/pages/docs/installation.mdx b/src/content/pages/docs/installation.mdx
index a72762ed8..81dfea7ce 100644
--- a/src/content/pages/docs/installation.mdx
+++ b/src/content/pages/docs/installation.mdx
@@ -133,13 +133,13 @@ pieces you need.
## Data Slot 1.x upgrades
-Interactive components require Data Slot 1.0.1 or newer within 1.x. Updating npm
+Interactive components require Data Slot 1.0.2 or newer within 1.x. Updating npm
versions alone does not update component files previously copied by the registry.
Reinstall the affected registry items and merge their source changes with your
customizations.
-Components use Data Slot's own initialization and release their controllers before
-Astro's `ClientRouter` swaps the page. Component state is reinitialized on navigation;
+Components use Data Slot's own initialization. In projects using Astro's
+`ClientRouter`, they release their controllers before it swaps the page. Component state is reinitialized on navigation;
this integration does not preserve interactive state across `transition:persist`.
Select, Tooltip, Hover Card and Navigation Menu now use Data Slot's recommended
diff --git a/src/styles/global.css b/src/styles/global.css
index 673bc229b..87efb78fc 100644
--- a/src/styles/global.css
+++ b/src/styles/global.css
@@ -115,6 +115,8 @@
}
@theme inline {
+ --font-heading: var(--font-sans);
+
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
diff --git a/tests/data-slot.spec.ts b/tests/data-slot.spec.ts
index 12d41db58..842a25833 100644
--- a/tests/data-slot.spec.ts
+++ b/tests/data-slot.spec.ts
@@ -281,6 +281,355 @@ test("toggle: pointer and keyboard pressed state", async ({ page }) => {
await expect(toggle).toHaveAttribute("aria-pressed", "false")
})
+test("drawer: focus, dismissal, repeated opening and nested Escape", async ({
+ page,
+}) => {
+ await open(page, "drawer")
+ const trigger = demo(page).getByRole("button", { name: "Open drawer" })
+ const drawer = demo(page).locator('[data-slot="drawer"]')
+ const popup = page.getByRole("dialog", { name: "Edit profile" })
+
+ for (let i = 0; i < 2; i++) {
+ await trigger.press("Enter")
+ await expect(popup).toBeVisible()
+ await expect(popup).toBeFocused()
+ await page.keyboard.press("Escape")
+ await expect(popup).toBeHidden()
+ await expect(trigger).toBeFocused()
+ }
+
+ await trigger.click()
+ await expect(drawer).toHaveAttribute("data-state", "open")
+ await page.mouse.click(2, 2)
+ await expect(popup).toBeHidden()
+
+ const outer = page.locator("#nested-drawer-example")
+ const outerPopup = page.getByRole("dialog", {
+ name: "Project settings",
+ exact: true,
+ })
+ const nestedPopup = page.getByRole("dialog", {
+ name: "Advanced settings",
+ exact: true,
+ })
+ await outer
+ .getByRole("button", { name: "Open project settings", exact: true })
+ .click()
+ await expect(outerPopup).toBeVisible()
+ await page
+ .getByRole("button", { name: "Open advanced settings", exact: true })
+ .click()
+ await expect(nestedPopup).toBeVisible()
+ await expect(
+ page.locator('[data-slot="drawer-popup"][data-nested-drawer-open]')
+ ).toBeVisible()
+ await page.keyboard.press("Escape")
+ await expect(nestedPopup).toBeHidden()
+ await expect(outerPopup).toBeVisible()
+ await page.keyboard.press("Escape")
+ await expect(outerPopup).toBeHidden()
+})
+
+test("toast: events, actions, dismissal, paused timers and navigation", async ({
+ page,
+}) => {
+ await open(page, "toast")
+ const root = page.locator("#example-toaster")
+ const items = page.locator('[data-slot="toast-item"]')
+
+ await root.evaluate((element) => {
+ element.addEventListener("toast:change", (event) => {
+ const detail = (event as CustomEvent).detail
+ element.setAttribute(
+ "data-test-changes",
+ [
+ element.getAttribute("data-test-changes"),
+ `${detail.action}:${detail.id}`,
+ ]
+ .filter(Boolean)
+ .join(",")
+ )
+ })
+ element.addEventListener("toast:action", (event) => {
+ const detail = (event as CustomEvent).detail
+ element.setAttribute("data-test-action", `${detail.id}:${detail.value}`)
+ })
+ })
+
+ await demo(page).getByRole("button", { name: "Show toast" }).click()
+ await expect(items).toHaveCount(1)
+ const basic = items.first()
+ await expect(basic).toHaveAttribute("data-type", "success")
+ await expect(basic).toContainText("Event created")
+ await expect(basic).toContainText("Sunday, December 3 at 9:00 AM")
+ await basic.getByRole("button", { name: "Close notification" }).click()
+ await expect(items).toHaveCount(0)
+ await expect(root).toHaveAttribute(
+ "data-test-changes",
+ /show:toast-1,dismiss:toast-1/
+ )
+
+ await demo(page).getByRole("button", { name: "Toast with action" }).click()
+ const actionToast = items.filter({ hasText: "You can undo this action." })
+ await actionToast.getByRole("button", { name: "Undo" }).click()
+ await expect(root).toHaveAttribute("data-test-action", /:undo-event$/)
+ await expect(actionToast).toHaveCount(0)
+
+ await root.evaluate((element) =>
+ element.dispatchEvent(
+ new CustomEvent("toast:show", {
+ detail: { id: "paused-toast", title: "Paused", duration: 200 },
+ })
+ )
+ )
+ const viewport = page.locator('[data-slot="toast-viewport"]')
+ await viewport.evaluate((element) =>
+ element.dispatchEvent(new PointerEvent("pointerenter", { bubbles: true }))
+ )
+ const pausedToast = items.filter({ hasText: "Paused" })
+ await expect(pausedToast).toBeVisible()
+ await page.waitForTimeout(300)
+ await expect(pausedToast).toBeVisible()
+ await viewport.evaluate((element) =>
+ element.dispatchEvent(new PointerEvent("pointerleave", { bubbles: true }))
+ )
+ await expect(pausedToast).toHaveCount(0)
+
+ const pagination = page.getByRole("navigation", {
+ name: "Document pagination",
+ })
+ await page.addStyleTag({
+ content: "@view-transition { navigation: none; }",
+ })
+ await pagination.locator('a[href="/components/toc/"]').click()
+ await expect(page).toHaveURL(/\/components\/toc\/$/)
+ await page.addStyleTag({
+ content: "@view-transition { navigation: none; }",
+ })
+ await page
+ .getByRole("navigation", { name: "Document pagination" })
+ .locator('a[href="/components/toast/"]')
+ .click()
+ await expect(page).toHaveURL(/\/components\/toast\/$/)
+ await expect(
+ demo(page).getByRole("button", { name: "Show toast" })
+ ).toBeVisible()
+ await demo(page).getByRole("button", { name: "Show toast" }).click()
+ await expect(page.locator('[data-slot="toast-item"]')).toHaveCount(1)
+})
+
+test("toggle group: single, multiple, keyboard and disabled states", async ({
+ page,
+}) => {
+ await open(page, "toggle-group")
+ const previews = page.locator(".live-code-layout")
+ const single = previews.nth(0).locator('[data-slot="toggle-group"]')
+ const left = single.getByRole("button", { name: "Align left" })
+ const center = single.getByRole("button", { name: "Align center" })
+ const right = single.getByRole("button", { name: "Align right" })
+
+ await expect(center).toHaveAttribute("aria-pressed", "true")
+ await left.click()
+ await expect(left).toHaveAttribute("aria-pressed", "true")
+ await expect(center).toHaveAttribute("aria-pressed", "false")
+ await left.press("ArrowRight")
+ await expect(center).toBeFocused()
+ await center.press("End")
+ await expect(right).toBeFocused()
+ await right.press("Space")
+ await expect(right).toHaveAttribute("aria-pressed", "true")
+ await expect(left).toHaveAttribute("aria-pressed", "false")
+
+ const multiple = previews.nth(1).locator('[data-slot="toggle-group"]')
+ const bold = multiple.getByRole("button", { name: "Bold" })
+ const italic = multiple.getByRole("button", { name: "Italic" })
+ const underline = multiple.getByRole("button", { name: "Underline" })
+ await expect(bold).toHaveAttribute("aria-pressed", "true")
+ await expect(italic).toHaveAttribute("aria-pressed", "true")
+ await underline.click()
+ await expect(underline).toHaveAttribute("aria-pressed", "true")
+ await expect(bold).toHaveAttribute("aria-pressed", "true")
+ await bold.press("Space")
+ await expect(bold).toHaveAttribute("aria-pressed", "false")
+
+ const disabled = previews.nth(4).locator('[data-slot="toggle-group"]')
+ await expect(disabled.nth(0).getByRole("button").first()).toBeDisabled()
+ await expect(disabled.nth(1).getByRole("button").nth(2)).toBeDisabled()
+})
+
+test("resizable: pointer, keyboard bounds and collapsible panel", async ({
+ page,
+}) => {
+ await open(page, "resizable")
+ const previews = page.locator(".live-code-layout")
+ const handle = previews
+ .nth(0)
+ .getByRole("separator", { name: "Resize sidebar and content" })
+
+ await expect(handle).toHaveAttribute("aria-valuenow", "35")
+ await handle.press("ArrowRight")
+ await expect(handle).toHaveAttribute("aria-valuenow", "45")
+ await handle.press("Home")
+ await expect(handle).toHaveAttribute("aria-valuenow", "20")
+ await handle.press("End")
+ await expect(handle).toHaveAttribute("aria-valuenow", "70")
+
+ const box = await handle.boundingBox()
+ if (!box) throw new Error("Resizable handle has no layout box")
+ await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2)
+ await page.mouse.down()
+ await page.mouse.move(box.x - 80, box.y + box.height / 2, { steps: 4 })
+ await page.mouse.up()
+ await expect(handle).not.toHaveAttribute("aria-valuenow", "70")
+
+ const verticalHandle = previews.nth(1).getByRole("separator", {
+ name: "Resize header and body",
+ })
+ await expect(verticalHandle).toHaveAttribute("aria-valuenow", "35")
+ await verticalHandle.press("ArrowDown")
+ await expect(verticalHandle).toHaveAttribute("aria-valuenow", "45")
+
+ const collapsibleDemo = previews.nth(2)
+ const collapsibleHandle = collapsibleDemo.getByRole("separator", {
+ name: "Resize or collapse sidebar",
+ })
+ const panel = collapsibleDemo.locator('[data-slot="resizable-panel"]').first()
+ await collapsibleHandle.press("Enter")
+ await expect(panel).toHaveAttribute("data-collapsed", "")
+ await expect(collapsibleHandle).toHaveAttribute("aria-valuenow", "0")
+ await collapsibleHandle.press("Enter")
+ await expect(panel).toHaveAttribute("data-expanded", "")
+ await expect(collapsibleHandle).toHaveAttribute("aria-valuenow", "30")
+
+ const nestedDemo = previews.nth(3)
+ const outerHandle = nestedDemo.getByRole("separator", {
+ name: "Resize navigation and workspace",
+ })
+ const innerHandle = nestedDemo.getByRole("separator", {
+ name: "Resize editor and console",
+ })
+ await expect(outerHandle).toHaveAttribute("aria-valuenow", "35")
+ await expect(innerHandle).toHaveAttribute("aria-valuenow", "60")
+ await innerHandle.press("ArrowDown")
+ await expect(innerHandle).toHaveAttribute("aria-valuenow", "70")
+ await expect(outerHandle).toHaveAttribute("aria-valuenow", "35")
+})
+
+test("carousel: controls, full-slide state and keyboard navigation", async ({
+ page,
+}) => {
+ await open(page, "carousel")
+ const root = demo(page).locator('[data-slot="carousel"]')
+ const content = root.locator('[data-slot="carousel-content"]')
+ const items = root.locator('[data-slot="carousel-item"]')
+ const previous = root.getByRole("button", { name: "Previous slide" })
+ const next = root.getByRole("button", { name: "Next slide" })
+
+ await expect(root).toHaveAttribute("data-index", "0")
+ await expect(previous).toBeDisabled()
+ await expect(items.nth(0)).toHaveAttribute("data-state", "active")
+ await expect(items.nth(1)).toHaveAttribute("aria-hidden", "true")
+ await expect(items.nth(1)).toHaveAttribute("inert", "")
+ const contentBox = await content.boundingBox()
+ const itemBox = await items.nth(0).boundingBox()
+ if (!contentBox || !itemBox) throw new Error("Carousel has no layout box")
+ expect(Math.abs(contentBox.width - itemBox.width)).toBeLessThanOrEqual(1)
+
+ await page.mouse.move(
+ contentBox.x + contentBox.width * 0.75,
+ contentBox.y + contentBox.height / 2
+ )
+ await page.mouse.down()
+ await page.mouse.move(
+ contentBox.x + contentBox.width * 0.15,
+ contentBox.y + contentBox.height / 2,
+ { steps: 6 }
+ )
+ await page.mouse.up()
+ await expect(root).toHaveAttribute("data-index", "1")
+
+ await previous.click()
+ await expect(root).toHaveAttribute("data-index", "0")
+ await next.click()
+ await expect(root).toHaveAttribute("data-index", "1")
+ await expect(items.nth(1)).toHaveAttribute("data-state", "active")
+ await previous.click()
+ await expect(root).toHaveAttribute("data-index", "0")
+
+ await next.focus()
+ await next.press("ArrowRight")
+ await expect(root).toHaveAttribute("data-index", "1")
+ await next.press("End")
+ await expect(root).toHaveAttribute("data-index", "2")
+ await expect(next).toBeDisabled()
+ await previous.press("Home")
+ await expect(root).toHaveAttribute("data-index", "0")
+
+ const loopRoot = page
+ .locator(".live-code-layout")
+ .nth(1)
+ .locator('[data-slot="carousel"]')
+ const loopItems = loopRoot.locator('[data-slot="carousel-item"]')
+ const loopPrevious = loopRoot.getByRole("button", { name: "Previous slide" })
+ const loopNext = loopRoot.getByRole("button", { name: "Next slide" })
+ await expect(loopRoot).toHaveAttribute("data-index", "1")
+ await expect(loopItems.nth(1)).toHaveAttribute("data-state", "active")
+ await loopPrevious.click()
+ await expect(loopRoot).toHaveAttribute("data-index", "0")
+ await loopPrevious.click()
+ await expect(loopRoot).toHaveAttribute("data-index", "2")
+ await loopNext.click()
+ await expect(loopRoot).toHaveAttribute("data-index", "0")
+
+ const verticalRoot = page
+ .locator(".live-code-layout")
+ .nth(2)
+ .locator('[data-slot="carousel"]')
+ const verticalContent = verticalRoot.locator('[data-slot="carousel-content"]')
+ const verticalItems = verticalRoot.locator('[data-slot="carousel-item"]')
+ const verticalNext = verticalRoot.getByRole("button", {
+ name: "Next slide",
+ })
+ const verticalPrevious = verticalRoot.getByRole("button", {
+ name: "Previous slide",
+ })
+ await verticalContent.scrollIntoViewIfNeeded()
+ const verticalContentBox = await verticalContent.boundingBox()
+ const verticalItemBox = await verticalItems.nth(0).boundingBox()
+ if (!verticalContentBox || !verticalItemBox)
+ throw new Error("Vertical carousel has no layout box")
+ expect(
+ Math.abs(verticalContentBox.height - verticalItemBox.height)
+ ).toBeLessThanOrEqual(1)
+ await verticalNext.click()
+ await expect(verticalRoot).toHaveAttribute("data-index", "1")
+ await verticalPrevious.click()
+ await expect(verticalRoot).toHaveAttribute("data-index", "0")
+ await expect
+ .poll(() => verticalContent.evaluate((element) => element.scrollTop))
+ .toBeLessThan(verticalContentBox.height * 0.2)
+ await verticalNext.focus()
+ await verticalNext.press("ArrowDown")
+ await expect(verticalRoot).toHaveAttribute("data-index", "1")
+ await expect
+ .poll(() => verticalContent.evaluate((element) => element.scrollTop))
+ .toBeGreaterThan(verticalContentBox.height * 0.8)
+ const verticalDragBox = await verticalContent.boundingBox()
+ if (!verticalDragBox) throw new Error("Vertical carousel moved out of view")
+ await page.mouse.move(
+ verticalDragBox.x + verticalDragBox.width / 2,
+ verticalDragBox.y + verticalDragBox.height * 0.75
+ )
+ await page.mouse.down()
+ await page.mouse.move(
+ verticalDragBox.x + verticalDragBox.width / 2,
+ verticalDragBox.y + verticalDragBox.height * 0.15,
+ { steps: 6 }
+ )
+ await page.mouse.up()
+ await expect(verticalRoot).toHaveAttribute("data-index", "2")
+})
+
test("command: new trigger slot, nested command filtering and dismissal", async ({
page,
}) => {
diff --git a/tests/visual.spec.ts b/tests/visual.spec.ts
index 447ce686d..d4464157b 100644
--- a/tests/visual.spec.ts
+++ b/tests/visual.spec.ts
@@ -12,6 +12,19 @@ const pages = [
"/components/accordion",
"/components/table",
"/components/select",
+ "/components/attachment",
+ "/components/aspect-ratio",
+ "/components/button-group",
+ "/components/carousel",
+ "/components/combobox",
+ "/components/drawer",
+ "/components/navigation-menu",
+ "/components/pagination",
+ "/components/resizable",
+ "/components/slider",
+ "/components/toast",
+ "/components/toggle-group",
+ "/components/typography",
]
for (const path of pages) {