fulldev-ui 0.9.2 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +100 -16
  3. package/package.json +3 -2
  4. package/public/r/accordion.json +3 -5
  5. package/public/r/alert-dialog.json +1 -1
  6. package/public/r/alert.json +0 -5
  7. package/public/r/article-1.json +1 -1
  8. package/public/r/article-2.json +1 -1
  9. package/public/r/articles-1.json +1 -1
  10. package/public/r/articles-2.json +1 -1
  11. package/public/r/articles-3.json +1 -1
  12. package/public/r/avatar.json +1 -16
  13. package/public/r/badge.json +1 -1
  14. package/public/r/banner-1.json +5 -3
  15. package/public/r/banner-2.json +1 -1
  16. package/public/r/banner.json +5 -3
  17. package/public/r/blocks-1.json +6 -3
  18. package/public/r/breadcrumb.json +4 -4
  19. package/public/r/button.json +1 -1
  20. package/public/r/card.json +4 -4
  21. package/public/r/carousel.json +5 -5
  22. package/public/r/checkbox.json +1 -1
  23. package/public/r/combobox.json +8 -8
  24. package/public/r/command.json +6 -6
  25. package/public/r/components.json +1 -6
  26. package/public/r/contact-1.json +4 -2
  27. package/public/r/contact-2.json +4 -2
  28. package/public/r/contact-3.json +11 -3
  29. package/public/r/content-1.json +11 -3
  30. package/public/r/content-2.json +11 -3
  31. package/public/r/content-3.json +7 -1
  32. package/public/r/content-4.json +11 -3
  33. package/public/r/cta-2.json +7 -1
  34. package/public/r/cta-4.json +7 -1
  35. package/public/r/cta-5.json +11 -3
  36. package/public/r/cta-6.json +7 -1
  37. package/public/r/dialog.json +6 -6
  38. package/public/r/doc-1.json +6 -3
  39. package/public/r/dropdown-menu.json +9 -11
  40. package/public/r/features-1.json +5 -3
  41. package/public/r/features-2.json +5 -3
  42. package/public/r/features-4.json +5 -3
  43. package/public/r/features-5.json +4 -2
  44. package/public/r/field.json +2 -7
  45. package/public/r/footer-1.json +5 -3
  46. package/public/r/footer-2.json +5 -3
  47. package/public/r/footer-3.json +5 -3
  48. package/public/r/header-1.json +1 -1
  49. package/public/r/header.json +3 -0
  50. package/public/r/hero-13.json +1 -1
  51. package/public/r/hero-4.json +5 -3
  52. package/public/r/hero-5.json +5 -3
  53. package/public/r/hero-6.json +5 -3
  54. package/public/r/hero-7.json +5 -3
  55. package/public/r/hero-8.json +1 -1
  56. package/public/r/hero-9.json +5 -3
  57. package/public/r/hover-card.json +2 -2
  58. package/public/r/icon.json +1 -1
  59. package/public/r/input-group.json +1 -1
  60. package/public/r/item.json +2 -20
  61. package/public/r/kbd.json +2 -2
  62. package/public/r/layout.json +4 -7
  63. package/public/r/links-2.json +5 -3
  64. package/public/r/marquee.json +1 -1
  65. package/public/r/native-select.json +3 -3
  66. package/public/r/navigation-menu.json +6 -8
  67. package/public/r/page.json +17 -0
  68. package/public/r/popover.json +1 -1
  69. package/public/r/pricing-1.json +5 -3
  70. package/public/r/pricing-2.json +5 -3
  71. package/public/r/pricing-3.json +5 -3
  72. package/public/r/products-1.json +1 -1
  73. package/public/r/products-4.json +1 -1
  74. package/public/r/products-5.json +1 -1
  75. package/public/r/radio-group.json +1 -1
  76. package/public/r/rating.json +3 -3
  77. package/public/r/registry.json +186 -440
  78. package/public/r/reviews-1.json +5 -3
  79. package/public/r/reviews-2.json +5 -3
  80. package/public/r/reviews-3.json +5 -3
  81. package/public/r/reviews-4.json +1 -1
  82. package/public/r/reviews-5.json +5 -3
  83. package/public/r/select.json +6 -8
  84. package/public/r/services-1.json +11 -3
  85. package/public/r/services-2.json +7 -1
  86. package/public/r/services-3.json +7 -1
  87. package/public/r/services-4.json +11 -3
  88. package/public/r/services-5.json +5 -3
  89. package/public/r/services-6.json +11 -3
  90. package/public/r/services-7.json +11 -3
  91. package/public/r/sheet.json +6 -3
  92. package/public/r/sidebar-1.json +4 -2
  93. package/public/r/sidebar.json +10 -7
  94. package/public/r/slider.json +1 -1
  95. package/public/r/spinner.json +3 -3
  96. package/public/r/switch.json +1 -1
  97. package/public/r/theme-toggle.json +5 -3
  98. package/public/r/tooltip.json +1 -1
  99. package/public/r/typography.json +16 -16
  100. package/public/r/video.json +1 -1
  101. package/registry.json +186 -440
  102. package/src/components/blocks/article-1.astro +1 -1
  103. package/src/components/blocks/article-2.astro +1 -1
  104. package/src/components/blocks/articles-1.astro +1 -1
  105. package/src/components/blocks/articles-2.astro +2 -2
  106. package/src/components/blocks/articles-3.astro +1 -1
  107. package/src/components/blocks/banner-1.astro +3 -5
  108. package/src/components/blocks/banner-2.astro +1 -1
  109. package/src/components/blocks/blocks-1.astro +25 -37
  110. package/src/components/blocks/contact-3.astro +4 -3
  111. package/src/components/blocks/content-1.astro +5 -4
  112. package/src/components/blocks/content-2.astro +6 -5
  113. package/src/components/blocks/content-3.astro +9 -2
  114. package/src/components/blocks/content-4.astro +6 -5
  115. package/src/components/blocks/cta-2.astro +4 -3
  116. package/src/components/blocks/cta-4.astro +3 -2
  117. package/src/components/blocks/cta-5.astro +6 -5
  118. package/src/components/blocks/cta-6.astro +4 -3
  119. package/src/components/blocks/doc-1.astro +28 -56
  120. package/src/components/blocks/features-1.astro +3 -1
  121. package/src/components/blocks/features-2.astro +4 -2
  122. package/src/components/blocks/features-4.astro +3 -1
  123. package/src/components/blocks/footer-1.astro +26 -12
  124. package/src/components/blocks/footer-2.astro +24 -12
  125. package/src/components/blocks/footer-3.astro +26 -12
  126. package/src/components/blocks/header-1.astro +2 -3
  127. package/src/components/blocks/hero-13.astro +1 -1
  128. package/src/components/blocks/hero-4.astro +2 -2
  129. package/src/components/blocks/hero-5.astro +3 -3
  130. package/src/components/blocks/hero-6.astro +3 -3
  131. package/src/components/blocks/hero-7.astro +3 -3
  132. package/src/components/blocks/hero-8.astro +1 -1
  133. package/src/components/blocks/hero-9.astro +2 -2
  134. package/src/components/blocks/links-2.astro +3 -5
  135. package/src/components/blocks/pricing-1.astro +3 -2
  136. package/src/components/blocks/pricing-2.astro +3 -2
  137. package/src/components/blocks/pricing-3.astro +3 -2
  138. package/src/components/blocks/products-1.astro +1 -1
  139. package/src/components/blocks/products-4.astro +2 -2
  140. package/src/components/blocks/products-5.astro +4 -4
  141. package/src/components/blocks/reviews-1.astro +2 -2
  142. package/src/components/blocks/reviews-2.astro +2 -2
  143. package/src/components/blocks/reviews-3.astro +2 -2
  144. package/src/components/blocks/reviews-4.astro +4 -4
  145. package/src/components/blocks/reviews-5.astro +16 -25
  146. package/src/components/blocks/services-1.astro +7 -9
  147. package/src/components/blocks/services-2.astro +5 -4
  148. package/src/components/blocks/services-3.astro +6 -5
  149. package/src/components/blocks/services-4.astro +7 -9
  150. package/src/components/blocks/services-5.astro +3 -4
  151. package/src/components/blocks/services-6.astro +7 -6
  152. package/src/components/blocks/services-7.astro +7 -9
  153. package/src/components/blocks/sidebar-1.astro +42 -97
  154. package/src/components/ui/accordion/accordion-trigger.astro +7 -8
  155. package/src/components/ui/alert-dialog/alert-dialog.astro +23 -3
  156. package/src/components/ui/avatar/avatar.astro +1 -1
  157. package/src/components/ui/badge/badge.astro +1 -0
  158. package/src/components/ui/banner/banner-container.astro +3 -3
  159. package/src/components/ui/breadcrumb/breadcrumb-ellipsis.astro +2 -2
  160. package/src/components/ui/breadcrumb/breadcrumb-separator.astro +2 -2
  161. package/src/components/ui/button/button-variants.ts +8 -7
  162. package/src/components/ui/card/card-content.astro +1 -1
  163. package/src/components/ui/card/card-footer.astro +1 -1
  164. package/src/components/ui/card/card-header.astro +1 -1
  165. package/src/components/ui/card/card.astro +1 -1
  166. package/src/components/ui/carousel/carousel-next.astro +3 -3
  167. package/src/components/ui/carousel/carousel-previous.astro +3 -3
  168. package/src/components/ui/checkbox/checkbox.astro +1 -1
  169. package/src/components/ui/combobox/combobox-input.astro +2 -2
  170. package/src/components/ui/combobox/combobox-item.astro +4 -4
  171. package/src/components/ui/combobox/combobox-list.astro +1 -1
  172. package/src/components/ui/combobox/combobox-trigger.astro +2 -5
  173. package/src/components/ui/combobox/combobox.astro +3 -0
  174. package/src/components/ui/command/command-dialog.astro +10 -10
  175. package/src/components/ui/command/command-input.astro +2 -2
  176. package/src/components/ui/command/command-item.astro +4 -5
  177. package/src/components/ui/dialog/dialog-close.astro +2 -2
  178. package/src/components/ui/dialog/dialog-content.astro +2 -2
  179. package/src/components/ui/dialog/dialog.astro +26 -3
  180. package/src/components/ui/dropdown-menu/dropdown-menu-checkbox-item.astro +4 -5
  181. package/src/components/ui/dropdown-menu/dropdown-menu-content.astro +4 -4
  182. package/src/components/ui/dropdown-menu/dropdown-menu-item.astro +1 -1
  183. package/src/components/ui/dropdown-menu/dropdown-menu-label.astro +1 -1
  184. package/src/components/ui/dropdown-menu/dropdown-menu-radio-item.astro +4 -5
  185. package/src/components/ui/dropdown-menu/dropdown-menu-shortcut.astro +1 -1
  186. package/src/components/ui/dropdown-menu/dropdown-menu.astro +3 -0
  187. package/src/components/ui/field/field-label.astro +1 -1
  188. package/src/components/ui/field/field-title.astro +1 -1
  189. package/src/components/ui/hover-card/hover-card-content.astro +4 -4
  190. package/src/components/ui/hover-card/hover-card.astro +2 -2
  191. package/src/components/ui/icon/icon.astro +7 -10
  192. package/src/components/ui/input-group/input-group-button.astro +0 -1
  193. package/src/components/ui/item/item-media.astro +1 -1
  194. package/src/components/ui/item/item.astro +0 -18
  195. package/src/components/ui/kbd/kbd-group.astro +1 -1
  196. package/src/components/ui/kbd/kbd.astro +1 -1
  197. package/src/components/ui/layout/layout-body.astro +1 -1
  198. package/src/components/ui/layout/layout-head.astro +3 -2
  199. package/src/components/ui/layout/layout-main.astro +1 -1
  200. package/src/components/ui/layout/layout.astro +4 -0
  201. package/src/components/ui/marquee/marquee.astro +49 -68
  202. package/src/components/ui/native-select/native-select.astro +2 -3
  203. package/src/components/ui/navigation-menu/navigation-menu-content.astro +1 -1
  204. package/src/components/ui/navigation-menu/navigation-menu-list.astro +1 -1
  205. package/src/components/ui/navigation-menu/navigation-menu-trigger.astro +2 -3
  206. package/src/components/ui/navigation-menu/navigation-menu.astro +1 -1
  207. package/src/components/ui/popover/popover-content.astro +1 -1
  208. package/src/components/ui/radio-group/radio-group-item.astro +3 -3
  209. package/src/components/ui/rating/rating.astro +3 -3
  210. package/src/components/ui/select/select-content.astro +1 -1
  211. package/src/components/ui/select/select-item.astro +4 -4
  212. package/src/components/ui/select/select-trigger.astro +3 -6
  213. package/src/components/ui/select/select.astro +6 -0
  214. package/src/components/ui/sheet/sheet-content.astro +4 -5
  215. package/src/components/ui/sidebar/sidebar-menu-button.astro +13 -10
  216. package/src/components/ui/sidebar/sidebar-menu-sub-button.astro +10 -8
  217. package/src/components/ui/sidebar/sidebar-provider.astro +1 -13
  218. package/src/components/ui/sidebar/sidebar-rail.astro +1 -1
  219. package/src/components/ui/sidebar/sidebar-trigger.astro +3 -3
  220. package/src/components/ui/sidebar/sidebar.astro +1 -1
  221. package/src/components/ui/slider/slider.astro +6 -4
  222. package/src/components/ui/spinner/spinner.astro +4 -4
  223. package/src/components/ui/switch/switch.astro +1 -1
  224. package/src/components/ui/theme-toggle/theme-toggle.astro +4 -3
  225. package/src/components/ui/tooltip/tooltip-content.astro +1 -1
  226. package/src/components/ui/typography/typography-a.astro +19 -4
  227. package/src/components/ui/typography/typography-blockquote.astro +26 -6
  228. package/src/components/ui/typography/typography-h1.astro +7 -9
  229. package/src/components/ui/typography/typography-h2.astro +12 -9
  230. package/src/components/ui/typography/typography-h3.astro +7 -9
  231. package/src/components/ui/typography/typography-h4.astro +7 -9
  232. package/src/components/ui/typography/typography-inline-code.astro +28 -12
  233. package/src/components/ui/typography/typography-lead.astro +29 -4
  234. package/src/components/ui/typography/typography-list-item.astro +25 -9
  235. package/src/components/ui/typography/typography-list.astro +29 -11
  236. package/src/components/ui/typography/typography-p.astro +26 -6
  237. package/src/components/ui/typography/typography-table-cell.astro +32 -13
  238. package/src/components/ui/typography/typography-table-head.astro +27 -13
  239. package/src/components/ui/typography/typography-table-row.astro +23 -13
  240. package/src/components/ui/typography/typography-table.astro +29 -20
  241. package/src/components/ui/typography/typography.astro +172 -46
  242. package/src/components/ui/video/video.astro +11 -27
  243. package/src/styles/global.css +2 -15
  244. package/public/r/beta-repo-setup.json +0 -131
  245. package/public/r/blocks.json +0 -91
  246. package/public/r/content-5.json +0 -17
  247. package/public/r/content-6.json +0 -17
  248. package/public/r/init.json +0 -23
  249. package/public/r/tile.json +0 -27
  250. package/src/components/blocks/content-5.astro +0 -115
  251. package/src/components/blocks/content-6.astro +0 -91
  252. package/src/components/ui/tile/index.ts +0 -3
  253. package/src/components/ui/tile/tile-content.astro +0 -17
  254. package/src/components/ui/tile/tile-group.astro +0 -76
  255. package/src/components/ui/tile/tile.astro +0 -46
