fulldev-ui 0.11.1 → 0.13.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 (166) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/package.json +29 -21
  3. package/public/r/accordion.json +2 -2
  4. package/public/r/alert-dialog.json +2 -2
  5. package/public/r/aspect-ratio.json +23 -0
  6. package/public/r/attachment.json +66 -0
  7. package/public/r/banner.json +0 -4
  8. package/public/r/blocks-1.json +1 -1
  9. package/public/r/button-group.json +41 -0
  10. package/public/r/button.json +1 -1
  11. package/public/r/carousel.json +8 -8
  12. package/public/r/collapsible.json +2 -2
  13. package/public/r/combobox.json +6 -5
  14. package/public/r/command.json +5 -4
  15. package/public/r/components.json +8 -0
  16. package/public/r/dialog.json +2 -2
  17. package/public/r/doc-1.json +1 -1
  18. package/public/r/drawer.json +109 -0
  19. package/public/r/dropdown-menu.json +4 -4
  20. package/public/r/hover-card.json +4 -4
  21. package/public/r/init.json +1 -1
  22. package/public/r/input-group.json +0 -1
  23. package/public/r/layout.json +3 -0
  24. package/public/r/navigation-menu.json +3 -3
  25. package/public/r/pagination.json +59 -0
  26. package/public/r/popover.json +3 -3
  27. package/public/r/radio-group.json +2 -2
  28. package/public/r/registry.json +418 -28
  29. package/public/r/resizable.json +36 -0
  30. package/public/r/reviews-3.json +1 -1
  31. package/public/r/select.json +3 -3
  32. package/public/r/sheet.json +2 -2
  33. package/public/r/sidebar-1.json +1 -1
  34. package/public/r/sidebar.json +1 -1
  35. package/public/r/slider.json +2 -2
  36. package/public/r/switch.json +2 -2
  37. package/public/r/tabs.json +4 -4
  38. package/public/r/toast.json +80 -0
  39. package/public/r/toggle-group.json +34 -0
  40. package/public/r/toggle.json +2 -2
  41. package/public/r/tooltip.json +3 -3
  42. package/public/r/typography.json +21 -16
  43. package/registry/init/global.css +2 -0
  44. package/registry.json +384 -23
  45. package/src/components/blocks/blocks-1.astro +23 -23
  46. package/src/components/blocks/doc-1.astro +116 -26
  47. package/src/components/blocks/reviews-3.astro +1 -1
  48. package/src/components/blocks/sidebar-1.astro +46 -44
  49. package/src/components/ui/accordion/accordion.astro +8 -2
  50. package/src/components/ui/alert-dialog/alert-dialog.astro +8 -2
  51. package/src/components/ui/aspect-ratio/aspect-ratio.astro +25 -0
  52. package/src/components/ui/aspect-ratio/index.ts +1 -0
  53. package/src/components/ui/attachment/attachment-action.astro +20 -0
  54. package/src/components/ui/attachment/attachment-actions.astro +20 -0
  55. package/src/components/ui/attachment/attachment-content.astro +20 -0
  56. package/src/components/ui/attachment/attachment-description.astro +20 -0
  57. package/src/components/ui/attachment/attachment-group.astro +20 -0
  58. package/src/components/ui/attachment/attachment-media.astro +36 -0
  59. package/src/components/ui/attachment/attachment-title.astro +20 -0
  60. package/src/components/ui/attachment/attachment-trigger.astro +24 -0
  61. package/src/components/ui/attachment/attachment.astro +52 -0
  62. package/src/components/ui/attachment/index.ts +9 -0
  63. package/src/components/ui/button/button.astro +4 -1
  64. package/src/components/ui/button-group/button-group-separator.astro +29 -0
  65. package/src/components/ui/button-group/button-group-text.astro +20 -0
  66. package/src/components/ui/button-group/button-group-variants.ts +20 -0
  67. package/src/components/ui/button-group/button-group.astro +30 -0
  68. package/src/components/ui/button-group/index.ts +7 -0
  69. package/src/components/ui/carousel/carousel-content.astro +11 -13
  70. package/src/components/ui/carousel/carousel-item.astro +2 -5
  71. package/src/components/ui/carousel/carousel-next.astro +0 -3
  72. package/src/components/ui/carousel/carousel-previous.astro +0 -3
  73. package/src/components/ui/carousel/carousel.astro +19 -219
  74. package/src/components/ui/carousel/index.ts +1 -5
  75. package/src/components/ui/collapsible/collapsible.astro +8 -2
  76. package/src/components/ui/combobox/combobox-content.astro +1 -1
  77. package/src/components/ui/combobox/combobox-input.astro +11 -4
  78. package/src/components/ui/combobox/combobox-trigger.astro +7 -7
  79. package/src/components/ui/combobox/combobox.astro +9 -17
  80. package/src/components/ui/command/command-dialog.astro +1 -0
  81. package/src/components/ui/command/command.astro +40 -25
  82. package/src/components/ui/dialog/dialog.astro +8 -2
  83. package/src/components/ui/drawer/drawer-close.astro +13 -0
  84. package/src/components/ui/drawer/drawer-content.astro +43 -0
  85. package/src/components/ui/drawer/drawer-description.astro +17 -0
  86. package/src/components/ui/drawer/drawer-footer.astro +17 -0
  87. package/src/components/ui/drawer/drawer-header.astro +17 -0
  88. package/src/components/ui/drawer/drawer-indent-background.astro +11 -0
  89. package/src/components/ui/drawer/drawer-indent.astro +11 -0
  90. package/src/components/ui/drawer/drawer-overlay.astro +21 -0
  91. package/src/components/ui/drawer/drawer-popup.astro +36 -0
  92. package/src/components/ui/drawer/drawer-portal.astro +27 -0
  93. package/src/components/ui/drawer/drawer-provider.astro +11 -0
  94. package/src/components/ui/drawer/drawer-swipe-handle.astro +20 -0
  95. package/src/components/ui/drawer/drawer-title.astro +17 -0
  96. package/src/components/ui/drawer/drawer-trigger.astro +21 -0
  97. package/src/components/ui/drawer/drawer-viewport.astro +21 -0
  98. package/src/components/ui/drawer/drawer-virtual-keyboard-provider.astro +11 -0
  99. package/src/components/ui/drawer/drawer.astro +60 -0
  100. package/src/components/ui/drawer/index.ts +28 -0
  101. package/src/components/ui/dropdown-menu/dropdown-menu-content.astro +1 -1
  102. package/src/components/ui/dropdown-menu/dropdown-menu-item.astro +40 -9
  103. package/src/components/ui/dropdown-menu/dropdown-menu.astro +8 -2
  104. package/src/components/ui/hover-card/hover-card-content.astro +1 -1
  105. package/src/components/ui/hover-card/hover-card.astro +15 -4
  106. package/src/components/ui/navigation-menu/navigation-menu-positioner.astro +1 -1
  107. package/src/components/ui/navigation-menu/navigation-menu.astro +13 -4
  108. package/src/components/ui/pagination/index.ts +7 -0
  109. package/src/components/ui/pagination/pagination-content.astro +17 -0
  110. package/src/components/ui/pagination/pagination-ellipsis.astro +22 -0
  111. package/src/components/ui/pagination/pagination-item.astro +11 -0
  112. package/src/components/ui/pagination/pagination-link.astro +41 -0
  113. package/src/components/ui/pagination/pagination-next.astro +27 -0
  114. package/src/components/ui/pagination/pagination-previous.astro +27 -0
  115. package/src/components/ui/pagination/pagination.astro +19 -0
  116. package/src/components/ui/popover/popover-content.astro +2 -1
  117. package/src/components/ui/popover/popover.astro +9 -2
  118. package/src/components/ui/radio-group/radio-group.astro +8 -2
  119. package/src/components/ui/resizable/index.ts +4 -0
  120. package/src/components/ui/resizable/resizable-handle.astro +32 -0
  121. package/src/components/ui/resizable/resizable-panel.astro +36 -0
  122. package/src/components/ui/resizable/resizable.astro +43 -0
  123. package/src/components/ui/select/select-content.astro +2 -2
  124. package/src/components/ui/select/select.astro +11 -7
  125. package/src/components/ui/sheet/sheet.astro +8 -2
  126. package/src/components/ui/slider/slider.astro +9 -3
  127. package/src/components/ui/switch/switch.astro +8 -2
  128. package/src/components/ui/tabs/tabs-content.astro +1 -1
  129. package/src/components/ui/tabs/tabs-trigger.astro +3 -2
  130. package/src/components/ui/tabs/tabs.astro +8 -2
  131. package/src/components/ui/toast/index.ts +26 -0
  132. package/src/components/ui/toast/toast-action.astro +25 -0
  133. package/src/components/ui/toast/toast-close.astro +27 -0
  134. package/src/components/ui/toast/toast-content.astro +20 -0
  135. package/src/components/ui/toast/toast-description.astro +18 -0
  136. package/src/components/ui/toast/toast-icon.astro +37 -0
  137. package/src/components/ui/toast/toast-item.astro +28 -0
  138. package/src/components/ui/toast/toast-template.astro +11 -0
  139. package/src/components/ui/toast/toast-title.astro +17 -0
  140. package/src/components/ui/toast/toast-viewport.astro +20 -0
  141. package/src/components/ui/toast/toast.astro +51 -0
  142. package/src/components/ui/toast/toaster.astro +37 -0
  143. package/src/components/ui/toggle/toggle.astro +8 -2
  144. package/src/components/ui/toggle-group/index.ts +2 -0
  145. package/src/components/ui/toggle-group/toggle-group-item.astro +44 -0
  146. package/src/components/ui/toggle-group/toggle-group.astro +74 -0
  147. package/src/components/ui/tooltip/tooltip-content.astro +1 -1
  148. package/src/components/ui/tooltip/tooltip.astro +11 -2
  149. package/src/components/ui/typography/typeset.css +441 -0
  150. package/src/components/ui/typography/typography-a.astro +13 -22
  151. package/src/components/ui/typography/typography-blockquote.astro +4 -23
  152. package/src/components/ui/typography/typography-h1.astro +13 -26
  153. package/src/components/ui/typography/typography-h2.astro +13 -31
  154. package/src/components/ui/typography/typography-h3.astro +9 -26
  155. package/src/components/ui/typography/typography-h4.astro +9 -26
  156. package/src/components/ui/typography/typography-inline-code.astro +8 -27
  157. package/src/components/ui/typography/typography-lead.astro +4 -26
  158. package/src/components/ui/typography/typography-list-item.astro +4 -24
  159. package/src/components/ui/typography/typography-list.astro +10 -40
  160. package/src/components/ui/typography/typography-p.astro +9 -28
  161. package/src/components/ui/typography/typography-table-cell.astro +9 -40
  162. package/src/components/ui/typography/typography-table-head.astro +9 -35
  163. package/src/components/ui/typography/typography-table-row.astro +4 -23
  164. package/src/components/ui/typography/typography-table.astro +8 -28
  165. package/src/components/ui/typography/typography.astro +10 -283
  166. package/src/styles/global.css +2 -0