@@ -69,7 +69,7 @@ const {
69
69
  <Image
70
70
  src={image.src}
71
71
  alt={image.alt}
72
- class="aspect-16/10 w-full rounded-xl object-cover"
72
+ class="aspect-[16/10] w-full rounded-xl object-cover"
73
73
  widths={[640, 960]}
74
74
  sizes="(min-width: 42rem) 42rem, 100vw"
75
75
  />
@@ -69,7 +69,7 @@ const {
69
69
  <Image
70
70
  src={image.src}
71
71
  alt={image.alt}
72
- class="aspect-16/10 w-full rounded-xl object-cover"
72
+ class="aspect-[16/10] w-full rounded-xl object-cover"
73
73
  widths={[640, 960]}
74
74
  sizes="(min-width: 42rem) 42rem, 100vw"
75
75
  />
@@ -63,7 +63,7 @@ const { class: className, badge, title, description, articles } = Astro.props
63
63
  <Image
64
64
  src={article.image.src}
65
65
  alt={article.image.alt}
66
- class="-mx-4 -mt-4 aspect-video w-[calc(100%+2rem)] max-w-none rounded-lg object-cover transition-opacity group-hover:opacity-85"
66
+ class="-mx-4 -mt-4 aspect-[16/9] w-[calc(100%+2rem)] max-w-none rounded-lg object-cover transition-opacity group-hover:opacity-85"
67
67
  widths={[480, 720, 960]}
68
68
  sizes="(min-width: 64rem) 26rem, (min-width: 48rem) 50vw, 100vw"
69
69
  />
@@ -80,7 +80,7 @@ const {
80
80
  <Image
81
81
  src={featured.image.src}
82
82
  alt={featured.image.alt}
83
- class="aspect-4/3 rounded-lg object-cover transition-opacity group-hover:opacity-85"
83
+ class="aspect-[4/3] rounded-lg object-cover transition-opacity group-hover:opacity-85"
84
84
  widths={[640, 960, 1280]}
85
85
  sizes="(min-width: 64rem) 50vw, 100vw"
86
86
  />
@@ -120,7 +120,7 @@ const {
120
120
  <Image
121
121
  src={article.image.src}
122
122
  alt={article.image.alt}
123
- class="-mx-4 -mt-4 aspect-video w-[calc(100%+2rem)] max-w-none rounded-lg object-cover transition-opacity group-hover:opacity-85"
123
+ class="-mx-4 -mt-4 aspect-[16/9] w-[calc(100%+2rem)] max-w-none rounded-lg object-cover transition-opacity group-hover:opacity-85"
124
124
  widths={[480, 720]}
125
125
  sizes="(min-width: 64rem) 22rem, (min-width: 48rem) 50vw, 100vw"
126
126
  />
@@ -61,7 +61,7 @@ const { class: className, badge, title, articles } = Astro.props
61
61
  <Image
62
62
  src={article.image.src}
63
63
  alt={article.image.alt}
64
- class="-mx-4 -mt-4 aspect-video w-[calc(100%+2rem)] max-w-none rounded-lg object-cover transition-opacity group-hover:opacity-85"
64
+ class="-mx-4 -mt-4 aspect-[16/9] w-[calc(100%+2rem)] max-w-none rounded-lg object-cover transition-opacity group-hover:opacity-85"
65
65
  widths={[480, 720]}
66
66
  sizes="(min-width: 64rem) 18rem, (min-width: 48rem) 50vw, 100vw"
67
67
  />
@@ -1,7 +1,8 @@
1
1
  ---
2
+ import ArrowRightIcon from "@lucide/astro/icons/arrow-right"
3
+
2
4
  import { cn } from "@/lib/utils"
3
5
  import { Banner, BannerContainer } from "@/components/ui/banner"
4
- import { Icon } from "@/components/ui/icon"
5
6
 
6
7
  type Props = {
7
8
  class?: string
@@ -33,10 +34,7 @@ const { class: className, title, description, link } = Astro.props
33
34
  class="group/link inline-flex shrink-0 items-center gap-1 text-sm font-medium underline underline-offset-4 transition-opacity hover:opacity-80"
34
35
  >
35
36
  {link.label}
36
- <Icon
37
- name="arrow-right"
38
- class="size-3.5 transition-transform group-hover/link:translate-x-0.5"
39
- />
37
+ <ArrowRightIcon class="size-3.5 transition-transform group-hover/link:translate-x-0.5" />
40
38
  </a>
41
39
  )
42
40
  }
@@ -20,7 +20,7 @@ const { class: className, title, description, buttons } = Astro.props
20
20
  <Banner variant="floating" storageKey="banner-2" class={cn("", className)}>
21
21
  <BannerContainer class="gap-4 py-1" showClose={false}>
22
22
  <div
23
- class="flex flex-1 flex-col gap-0.5 lg:flex-row lg:items-center lg:gap-x-4"
23
+ class="flex flex-1 flex-col gap-0.5 @5xl:flex-row @5xl:items-center @5xl:gap-x-4"
24
24
  >
25
25
  <p class="text-sm font-semibold">{title}</p>
26
26
  <p class="text-muted-foreground text-sm">{description}</p>
@@ -1,4 +1,14 @@
1
1
  ---
2
+ import ArrowLeft from "@lucide/astro/icons/arrow-left"
3
+ import ArrowRight from "@lucide/astro/icons/arrow-right"
4
+ import Check from "@lucide/astro/icons/check"
5
+ import ChevronDown from "@lucide/astro/icons/chevron-down"
6
+ import Copy from "@lucide/astro/icons/copy"
7
+ import ExternalLink from "@lucide/astro/icons/external-link"
8
+ import Claude from "simple-icons-astro/Claude"
9
+ import Cursor from "simple-icons-astro/Cursor"
10
+ import Markdown from "simple-icons-astro/Markdown"
11
+
2
12
  import { cn } from "@/lib/utils"
3
13
  import { Button } from "@/components/ui/button"
4
14
  import { buttonVariants } from "@/components/ui/button/button-variants"
@@ -7,7 +17,6 @@ import {
7
17
  DropdownMenuContent,
8
18
  DropdownMenuTrigger,
9
19
  } from "@/components/ui/dropdown-menu"
10
- import { Icon } from "@/components/ui/icon"
11
20
  import { SectionContainer } from "@/components/ui/section"
12
21
  import {
13
22
  Typography,
@@ -93,7 +102,7 @@ const openLinks = markdownUrl
93
102
  data-slot="blocks-page"
94
103
  class={cn("gap-10 pt-10 pb-10 sm:pt-12 sm:pb-12", className)}
95
104
  >
96
- <div class="mx-auto flex w-full max-w-336 flex-col gap-10">
105
+ <div class="mx-auto flex w-full max-w-[84rem] flex-col gap-10">
97
106
  <header
98
107
  class="flex flex-col gap-4 border-b pb-8 sm:flex-row sm:items-start sm:justify-between"
99
108
  >
@@ -122,8 +131,8 @@ const openLinks = markdownUrl
122
131
  data-source={copyButton?.source}
123
132
  aria-label={labels.copyMarkdown}
124
133
  >
125
- <Icon name="copy" class="blocks-copy-icon size-3.5" />
126
- <Icon name="check" class="blocks-check-icon hidden size-3.5" />
134
+ <Copy class="blocks-copy-icon size-3.5" />
135
+ <Check class="blocks-check-icon hidden size-3.5" />
127
136
  <span>{labels.copyMarkdown}</span>
128
137
  </Button>
129
138
  )
@@ -135,7 +144,7 @@ const openLinks = markdownUrl
135
144
  class={buttonVariants({ variant: "outline", size: "xs" })}
136
145
  >
137
146
  <span>{labels.openIn}</span>
138
- <Icon name="chevron-down" class="size-3.5 opacity-70" />
147
+ <ChevronDown class="size-3.5 opacity-70" />
139
148
  </DropdownMenuTrigger>
140
149
  <DropdownMenuContent align="end" sideOffset={6} class="w-56">
141
150
  {openLinks.map((link) => (
@@ -145,9 +154,7 @@ const openLinks = markdownUrl
145
154
  rel="noreferrer noopener"
146
155
  class="hover:bg-accent hover:text-accent-foreground flex items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none"
147
156
  >
148
- {link.icon === "markdown" && (
149
- <Icon name="markdown" class="size-4 fill-current" />
150
- )}
157
+ {link.icon === "markdown" && <Markdown class="size-4" />}
151
158
  {link.icon === "chatgpt" && (
152
159
  <svg
153
160
  role="img"
@@ -159,17 +166,10 @@ const openLinks = markdownUrl
159
166
  <path d="M22.282 9.821a5.985 5.985 0 0 0-.516-4.91 6.046 6.046 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.182a5.985 5.985 0 0 0-3.998 2.9 6.046 6.046 0 0 0 .743 7.097 5.98 5.98 0 0 0 .511 4.91 6.051 6.051 0 0 0 6.515 2.9A5.985 5.985 0 0 0 13.26 24a6.056 6.056 0 0 0 5.772-4.206 5.989 5.989 0 0 0 3.998-2.9 6.056 6.056 0 0 0-.748-7.073ZM13.26 22.43a4.476 4.476 0 0 1-2.876-1.04l.142-.081 4.778-2.758a.795.795 0 0 0 .393-.681v-6.737l2.02 1.169a.071.071 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.495 4.494Zm-9.66-4.125a4.471 4.471 0 0 1-.535-3.014l.142.085 4.783 2.758a.771.771 0 0 0 .781 0l5.843-3.368v2.332a.08.08 0 0 1-.034.062L9.74 19.95a4.499 4.499 0 0 1-6.14-1.646ZM2.34 7.896a4.485 4.485 0 0 1 2.366-1.973V11.6a.766.766 0 0 0 .388.677l5.814 3.354-2.02 1.169a.076.076 0 0 1-.071 0l-4.83-2.787A4.504 4.504 0 0 1 2.34 7.872Zm16.596 3.856-5.833-3.388L15.12 7.2a.076.076 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.104v-5.677a.79.79 0 0 0-.407-.667Zm2.011-3.024-.142-.085-4.774-2.782a.776.776 0 0 0-.785 0L9.409 9.23V6.897a.066.066 0 0 1 .028-.061l4.83-2.787a4.499 4.499 0 0 1 6.68 4.66ZM8.307 12.863l-2.02-1.164a.08.08 0 0 1-.038-.057V6.074a4.499 4.499 0 0 1 7.376-3.453l-.142.08-4.778 2.758a.795.795 0 0 0-.393.681Zm1.097-2.365 2.602-1.5 2.607 1.5v2.999l-2.597 1.5-2.607-1.5Z" />
160
167
  </svg>
161
168
  )}
162
- {link.icon === "claude" && (
163
- <Icon name="claude" class="size-4 fill-current" />
164
- )}
165
- {link.icon === "cursor" && (
166
- <Icon name="cursor" class="size-4 fill-current" />
167
- )}
169
+ {link.icon === "claude" && <Claude class="size-4" />}
170
+ {link.icon === "cursor" && <Cursor class="size-4" />}
168
171
  <span>{link.label}</span>
169
- <Icon
170
- name="external-link"
171
- class="text-muted-foreground ml-auto size-3.5"
172
- />
172
+ <ExternalLink class="text-muted-foreground ml-auto size-3.5" />
173
173
  </a>
174
174
  ))}
175
175
  </DropdownMenuContent>
@@ -179,7 +179,7 @@ const openLinks = markdownUrl
179
179
  </div>
180
180
  </header>
181
181
 
182
- <Typography as="article" class="w-full max-w-none" size="sm">
182
+ <Typography as="article" class="w-full max-w-none">
183
183
  <slot />
184
184
  </Typography>
185
185
 
@@ -196,7 +196,7 @@ const openLinks = markdownUrl
196
196
  variant="outline"
197
197
  class="h-auto min-w-0 items-center justify-start gap-2 px-3 py-2 whitespace-normal"
198
198
  >
199
- <Icon name="arrow-left" class="size-4" />
199
+ <ArrowLeft class="size-4" />
200
200
  <span class="truncate text-sm font-medium">
201
201
  {previousPage.title}
202
202
  </span>
@@ -213,7 +213,7 @@ const openLinks = markdownUrl
213
213
  class="h-auto min-w-0 items-center justify-end gap-2 px-3 py-2 text-right whitespace-normal"
214
214
  >
215
215
  <span class="truncate text-sm font-medium">{nextPage.title}</span>
216
- <Icon name="arrow-right" class="size-4" />
216
+ <ArrowRight class="size-4" />
217
217
  </Button>
218
218
  ) : (
219
219
  <div aria-hidden="true" />
@@ -228,27 +228,13 @@ const openLinks = markdownUrl
228
228
  const button = copyButtonId ? document.getElementById(copyButtonId) : null
229
229
 
230
230
  if (button instanceof HTMLButtonElement) {
231
- const writeToClipboard = async (text) => {
232
- if (navigator.clipboard && window.isSecureContext) {
233
- try {
234
- await navigator.clipboard.writeText(text)
235
- return true
236
- } catch {
237
- return false
238
- }
239
- }
240
-
241
- return false
242
- }
243
-
244
231
  button.addEventListener("click", async () => {
245
232
  const source = button.dataset.source
246
233
 
247
234
  if (!source) return
248
235
 
249
- const copied = await writeToClipboard(source)
250
-
251
- if (copied) {
236
+ try {
237
+ await navigator.clipboard.writeText(source)
252
238
  button.querySelector(".blocks-copy-icon")?.classList.add("hidden")
253
239
  button.querySelector(".blocks-check-icon")?.classList.remove("hidden")
254
240
 
@@ -256,6 +242,8 @@ const openLinks = markdownUrl
256
242
  button.querySelector(".blocks-copy-icon")?.classList.remove("hidden")
257
243
  button.querySelector(".blocks-check-icon")?.classList.add("hidden")
258
244
  }, 1200)
245
+ } catch {
246
+ // Ignore clipboard failures; the button remains available for retry.
259
247
  }
260
248
  })
261
249
  }
@@ -15,6 +15,7 @@ import { Icon } from "@/components/ui/icon"
15
15
  import { Input } from "@/components/ui/input"
16
16
  import { Section, SectionContainer } from "@/components/ui/section"
17
17
  import { Textarea } from "@/components/ui/textarea"
18
+ import PlaceholderImage from "@/assets/placeholder.webp"
18
19
 
19
20
  type Props = {
20
21
  class?: string
@@ -36,7 +37,7 @@ type Props = {
36
37
  messagePlaceholder: string
37
38
  actionLabel: string
38
39
  }
39
- image: {
40
+ image?: {
40
41
  src: ImageMetadata
41
42
  alt: string
42
43
  }
@@ -48,7 +49,7 @@ const {
48
49
  description,
49
50
  contactItems,
50
51
  form,
51
- image,
52
+ image = { src: PlaceholderImage, alt: "Contact image" },
52
53
  } = Astro.props
53
54
  ---
54
55
 
@@ -136,7 +137,7 @@ const {
136
137
  <Image
137
138
  src={image.src}
138
139
  alt={image.alt}
139
- class="aspect-3/4 w-full rounded-xl border object-cover lg:sticky lg:top-24"
140
+ class="aspect-[3/4] w-full rounded-xl border object-cover lg:sticky lg:top-24"
140
141
  widths={[640, 960, 1280]}
141
142
  sizes="(min-width: 1024px) 50vw, 100vw"
142
143
  />
@@ -1,11 +1,12 @@
1
1
  ---
2
2
  import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
+ import { CheckIcon } from "@lucide/astro"
4
5
 
5
6
  import { cn } from "@/lib/utils"
6
7
  import { Button } from "@/components/ui/button"
7
- import { Icon } from "@/components/ui/icon"
8
8
  import { Section, SectionContainer } from "@/components/ui/section"
9
+ import PlaceholderImage from "@/assets/placeholder.webp"
9
10
 
10
11
  type Props = {
11
12
  class?: string
@@ -17,7 +18,7 @@ type Props = {
17
18
  href: string
18
19
  variant?: "default" | "outline" | "secondary" | "ghost"
19
20
  }[]
20
- image: {
21
+ image?: {
21
22
  src: ImageMetadata
22
23
  alt: string
23
24
  }
@@ -29,7 +30,7 @@ const {
29
30
  description,
30
31
  features,
31
32
  buttons,
32
- image,
33
+ image = { src: PlaceholderImage, alt: "Content image" },
33
34
  } = Astro.props
34
35
  ---
35
36
 
@@ -50,7 +51,7 @@ const {
50
51
  <ul class="flex flex-col gap-3">
51
52
  {features.map((feature) => (
52
53
  <li class="flex items-center gap-3 text-sm">
53
- <Icon name="check" class="text-primary size-4 shrink-0" />
54
+ <CheckIcon class="text-primary size-4 shrink-0" />
54
55
  {feature}
55
56
  </li>
56
57
  ))}
@@ -1,11 +1,12 @@
1
1
  ---
2
2
  import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
+ import { CheckIcon } from "@lucide/astro"
4
5
 
5
6
  import { cn } from "@/lib/utils"
6
7
  import { Button } from "@/components/ui/button"
7
- import { Icon } from "@/components/ui/icon"
8
8
  import { Section, SectionContainer } from "@/components/ui/section"
9
+ import PlaceholderImage from "@/assets/placeholder.webp"
9
10
 
10
11
  type Props = {
11
12
  class?: string
@@ -17,7 +18,7 @@ type Props = {
17
18
  href: string
18
19
  variant?: "default" | "outline" | "secondary" | "ghost"
19
20
  }[]
20
- image: {
21
+ image?: {
21
22
  src: ImageMetadata
22
23
  alt: string
23
24
  }
@@ -29,7 +30,7 @@ const {
29
30
  description,
30
31
  features,
31
32
  buttons,
32
- image,
33
+ image = { src: PlaceholderImage, alt: "Content image" },
33
34
  } = Astro.props
34
35
  ---
35
36
 
@@ -51,7 +52,7 @@ const {
51
52
  <ul class="flex flex-col gap-3">
52
53
  {features.map((feature) => (
53
54
  <li class="flex items-center gap-3 text-sm">
54
- <Icon name="check" class="text-primary size-4 shrink-0" />
55
+ <CheckIcon class="text-primary size-4 shrink-0" />
55
56
  {feature}
56
57
  </li>
57
58
  ))}
@@ -81,7 +82,7 @@ const {
81
82
  <Image
82
83
  src={image.src}
83
84
  alt={image.alt}
84
- class="aspect-4/3 w-full rounded-xl border object-cover"
85
+ class="aspect-[4/3] w-full rounded-xl border object-cover"
85
86
  widths={[640, 960, 1280]}
86
87
  sizes="(min-width: 1024px) 50vw, 100vw"
87
88
  />
@@ -5,6 +5,7 @@ import { Image } from "astro:assets"
5
5
  import { cn } from "@/lib/utils"
6
6
  import { Button } from "@/components/ui/button"
7
7
  import { Section, SectionContainer } from "@/components/ui/section"
8
+ import PlaceholderImage from "@/assets/placeholder.webp"
8
9
 
9
10
  type Props = {
10
11
  class?: string
@@ -15,13 +16,19 @@ type Props = {
15
16
  href: string
16
17
  variant?: "default" | "outline" | "secondary" | "ghost"
17
18
  }[]
18
- image: {
19
+ image?: {
19
20
  src: ImageMetadata
20
21
  alt: string
21
22
  }
22
23
  }
23
24
 
24
- const { class: className, title, description, buttons, image } = Astro.props
25
+ const {
26
+ class: className,
27
+ title,
28
+ description,
29
+ buttons,
30
+ image = { src: PlaceholderImage, alt: "Content image" },
31
+ } = Astro.props
25
32
  ---
26
33
 
27
34
  <Section class={cn("", className)}>
@@ -1,11 +1,12 @@
1
1
  ---
2
2
  import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
+ import { CheckIcon } from "@lucide/astro"
4
5
 
5
6
  import { cn } from "@/lib/utils"
6
7
  import { Button } from "@/components/ui/button"
7
- import { Icon } from "@/components/ui/icon"
8
8
  import { Section, SectionContainer } from "@/components/ui/section"
9
+ import PlaceholderImage from "@/assets/placeholder.webp"
9
10
 
10
11
  type Props = {
11
12
  class?: string
@@ -17,7 +18,7 @@ type Props = {
17
18
  href: string
18
19
  variant?: "default" | "outline" | "secondary" | "ghost"
19
20
  }[]
20
- image: {
21
+ image?: {
21
22
  src: ImageMetadata
22
23
  alt: string
23
24
  }
@@ -29,7 +30,7 @@ const {
29
30
  description,
30
31
  features,
31
32
  buttons,
32
- image,
33
+ image = { src: PlaceholderImage, alt: "Content image" },
33
34
  } = Astro.props
34
35
  ---
35
36
 
@@ -52,7 +53,7 @@ const {
52
53
  <ul class="flex flex-col gap-3">
53
54
  {features.map((feature) => (
54
55
  <li class="flex items-center gap-3 text-sm">
55
- <Icon name="check" class="text-primary size-4 shrink-0" />
56
+ <CheckIcon class="text-primary size-4 shrink-0" />
56
57
  {feature}
57
58
  </li>
58
59
  ))}
@@ -82,7 +83,7 @@ const {
82
83
  <Image
83
84
  src={image.src}
84
85
  alt={image.alt}
85
- class="aspect-4/3 w-full rounded-xl border object-cover"
86
+ class="aspect-[4/3] w-full rounded-xl border object-cover"
86
87
  widths={[640, 960, 1280]}
87
88
  sizes="(min-width: 1024px) 66vw, 100vw"
88
89
  />
@@ -12,6 +12,7 @@ import {
12
12
  import { Button } from "@/components/ui/button"
13
13
  import { Rating } from "@/components/ui/rating"
14
14
  import { Section, SectionContainer } from "@/components/ui/section"
15
+ import PlaceholderImage from "@/assets/placeholder.webp"
15
16
 
16
17
  type Props = {
17
18
  class?: string
@@ -31,7 +32,7 @@ type Props = {
31
32
  rating: number
32
33
  text: string
33
34
  }
34
- image: {
35
+ image?: {
35
36
  src: ImageMetadata
36
37
  alt: string
37
38
  }
@@ -43,7 +44,7 @@ const {
43
44
  description,
44
45
  buttons,
45
46
  socialProof,
46
- image,
47
+ image = { src: PlaceholderImage, alt: "CTA image" },
47
48
  } = Astro.props
48
49
  ---
49
50
 
@@ -106,7 +107,7 @@ const {
106
107
  <Image
107
108
  src={image.src}
108
109
  alt={image.alt}
109
- class="aspect-4/3 w-full rounded-xl border object-cover"
110
+ class="aspect-[4/3] w-full rounded-xl border object-cover"
110
111
  widths={[640, 960, 1280]}
111
112
  sizes="(min-width: 1024px) 50vw, 100vw"
112
113
  />
@@ -12,6 +12,7 @@ import {
12
12
  import { Button } from "@/components/ui/button"
13
13
  import { Rating } from "@/components/ui/rating"
14
14
  import { Section, SectionContainer } from "@/components/ui/section"
15
+ import PlaceholderImage from "@/assets/placeholder.webp"
15
16
 
16
17
  type Props = {
17
18
  class?: string
@@ -31,7 +32,7 @@ type Props = {
31
32
  rating: number
32
33
  text: string
33
34
  }
34
- image: {
35
+ image?: {
35
36
  src: ImageMetadata
36
37
  alt: string
37
38
  }
@@ -43,7 +44,7 @@ const {
43
44
  description,
44
45
  buttons,
45
46
  socialProof,
46
- image,
47
+ image = { src: PlaceholderImage, alt: "CTA image" },
47
48
  } = Astro.props
48
49
  ---
49
50
 
@@ -1,11 +1,12 @@
1
1
  ---
2
2
  import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
+ import { CheckIcon } from "@lucide/astro"
4
5
 
5
6
  import { cn } from "@/lib/utils"
6
7
  import { Button } from "@/components/ui/button"
7
- import { Icon } from "@/components/ui/icon"
8
8
  import { Section, SectionContainer } from "@/components/ui/section"
9
+ import PlaceholderImage from "@/assets/placeholder.webp"
9
10
 
10
11
  type Props = {
11
12
  class?: string
@@ -17,7 +18,7 @@ type Props = {
17
18
  href: string
18
19
  variant?: "default" | "outline" | "secondary" | "ghost"
19
20
  }[]
20
- image: {
21
+ image?: {
21
22
  src: ImageMetadata
22
23
  alt: string
23
24
  }
@@ -29,7 +30,7 @@ const {
29
30
  description,
30
31
  features,
31
32
  buttons,
32
- image,
33
+ image = { src: PlaceholderImage, alt: "CTA image" },
33
34
  } = Astro.props
34
35
  ---
35
36
 
@@ -51,7 +52,7 @@ const {
51
52
  <ul class="flex flex-col gap-3">
52
53
  {features.map((feature) => (
53
54
  <li class="flex items-center gap-3 text-sm">
54
- <Icon name="check" class="text-primary size-4 shrink-0" />
55
+ <CheckIcon class="text-primary size-4 shrink-0" />
55
56
  {feature}
56
57
  </li>
57
58
  ))}
@@ -81,7 +82,7 @@ const {
81
82
  <Image
82
83
  src={image.src}
83
84
  alt={image.alt}
84
- class="aspect-4/3 w-full rounded-xl border object-cover"
85
+ class="aspect-[4/3] w-full rounded-xl border object-cover"
85
86
  widths={[640, 960, 1280]}
86
87
  sizes="(min-width: 1024px) 50vw, 100vw"
87
88
  />
@@ -12,6 +12,7 @@ import {
12
12
  import { Button } from "@/components/ui/button"
13
13
  import { Rating } from "@/components/ui/rating"
14
14
  import { Section, SectionContainer } from "@/components/ui/section"
15
+ import PlaceholderImage from "@/assets/placeholder.webp"
15
16
 
16
17
  type Props = {
17
18
  class?: string
@@ -31,7 +32,7 @@ type Props = {
31
32
  rating: number
32
33
  text: string
33
34
  }
34
- image: {
35
+ image?: {
35
36
  src: ImageMetadata
36
37
  alt: string
37
38
  }
@@ -43,7 +44,7 @@ const {
43
44
  description,
44
45
  buttons,
45
46
  socialProof,
46
- image,
47
+ image = { src: PlaceholderImage, alt: "CTA image" },
47
48
  } = Astro.props
48
49
  ---
49
50
 
@@ -52,7 +53,7 @@ const {
52
53
  <Image
53
54
  src={image.src}
54
55
  alt={image.alt}
55
- class="aspect-4/3 w-full rounded-xl border object-cover"
56
+ class="aspect-[4/3] w-full rounded-xl border object-cover"
56
57
  widths={[640, 960, 1280]}
57
58
  sizes="(min-width: 1024px) 50vw, 100vw"
58
59
  />