@@ -0,0 +1,24 @@
1
+ ---
2
+ import type { HTMLTag, Polymorphic } from "astro/types"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ type Props<Tag extends HTMLTag = "button"> = Polymorphic<{ as: Tag }>
7
+
8
+ const {
9
+ as: Tag = "href" in Astro.props ? "a" : "button",
10
+ class: className,
11
+ ...props
12
+ } = Astro.props
13
+
14
+ const attributes: Record<string, unknown> = { ...props }
15
+ if (Tag === "button") attributes.type ??= "button"
16
+ ---
17
+
18
+ <Tag
19
+ data-slot="attachment-trigger"
20
+ class={cn("absolute inset-0 z-10 outline-none", className)}
21
+ {...attributes}
22
+ >
23
+ <slot />
24
+ </Tag>
@@ -0,0 +1,52 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types"
3
+ import { cva, type VariantProps } from "class-variance-authority"
4
+
5
+ import { cn } from "@/lib/utils"
6
+
7
+ const attachmentVariants = cva(
8
+ "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",
9
+ {
10
+ variants: {
11
+ size: {
12
+ default:
13
+ "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",
14
+ 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",
15
+ 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",
16
+ },
17
+ orientation: {
18
+ horizontal: "min-w-40 items-center",
19
+ vertical: "w-24 flex-col has-data-[slot=attachment-content]:w-30",
20
+ },
21
+ },
22
+ defaultVariants: {
23
+ size: "default",
24
+ orientation: "horizontal",
25
+ },
26
+ }
27
+ )
28
+
29
+ type Props = HTMLAttributes<"div"> &
30
+ VariantProps<typeof attachmentVariants> & {
31
+ state?: "idle" | "uploading" | "processing" | "error" | "done"
32
+ }
33
+
34
+ const {
35
+ class: className,
36
+ state = "done",
37
+ size = "default",
38
+ orientation = "horizontal",
39
+ ...props
40
+ } = Astro.props
41
+ ---
42
+
43
+ <div
44
+ data-slot="attachment"
45
+ data-state={state}
46
+ data-size={size}
47
+ data-orientation={orientation}
48
+ class={cn(attachmentVariants({ size, orientation }), className)}
49
+ {...props}
50
+ >
51
+ <slot />
52
+ </div>
@@ -0,0 +1,9 @@
1
+ export { default as Attachment } from "./attachment.astro"
2
+ export { default as AttachmentAction } from "./attachment-action.astro"
3
+ export { default as AttachmentActions } from "./attachment-actions.astro"
4
+ export { default as AttachmentContent } from "./attachment-content.astro"
5
+ export { default as AttachmentDescription } from "./attachment-description.astro"
6
+ export { default as AttachmentGroup } from "./attachment-group.astro"
7
+ export { default as AttachmentMedia } from "./attachment-media.astro"
8
+ export { default as AttachmentTitle } from "./attachment-title.astro"
9
+ export { default as AttachmentTrigger } from "./attachment-trigger.astro"
@@ -15,12 +15,15 @@ const {
15
15
  size,
16
16
  ...props
17
17
  } = Astro.props
18
+
19
+ const attributes: Record<string, unknown> = { ...props }
20
+ if (Tag === "button") attributes.type ??= "button"
18
21
  ---
19
22
 
20
23
  <Tag
21
24
  data-slot="button"
22
25
  class={cn(buttonVariants({ variant, size }), className)}
23
- {...props}
26
+ {...attributes}
24
27
  >
25
28
  <slot />
26
29
  </Tag>
@@ -0,0 +1,29 @@
1
+ ---
2
+ import type { HTMLAttributes } from "astro/types"
3
+
4
+ import { cn } from "@/lib/utils"
5
+ import { Separator } from "@/components/ui/separator"
6
+
7
+ type Props = HTMLAttributes<"div"> & {
8
+ orientation?: "horizontal" | "vertical"
9
+ decorative?: boolean
10
+ }
11
+
12
+ const {
13
+ class: className,
14
+ orientation = "vertical",
15
+ decorative = true,
16
+ ...props
17
+ } = Astro.props
18
+ ---
19
+
20
+ <Separator
21
+ data-slot="button-group-separator"
22
+ orientation={orientation}
23
+ decorative={decorative}
24
+ class={cn(
25
+ "bg-input relative self-stretch data-horizontal:mx-px data-horizontal:w-auto data-vertical:my-px data-vertical:h-auto",
26
+ className
27
+ )}
28
+ {...props}
29
+ />
@@ -0,0 +1,20 @@
1
+ ---
2
+ import type { HTMLTag, Polymorphic } from "astro/types"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ type Props<Tag extends HTMLTag = "div"> = Polymorphic<{ as: Tag }>
7
+
8
+ const { as: Tag = "div", class: className, ...props } = Astro.props
9
+ ---
10
+
11
+ <Tag
12
+ data-slot="button-group-text"
13
+ class={cn(
14
+ "bg-muted flex items-center gap-2 rounded-md border px-2.5 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
15
+ className
16
+ )}
17
+ {...props}
18
+ >
19
+ <slot />
20
+ </Tag>
@@ -0,0 +1,20 @@
1
+ import { cva, type VariantProps } from "class-variance-authority"
2
+
3
+ export const buttonGroupVariants = cva(
4
+ "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",
5
+ {
6
+ variants: {
7
+ orientation: {
8
+ horizontal:
9
+ "*: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",
10
+ vertical:
11
+ "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",
12
+ },
13
+ },
14
+ defaultVariants: {
15
+ orientation: "horizontal",
16
+ },
17
+ }
18
+ )
19
+
20
+ export type ButtonGroupVariantProps = VariantProps<typeof buttonGroupVariants>
@@ -0,0 +1,30 @@
1
+ ---
2
+ import type { HTMLTag, Polymorphic } from "astro/types"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ import {
7
+ buttonGroupVariants,
8
+ type ButtonGroupVariantProps,
9
+ } from "./button-group-variants"
10
+
11
+ type Props<Tag extends HTMLTag = "div"> = Polymorphic<{ as: Tag }> &
12
+ ButtonGroupVariantProps
13
+
14
+ const {
15
+ as: Tag = "div",
16
+ class: className,
17
+ orientation = "horizontal",
18
+ ...props
19
+ } = Astro.props
20
+ ---
21
+
22
+ <Tag
23
+ role="group"
24
+ data-slot="button-group"
25
+ data-orientation={orientation}
26
+ class={cn(buttonGroupVariants({ orientation }), className)}
27
+ {...props}
28
+ >
29
+ <slot />
30
+ </Tag>
@@ -0,0 +1,7 @@
1
+ export { default as ButtonGroup } from "./button-group.astro"
2
+ export { default as ButtonGroupSeparator } from "./button-group-separator.astro"
3
+ export { default as ButtonGroupText } from "./button-group-text.astro"
4
+ export {
5
+ buttonGroupVariants,
6
+ type ButtonGroupVariantProps,
7
+ } from "./button-group-variants"
@@ -8,17 +8,15 @@ type Props = HTMLAttributes<"div">
8
8
  const { class: className, ...props } = Astro.props
9
9
  ---
10
10
 
11
- <div class="overflow-hidden" data-slot="carousel-content">
12
- <div
13
- data-slot="carousel-container"
14
- class={cn(
15
- "flex [touch-action:pan-y_pinch-zoom]",
16
- "group-data-[orientation=vertical]/carousel:-mt-4 group-data-[orientation=vertical]/carousel:[touch-action:pan-x_pinch-zoom] group-data-[orientation=vertical]/carousel:flex-col",
17
- "group-data-[orientation=horizontal]/carousel:-ml-4",
18
- className
19
- )}
20
- {...props}
21
- >
22
- <slot />
23
- </div>
11
+ <div
12
+ data-slot="carousel-content"
13
+ class={cn(
14
+ "no-scrollbar flex snap-x snap-mandatory overflow-x-auto overscroll-x-contain",
15
+ "group-data-[dragging=true]/carousel:cursor-grabbing",
16
+ "group-data-[orientation=vertical]/carousel:snap-y group-data-[orientation=vertical]/carousel:flex-col group-data-[orientation=vertical]/carousel:overflow-x-hidden group-data-[orientation=vertical]/carousel:overflow-y-auto group-data-[orientation=vertical]/carousel:overscroll-y-contain",
17
+ className
18
+ )}
19
+ {...props}
20
+ >
21
+ <slot />
24
22
  </div>
@@ -10,12 +10,9 @@ const { class: className, ...props } = Astro.props
10
10
 
11
11
  <div
12
12
  data-slot="carousel-item"
13
- role="group"
14
- aria-roledescription="slide"
15
13
  class={cn(
16
- "min-w-0 shrink-0 grow-0 basis-full",
17
- "group-data-[orientation=horizontal]/carousel:pl-4",
18
- "group-data-[orientation=vertical]/carousel:pt-4",
14
+ "min-w-0 shrink-0 grow-0 basis-full snap-start",
15
+ "group-data-[orientation=vertical]/carousel:min-h-0",
19
16
  className
20
17
  )}
21
18
  {...props}
@@ -11,7 +11,6 @@ const {
11
11
  class: className,
12
12
  variant = "outline",
13
13
  size = "icon-sm",
14
- disabled,
15
14
  ...props
16
15
  } = Astro.props
17
16
  ---
@@ -19,8 +18,6 @@ const {
19
18
  <button
20
19
  type="button"
21
20
  data-slot="carousel-next"
22
- data-manual-disabled={disabled ? "true" : undefined}
23
- disabled={disabled}
24
21
  class={cn(
25
22
  buttonVariants({ variant, size }),
26
23
  "absolute touch-manipulation rounded-full group-data-[orientation=horizontal]/carousel:inset-y-0 group-data-[orientation=horizontal]/carousel:-right-12 group-data-[orientation=horizontal]/carousel:my-auto",
@@ -11,7 +11,6 @@ const {
11
11
  class: className,
12
12
  variant = "outline",
13
13
  size = "icon-sm",
14
- disabled,
15
14
  ...props
16
15
  } = Astro.props
17
16
  ---
@@ -19,8 +18,6 @@ const {
19
18
  <button
20
19
  type="button"
21
20
  data-slot="carousel-previous"
22
- data-manual-disabled={disabled ? "true" : undefined}
23
- disabled={disabled}
24
21
  class={cn(
25
22
  buttonVariants({ variant, size }),
26
23
  "absolute touch-manipulation rounded-full group-data-[orientation=horizontal]/carousel:inset-y-0 group-data-[orientation=horizontal]/carousel:-left-12 group-data-[orientation=horizontal]/carousel:my-auto",
@@ -1,246 +1,46 @@
1
1
  ---
2
2
  import type { HTMLAttributes } from "astro/types"
3
- import type { EmblaOptionsType } from "embla-carousel"
4
3
 
5
4
  import { cn } from "@/lib/utils"
6
5
 
7
6
  type Props = HTMLAttributes<"div"> & {
8
- opts?: EmblaOptionsType
7
+ defaultIndex?: number
9
8
  orientation?: "horizontal" | "vertical"
9
+ drag?: boolean
10
+ loop?: boolean
10
11
  }
11
12
 
12
13
  const {
13
14
  class: className,
14
- opts,
15
+ defaultIndex,
15
16
  orientation = "horizontal",
17
+ drag,
18
+ loop,
16
19
  ...props
17
20
  } = Astro.props
18
-
19
- const resolvedOpts: EmblaOptionsType = {
20
- ...opts,
21
- axis: orientation === "horizontal" ? "x" : "y",
22
- }
23
21
  ---
24
22
 
25
23
  <div
26
24
  data-slot="carousel"
25
+ data-default-index={defaultIndex}
27
26
  data-orientation={orientation}
28
- data-carousel-options={JSON.stringify(resolvedOpts)}
27
+ data-drag={drag}
28
+ data-loop={loop}
29
29
  class={cn("group/carousel relative", className)}
30
- role="region"
31
- aria-roledescription="carousel"
32
30
  {...props}
33
31
  >
34
32
  <slot />
35
33
  </div>
36
34
 
37
35
  <script>
38
- import EmblaCarousel, {
39
- type EmblaCarouselType,
40
- type EmblaOptionsType,
41
- } from "embla-carousel"
42
-
43
- type CarouselRoot = HTMLElement & {
44
- __fulldevCarouselApi?: EmblaCarouselType
45
- }
46
-
47
- type CarouselInstance = {
48
- cleanup: () => void
49
- }
50
-
51
- type CarouselStore = Map<CarouselRoot, CarouselInstance>
52
-
53
- declare global {
54
- interface Window {
55
- __fulldevCarouselInitialized?: boolean
56
- __fulldevCarouselStore?: CarouselStore
57
- }
58
- }
59
-
60
- if (!window.__fulldevCarouselInitialized) {
61
- window.__fulldevCarouselInitialized = true
62
- window.__fulldevCarouselStore ??= new Map<CarouselRoot, CarouselInstance>()
63
-
64
- const store = window.__fulldevCarouselStore
65
-
66
- const getDetails = (api: EmblaCarouselType) => ({
67
- api,
68
- canScrollPrev: api.canScrollPrev(),
69
- canScrollNext: api.canScrollNext(),
70
- selectedScrollSnap: api.selectedScrollSnap(),
71
- scrollSnapList: api.scrollSnapList(),
72
- })
73
-
74
- const emit = (
75
- root: CarouselRoot,
76
- type: "carousel:init" | "carousel:select",
77
- api: EmblaCarouselType
78
- ) => {
79
- root.dispatchEvent(
80
- new CustomEvent(type, {
81
- detail: getDetails(api),
82
- })
83
- )
84
- }
85
-
86
- const parseOptions = (root: CarouselRoot): EmblaOptionsType => {
87
- const rawOptions = root.getAttribute("data-carousel-options")
88
-
89
- if (!rawOptions) {
90
- return {}
91
- }
92
-
93
- try {
94
- return JSON.parse(rawOptions) as EmblaOptionsType
95
- } catch {
96
- return {}
97
- }
98
- }
99
-
100
- const syncButton = (button: Element | null, enabled: boolean) => {
101
- if (!(button instanceof HTMLButtonElement)) {
102
- return
103
- }
104
-
105
- if (button.dataset.manualDisabled === "true") {
106
- button.disabled = true
107
- return
108
- }
109
-
110
- button.disabled = !enabled
111
- }
112
-
113
- const cleanupDisconnectedCarousels = () => {
114
- for (const [root, instance] of store.entries()) {
115
- if (document.contains(root)) {
116
- continue
117
- }
118
-
119
- instance.cleanup()
120
- store.delete(root)
121
- }
122
- }
123
-
124
- const initCarousel = (root: Element) => {
125
- if (!(root instanceof HTMLElement) || store.has(root)) {
126
- return
127
- }
128
-
129
- const carouselRoot = root as CarouselRoot
130
- const viewport = carouselRoot.querySelector(
131
- '[data-slot="carousel-content"]'
132
- )
133
- const prevButton = carouselRoot.querySelector(
134
- '[data-slot="carousel-previous"]'
135
- )
136
- const nextButton = carouselRoot.querySelector(
137
- '[data-slot="carousel-next"]'
138
- )
139
-
140
- if (!(viewport instanceof HTMLElement)) {
141
- return
142
- }
143
-
144
- const api = EmblaCarousel(viewport, parseOptions(carouselRoot))
145
-
146
- const sync = () => {
147
- const details = getDetails(api)
148
-
149
- carouselRoot.dataset.canScrollPrev = details.canScrollPrev
150
- ? "true"
151
- : "false"
152
- carouselRoot.dataset.canScrollNext = details.canScrollNext
153
- ? "true"
154
- : "false"
155
- carouselRoot.dataset.selectedScrollSnap = String(
156
- details.selectedScrollSnap
157
- )
158
-
159
- syncButton(prevButton, details.canScrollPrev)
160
- syncButton(nextButton, details.canScrollNext)
161
-
162
- emit(carouselRoot, "carousel:select", api)
163
- }
164
-
165
- const onPrevClick = () => {
166
- api.scrollPrev()
167
- }
168
-
169
- const onNextClick = () => {
170
- api.scrollNext()
171
- }
172
-
173
- const onKeyDown = (event: KeyboardEvent) => {
174
- const isVertical = carouselRoot.dataset.orientation === "vertical"
175
-
176
- if (!isVertical && event.key === "ArrowLeft") {
177
- event.preventDefault()
178
- api.scrollPrev()
179
- }
180
-
181
- if (!isVertical && event.key === "ArrowRight") {
182
- event.preventDefault()
183
- api.scrollNext()
184
- }
185
-
186
- if (isVertical && event.key === "ArrowUp") {
187
- event.preventDefault()
188
- api.scrollPrev()
189
- }
190
-
191
- if (isVertical && event.key === "ArrowDown") {
192
- event.preventDefault()
193
- api.scrollNext()
194
- }
195
- }
196
-
197
- if (prevButton instanceof HTMLElement) {
198
- prevButton.addEventListener("click", onPrevClick)
199
- }
200
-
201
- if (nextButton instanceof HTMLElement) {
202
- nextButton.addEventListener("click", onNextClick)
203
- }
204
-
205
- carouselRoot.addEventListener("keydown", onKeyDown, true)
206
-
207
- api.on("reInit", sync)
208
- api.on("select", sync)
209
-
210
- carouselRoot.__fulldevCarouselApi = api
211
-
212
- sync()
213
- requestAnimationFrame(() => emit(carouselRoot, "carousel:init", api))
214
-
215
- store.set(carouselRoot, {
216
- cleanup: () => {
217
- api.off("reInit", sync)
218
- api.off("select", sync)
219
-
220
- if (prevButton instanceof HTMLElement) {
221
- prevButton.removeEventListener("click", onPrevClick)
222
- }
223
-
224
- if (nextButton instanceof HTMLElement) {
225
- nextButton.removeEventListener("click", onNextClick)
226
- }
227
-
228
- carouselRoot.removeEventListener("keydown", onKeyDown, true)
229
- delete carouselRoot.__fulldevCarouselApi
230
- api.destroy()
231
- },
232
- })
233
- }
234
-
235
- const initCarousels = () => {
236
- cleanupDisconnectedCarousels()
237
-
238
- document
239
- .querySelectorAll('[data-slot="carousel"]')
240
- .forEach((root) => initCarousel(root))
241
- }
242
-
243
- initCarousels()
244
- document.addEventListener("astro:page-load", initCarousels)
245
- }
36
+ import { create } from "@data-slot/carousel"
37
+
38
+ const controllers: ReturnType<typeof create> = []
39
+ const initialize = () => controllers.push(...create())
40
+ initialize()
41
+ document.addEventListener("astro:page-load", initialize)
42
+ document.addEventListener("astro:before-swap", () => {
43
+ for (const controller of controllers) controller.destroy()
44
+ controllers.length = 0
45
+ })
246
46
  </script>
@@ -1,8 +1,4 @@
1
- export type {
2
- EmblaCarouselType as CarouselApi,
3
- EmblaOptionsType as CarouselOptions,
4
- EmblaPluginType as CarouselPlugin,
5
- } from "embla-carousel"
1
+ export type { CarouselController, CarouselOptions } from "@data-slot/carousel"
6
2
 
7
3
  export { default as Carousel } from "./carousel.astro"
8
4
  export { default as CarouselContent } from "./carousel-content.astro"
@@ -29,6 +29,12 @@ const {
29
29
  <script>
30
30
  import { create } from "@data-slot/collapsible"
31
31
 
32
- create()
33
- document.addEventListener("astro:page-load", () => create())
32
+ const controllers: ReturnType<typeof create> = []
33
+ const initialize = () => controllers.push(...create())
34
+ initialize()
35
+ document.addEventListener("astro:page-load", initialize)
36
+ document.addEventListener("astro:before-swap", () => {
37
+ for (const controller of controllers) controller.destroy()
38
+ controllers.length = 0
39
+ })
34
40
  </script>
@@ -38,7 +38,7 @@ const {
38
38
  data-align-offset={alignOffset}
39
39
  data-avoid-collisions={avoidCollisions}
40
40
  data-collision-padding={collisionPadding}
41
- class="isolate z-50"
41
+ class="isolate z-[1000]"
42
42
  >
43
43
  <div
44
44
  data-slot="combobox-content"
@@ -4,6 +4,7 @@ import XIcon from "@lucide/astro/icons/x"
4
4
 
5
5
  import { cn } from "@/lib/utils"
6
6
  import InputGroupAddon from "@/components/ui/input-group/input-group-addon.astro"
7
+ import InputGroupButton from "@/components/ui/input-group/input-group-button.astro"
7
8
  import InputGroupInput from "@/components/ui/input-group/input-group-input.astro"
8
9
  import InputGroup from "@/components/ui/input-group/input-group.astro"
9
10
 
@@ -24,7 +25,12 @@ const {
24
25
  } = Astro.props
25
26
  ---
26
27
 
27
- <InputGroup class={cn("w-auto", className)}>
28
+ <InputGroup
29
+ class={cn(
30
+ "has-[[data-slot=combobox-input]:focus-visible]:border-ring has-[[data-slot=combobox-input]:focus-visible]:ring-ring/50 w-auto has-[[data-slot=combobox-input]:focus-visible]:ring-3",
31
+ className
32
+ )}
33
+ >
28
34
  <InputGroupInput
29
35
  type={type}
30
36
  data-slot="combobox-input"
@@ -42,14 +48,15 @@ const {
42
48
  }
43
49
  {
44
50
  showClear && (
45
- <button
51
+ <InputGroupButton
46
52
  type="button"
53
+ variant="ghost"
54
+ size="icon-xs"
47
55
  data-slot="combobox-clear"
48
- class="inline-flex size-6 shrink-0 items-center justify-center rounded-[calc(var(--radius)-5px)] p-0 text-sm shadow-none outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
49
56
  disabled={disabled}
50
57
  >
51
58
  <XIcon class="pointer-events-none" />
52
- </button>
59
+ </InputGroupButton>
53
60
  )
54
61
  }
55
62
  </InputGroupAddon>
@@ -3,6 +3,7 @@ import type { HTMLAttributes } from "astro/types"
3
3
  import ChevronDownIcon from "@lucide/astro/icons/chevron-down"
4
4
 
5
5
  import { cn } from "@/lib/utils"
6
+ import InputGroupButton from "@/components/ui/input-group/input-group-button.astro"
6
7
 
7
8
  type Props = HTMLAttributes<"button"> & {
8
9
  showIcon?: boolean
@@ -16,13 +17,12 @@ const {
16
17
  } = Astro.props
17
18
  ---
18
19
 
19
- <button
20
- type={type}
20
+ <InputGroupButton
21
+ type={type ?? "button"}
22
+ variant="ghost"
23
+ size="icon-xs"
21
24
  data-slot="combobox-trigger"
22
- class={cn(
23
- "[&_svg]:text-muted-foreground inline-flex size-6 shrink-0 items-center justify-center gap-2 rounded-[calc(var(--radius)-5px)] p-0 text-sm shadow-none outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
24
- className
25
- )}
25
+ class={cn("[&_svg]:text-muted-foreground", className)}
26
26
  {...props}
27
27
  >
28
28
  <slot />
@@ -31,4 +31,4 @@ const {
31
31
  <ChevronDownIcon class="text-muted-foreground pointer-events-none size-4" />
32
32
  )
33
33
  }
34
- </button>
34
+ </InputGroupButton>