@betterstart/cli 0.1.3 → 0.1.5

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 (234) hide show
  1. package/README.md +133 -0
  2. package/dist/cli.d.ts +1 -9
  3. package/dist/cli.js +13585 -367
  4. package/dist/cli.js.map +1 -1
  5. package/dist/index.d.ts +24 -266
  6. package/dist/index.js +4 -11378
  7. package/dist/index.js.map +1 -1
  8. package/package.json +29 -42
  9. package/templates/schema.json +959 -0
  10. package/templates/tiptap/hooks/use-composed-ref.ts +43 -0
  11. package/templates/tiptap/hooks/use-cursor-visibility.ts +68 -0
  12. package/templates/tiptap/hooks/use-element-rect.ts +166 -0
  13. package/templates/tiptap/hooks/use-is-breakpoint.ts +32 -0
  14. package/templates/tiptap/hooks/use-menu-navigation.ts +182 -0
  15. package/templates/tiptap/hooks/use-scrolling.ts +64 -0
  16. package/templates/tiptap/hooks/use-throttled-callback.ts +146 -0
  17. package/templates/tiptap/hooks/use-tiptap-editor.ts +46 -0
  18. package/templates/tiptap/hooks/use-unmount.ts +21 -0
  19. package/templates/tiptap/hooks/use-window-size.ts +87 -0
  20. package/templates/tiptap/lib/tiptap-utils.ts +587 -0
  21. package/templates/tiptap/styles/_keyframe-animations.scss +91 -0
  22. package/templates/tiptap/styles/_variables.scss +296 -0
  23. package/templates/tiptap/tiptap-extension/node-background-extension.ts +138 -0
  24. package/templates/tiptap/tiptap-icons/align-center-icon.tsx +38 -0
  25. package/templates/tiptap/tiptap-icons/align-justify-icon.tsx +38 -0
  26. package/templates/tiptap/tiptap-icons/align-left-icon.tsx +38 -0
  27. package/templates/tiptap/tiptap-icons/align-right-icon.tsx +38 -0
  28. package/templates/tiptap/tiptap-icons/arrow-left-icon.tsx +24 -0
  29. package/templates/tiptap/tiptap-icons/ban-icon.tsx +26 -0
  30. package/templates/tiptap/tiptap-icons/blockquote-icon.tsx +44 -0
  31. package/templates/tiptap/tiptap-icons/bold-icon.tsx +26 -0
  32. package/templates/tiptap/tiptap-icons/chevron-down-icon.tsx +26 -0
  33. package/templates/tiptap/tiptap-icons/close-icon.tsx +24 -0
  34. package/templates/tiptap/tiptap-icons/code-block-icon.tsx +38 -0
  35. package/templates/tiptap/tiptap-icons/code2-icon.tsx +32 -0
  36. package/templates/tiptap/tiptap-icons/corner-down-left-icon.tsx +26 -0
  37. package/templates/tiptap/tiptap-icons/external-link-icon.tsx +28 -0
  38. package/templates/tiptap/tiptap-icons/heading-five-icon.tsx +28 -0
  39. package/templates/tiptap/tiptap-icons/heading-four-icon.tsx +28 -0
  40. package/templates/tiptap/tiptap-icons/heading-icon.tsx +24 -0
  41. package/templates/tiptap/tiptap-icons/heading-one-icon.tsx +28 -0
  42. package/templates/tiptap/tiptap-icons/heading-six-icon.tsx +30 -0
  43. package/templates/tiptap/tiptap-icons/heading-three-icon.tsx +36 -0
  44. package/templates/tiptap/tiptap-icons/heading-two-icon.tsx +28 -0
  45. package/templates/tiptap/tiptap-icons/highlighter-icon.tsx +26 -0
  46. package/templates/tiptap/tiptap-icons/image-plus-icon.tsx +26 -0
  47. package/templates/tiptap/tiptap-icons/italic-icon.tsx +24 -0
  48. package/templates/tiptap/tiptap-icons/link-icon.tsx +28 -0
  49. package/templates/tiptap/tiptap-icons/list-icon.tsx +56 -0
  50. package/templates/tiptap/tiptap-icons/list-ordered-icon.tsx +56 -0
  51. package/templates/tiptap/tiptap-icons/list-todo-icon.tsx +50 -0
  52. package/templates/tiptap/tiptap-icons/moon-star-icon.tsx +30 -0
  53. package/templates/tiptap/tiptap-icons/redo2-icon.tsx +26 -0
  54. package/templates/tiptap/tiptap-icons/strike-icon.tsx +28 -0
  55. package/templates/tiptap/tiptap-icons/subscript-icon.tsx +38 -0
  56. package/templates/tiptap/tiptap-icons/sun-icon.tsx +58 -0
  57. package/templates/tiptap/tiptap-icons/superscript-icon.tsx +38 -0
  58. package/templates/tiptap/tiptap-icons/trash-icon.tsx +26 -0
  59. package/templates/tiptap/tiptap-icons/underline-icon.tsx +26 -0
  60. package/templates/tiptap/tiptap-icons/undo2-icon.tsx +26 -0
  61. package/templates/tiptap/tiptap-node/blockquote-node/blockquote-node.scss +37 -0
  62. package/templates/tiptap/tiptap-node/code-block-node/code-block-node.scss +54 -0
  63. package/templates/tiptap/tiptap-node/heading-node/heading-node.scss +45 -0
  64. package/templates/tiptap/tiptap-node/horizontal-rule-node/horizontal-rule-node-extension.ts +10 -0
  65. package/templates/tiptap/tiptap-node/horizontal-rule-node/horizontal-rule-node.scss +25 -0
  66. package/templates/tiptap/tiptap-node/image-node/image-node.scss +35 -0
  67. package/templates/tiptap/tiptap-node/image-upload-node/image-upload-node-extension.ts +154 -0
  68. package/templates/tiptap/tiptap-node/image-upload-node/image-upload-node.scss +249 -0
  69. package/templates/tiptap/tiptap-node/image-upload-node/image-upload-node.tsx +522 -0
  70. package/templates/tiptap/tiptap-node/image-upload-node/index.tsx +1 -0
  71. package/templates/tiptap/tiptap-node/list-node/list-node.scss +208 -0
  72. package/templates/tiptap/tiptap-node/paragraph-node/paragraph-node.scss +273 -0
  73. package/templates/tiptap/tiptap-ui/blockquote-button/blockquote-button.tsx +104 -0
  74. package/templates/tiptap/tiptap-ui/blockquote-button/index.tsx +2 -0
  75. package/templates/tiptap/tiptap-ui/blockquote-button/use-blockquote.ts +252 -0
  76. package/templates/tiptap/tiptap-ui/code-block-button/code-block-button.tsx +106 -0
  77. package/templates/tiptap/tiptap-ui/code-block-button/index.tsx +2 -0
  78. package/templates/tiptap/tiptap-ui/code-block-button/use-code-block.ts +261 -0
  79. package/templates/tiptap/tiptap-ui/color-highlight-button/color-highlight-button.scss +49 -0
  80. package/templates/tiptap/tiptap-ui/color-highlight-button/color-highlight-button.tsx +153 -0
  81. package/templates/tiptap/tiptap-ui/color-highlight-button/index.tsx +2 -0
  82. package/templates/tiptap/tiptap-ui/color-highlight-button/use-color-highlight.ts +345 -0
  83. package/templates/tiptap/tiptap-ui/color-highlight-popover/color-highlight-popover.tsx +207 -0
  84. package/templates/tiptap/tiptap-ui/color-highlight-popover/index.tsx +1 -0
  85. package/templates/tiptap/tiptap-ui/heading-button/heading-button.tsx +107 -0
  86. package/templates/tiptap/tiptap-ui/heading-button/index.tsx +2 -0
  87. package/templates/tiptap/tiptap-ui/heading-button/use-heading.ts +314 -0
  88. package/templates/tiptap/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu.tsx +131 -0
  89. package/templates/tiptap/tiptap-ui/heading-dropdown-menu/index.tsx +2 -0
  90. package/templates/tiptap/tiptap-ui/heading-dropdown-menu/use-heading-dropdown-menu.ts +130 -0
  91. package/templates/tiptap/tiptap-ui/image-upload-button/image-upload-button.tsx +114 -0
  92. package/templates/tiptap/tiptap-ui/image-upload-button/index.tsx +2 -0
  93. package/templates/tiptap/tiptap-ui/image-upload-button/use-image-upload.ts +192 -0
  94. package/templates/tiptap/tiptap-ui/link-popover/index.tsx +2 -0
  95. package/templates/tiptap/tiptap-ui/link-popover/link-popover.tsx +285 -0
  96. package/templates/tiptap/tiptap-ui/link-popover/use-link-popover.ts +286 -0
  97. package/templates/tiptap/tiptap-ui/list-button/index.tsx +2 -0
  98. package/templates/tiptap/tiptap-ui/list-button/list-button.tsx +108 -0
  99. package/templates/tiptap/tiptap-ui/list-button/use-list.ts +329 -0
  100. package/templates/tiptap/tiptap-ui/list-dropdown-menu/index.tsx +1 -0
  101. package/templates/tiptap/tiptap-ui/list-dropdown-menu/list-dropdown-menu.tsx +123 -0
  102. package/templates/tiptap/tiptap-ui/list-dropdown-menu/use-list-dropdown-menu.ts +203 -0
  103. package/templates/tiptap/tiptap-ui/mark-button/index.tsx +2 -0
  104. package/templates/tiptap/tiptap-ui/mark-button/mark-button.tsx +107 -0
  105. package/templates/tiptap/tiptap-ui/mark-button/use-mark.ts +206 -0
  106. package/templates/tiptap/tiptap-ui/text-align-button/index.tsx +2 -0
  107. package/templates/tiptap/tiptap-ui/text-align-button/text-align-button.tsx +118 -0
  108. package/templates/tiptap/tiptap-ui/text-align-button/use-text-align.ts +212 -0
  109. package/templates/tiptap/tiptap-ui/undo-redo-button/index.tsx +2 -0
  110. package/templates/tiptap/tiptap-ui/undo-redo-button/undo-redo-button.tsx +105 -0
  111. package/templates/tiptap/tiptap-ui/undo-redo-button/use-undo-redo.ts +173 -0
  112. package/templates/tiptap/tiptap-ui-primitive/badge/badge-colors.scss +395 -0
  113. package/templates/tiptap/tiptap-ui-primitive/badge/badge-group.scss +16 -0
  114. package/templates/tiptap/tiptap-ui-primitive/badge/badge.scss +99 -0
  115. package/templates/tiptap/tiptap-ui-primitive/badge/badge.tsx +46 -0
  116. package/templates/tiptap/tiptap-ui-primitive/badge/index.tsx +1 -0
  117. package/templates/tiptap/tiptap-ui-primitive/button/button-colors.scss +429 -0
  118. package/templates/tiptap/tiptap-ui-primitive/button/button-group.scss +22 -0
  119. package/templates/tiptap/tiptap-ui-primitive/button/button.scss +314 -0
  120. package/templates/tiptap/tiptap-ui-primitive/button/button.tsx +102 -0
  121. package/templates/tiptap/tiptap-ui-primitive/button/index.tsx +1 -0
  122. package/templates/tiptap/tiptap-ui-primitive/card/card.scss +77 -0
  123. package/templates/tiptap/tiptap-ui-primitive/card/card.tsx +59 -0
  124. package/templates/tiptap/tiptap-ui-primitive/card/index.tsx +1 -0
  125. package/templates/tiptap/tiptap-ui-primitive/dropdown-menu/dropdown-menu.scss +63 -0
  126. package/templates/tiptap/tiptap-ui-primitive/dropdown-menu/dropdown-menu.tsx +95 -0
  127. package/templates/tiptap/tiptap-ui-primitive/dropdown-menu/index.tsx +1 -0
  128. package/templates/tiptap/tiptap-ui-primitive/input/index.tsx +1 -0
  129. package/templates/tiptap/tiptap-ui-primitive/input/input.scss +45 -0
  130. package/templates/tiptap/tiptap-ui-primitive/input/input.tsx +18 -0
  131. package/templates/tiptap/tiptap-ui-primitive/popover/index.tsx +1 -0
  132. package/templates/tiptap/tiptap-ui-primitive/popover/popover.scss +63 -0
  133. package/templates/tiptap/tiptap-ui-primitive/popover/popover.tsx +33 -0
  134. package/templates/tiptap/tiptap-ui-primitive/separator/index.tsx +1 -0
  135. package/templates/tiptap/tiptap-ui-primitive/separator/separator.scss +23 -0
  136. package/templates/tiptap/tiptap-ui-primitive/separator/separator.tsx +33 -0
  137. package/templates/tiptap/tiptap-ui-primitive/spacer/index.tsx +1 -0
  138. package/templates/tiptap/tiptap-ui-primitive/spacer/spacer.tsx +21 -0
  139. package/templates/tiptap/tiptap-ui-primitive/toolbar/index.tsx +1 -0
  140. package/templates/tiptap/tiptap-ui-primitive/toolbar/toolbar.scss +98 -0
  141. package/templates/tiptap/tiptap-ui-primitive/toolbar/toolbar.tsx +113 -0
  142. package/templates/tiptap/tiptap-ui-primitive/tooltip/index.tsx +1 -0
  143. package/templates/tiptap/tiptap-ui-primitive/tooltip/tooltip.scss +43 -0
  144. package/templates/tiptap/tiptap-ui-primitive/tooltip/tooltip.tsx +223 -0
  145. package/templates/ui/accordion.tsx +52 -0
  146. package/templates/ui/alert-dialog.tsx +116 -0
  147. package/templates/ui/alert.tsx +48 -0
  148. package/templates/ui/aspect-ratio.tsx +7 -0
  149. package/templates/ui/avatar.tsx +46 -0
  150. package/templates/ui/badge.tsx +32 -0
  151. package/templates/ui/breadcrumb.tsx +98 -0
  152. package/templates/ui/button-group.tsx +77 -0
  153. package/templates/ui/button.tsx +48 -0
  154. package/templates/ui/calendar.tsx +176 -0
  155. package/templates/ui/card.tsx +54 -0
  156. package/templates/ui/carousel.tsx +234 -0
  157. package/templates/ui/chart.tsx +349 -0
  158. package/templates/ui/checkbox.tsx +27 -0
  159. package/templates/ui/collapsible.tsx +11 -0
  160. package/templates/ui/command.tsx +142 -0
  161. package/templates/ui/context-menu.tsx +188 -0
  162. package/templates/ui/curriculum-editor.tsx +601 -0
  163. package/templates/ui/date-picker.tsx +70 -0
  164. package/templates/ui/dialog.tsx +103 -0
  165. package/templates/ui/drawer.tsx +99 -0
  166. package/templates/ui/dropdown-menu.tsx +185 -0
  167. package/templates/ui/dynamic-list-field.tsx +95 -0
  168. package/templates/ui/empty.tsx +90 -0
  169. package/templates/ui/field.tsx +231 -0
  170. package/templates/ui/file-upload-example.tsx +113 -0
  171. package/templates/ui/form.tsx +172 -0
  172. package/templates/ui/hover-card.tsx +28 -0
  173. package/templates/ui/icon-picker.tsx +435 -0
  174. package/templates/ui/icons-data.ts +6 -0
  175. package/templates/ui/image-upload-field.tsx +360 -0
  176. package/templates/ui/input-group.tsx +160 -0
  177. package/templates/ui/input-otp.tsx +70 -0
  178. package/templates/ui/input.tsx +21 -0
  179. package/templates/ui/item.tsx +171 -0
  180. package/templates/ui/kbd.tsx +28 -0
  181. package/templates/ui/label.tsx +20 -0
  182. package/templates/ui/logo.tsx +113 -0
  183. package/templates/ui/markdown-editor.tsx +303 -0
  184. package/templates/ui/markdown-utils.ts +128 -0
  185. package/templates/ui/media-upload-field.tsx +255 -0
  186. package/templates/ui/menubar.tsx +230 -0
  187. package/templates/ui/navigation-menu.tsx +119 -0
  188. package/templates/ui/pagination.tsx +96 -0
  189. package/templates/ui/placeholder.tsx +25 -0
  190. package/templates/ui/popover.tsx +32 -0
  191. package/templates/ui/progress.tsx +24 -0
  192. package/templates/ui/radio-group.tsx +37 -0
  193. package/templates/ui/resizable.tsx +41 -0
  194. package/templates/ui/rich-text-editor.tsx +374 -0
  195. package/templates/ui/scroll-area.tsx +45 -0
  196. package/templates/ui/select.tsx +151 -0
  197. package/templates/ui/separator.tsx +25 -0
  198. package/templates/ui/sheet.tsx +120 -0
  199. package/templates/ui/sidebar.tsx +687 -0
  200. package/templates/ui/skeleton.tsx +7 -0
  201. package/templates/ui/slider.tsx +24 -0
  202. package/templates/ui/sonner.tsx +29 -0
  203. package/templates/ui/spinner.tsx +15 -0
  204. package/templates/ui/switch.tsx +28 -0
  205. package/templates/ui/table.tsx +93 -0
  206. package/templates/ui/tabs.tsx +54 -0
  207. package/templates/ui/textarea.tsx +20 -0
  208. package/templates/ui/toast.tsx +127 -0
  209. package/templates/ui/toggle-group.tsx +56 -0
  210. package/templates/ui/toggle.tsx +43 -0
  211. package/templates/ui/tooltip.tsx +31 -0
  212. package/templates/ui/use-mobile.tsx +19 -0
  213. package/templates/ui/video-upload-field.tsx +368 -0
  214. package/dist/chunk-EIH4RRIJ.js +0 -183
  215. package/dist/chunk-EIH4RRIJ.js.map +0 -1
  216. package/dist/chunk-NKRQYAS6.js +0 -260
  217. package/dist/chunk-NKRQYAS6.js.map +0 -1
  218. package/dist/chunk-QLVSHP7X.js +0 -235
  219. package/dist/chunk-QLVSHP7X.js.map +0 -1
  220. package/dist/chunk-WY6BC55D.js +0 -357
  221. package/dist/chunk-WY6BC55D.js.map +0 -1
  222. package/dist/config/index.d.ts +0 -93
  223. package/dist/config/index.js +0 -58
  224. package/dist/config/index.js.map +0 -1
  225. package/dist/core/index.d.ts +0 -415
  226. package/dist/core/index.js +0 -906
  227. package/dist/core/index.js.map +0 -1
  228. package/dist/import-resolver-BaZ-rzkH.d.ts +0 -123
  229. package/dist/logger-awLb347n.d.ts +0 -81
  230. package/dist/plugins/index.d.ts +0 -213
  231. package/dist/plugins/index.js +0 -365
  232. package/dist/plugins/index.js.map +0 -1
  233. package/dist/types-ByX_gl6y.d.ts +0 -232
  234. package/dist/types-eI549DEG.d.ts +0 -331
@@ -0,0 +1,77 @@
1
+ import { cn } from '@cms/utils/cn'
2
+ import { Slot } from '@radix-ui/react-slot'
3
+ import { cva, type VariantProps } from 'class-variance-authority'
4
+ import { Separator } from './separator'
5
+
6
+ const buttonGroupVariants = cva(
7
+ "flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 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",
8
+ {
9
+ variants: {
10
+ orientation: {
11
+ horizontal:
12
+ '[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none',
13
+ vertical:
14
+ 'flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none'
15
+ }
16
+ },
17
+ defaultVariants: {
18
+ orientation: 'horizontal'
19
+ }
20
+ }
21
+ )
22
+
23
+ function ButtonGroup({
24
+ className,
25
+ orientation,
26
+ ...props
27
+ }: React.ComponentProps<'div'> & VariantProps<typeof buttonGroupVariants>) {
28
+ return (
29
+ <div
30
+ role="group"
31
+ data-slot="button-group"
32
+ data-orientation={orientation}
33
+ className={cn(buttonGroupVariants({ orientation }), className)}
34
+ {...props}
35
+ />
36
+ )
37
+ }
38
+
39
+ function ButtonGroupText({
40
+ className,
41
+ asChild = false,
42
+ ...props
43
+ }: React.ComponentProps<'div'> & {
44
+ asChild?: boolean
45
+ }) {
46
+ const Comp = asChild ? Slot : 'div'
47
+
48
+ return (
49
+ <Comp
50
+ className={cn(
51
+ "bg-muted shadow-xs flex items-center gap-2 rounded-md border px-4 text-sm font-medium [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none",
52
+ className
53
+ )}
54
+ {...props}
55
+ />
56
+ )
57
+ }
58
+
59
+ function ButtonGroupSeparator({
60
+ className,
61
+ orientation = 'vertical',
62
+ ...props
63
+ }: React.ComponentProps<typeof Separator>) {
64
+ return (
65
+ <Separator
66
+ data-slot="button-group-separator"
67
+ orientation={orientation}
68
+ className={cn(
69
+ 'bg-input relative !m-0 self-stretch data-[orientation=vertical]:h-auto',
70
+ className
71
+ )}
72
+ {...props}
73
+ />
74
+ )
75
+ }
76
+
77
+ export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants }
@@ -0,0 +1,48 @@
1
+ import { cn } from '@cms/utils/cn'
2
+ import { Slot } from '@radix-ui/react-slot'
3
+ import { cva, type VariantProps } from 'class-variance-authority'
4
+ import * as React from 'react'
5
+
6
+ const buttonVariants = cva(
7
+ 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
8
+ {
9
+ variants: {
10
+ variant: {
11
+ default: 'bg-primary text-primary-foreground hover:bg-primary/90',
12
+ destructive: 'bg-destructive text-white hover:bg-destructive/90',
13
+ outline: 'border border-border bg-background hover:bg-accent hover:text-accent-foreground',
14
+ secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
15
+ ghost: 'hover:bg-accent hover:text-accent-foreground',
16
+ link: 'text-primary underline-offset-4 hover:underline'
17
+ },
18
+ size: {
19
+ default: 'h-9 px-4 py-2',
20
+ sm: 'h-8 rounded-md px-3 text-xs',
21
+ lg: 'h-10 rounded-md px-8',
22
+ icon: 'h-9 w-9'
23
+ }
24
+ },
25
+ defaultVariants: {
26
+ variant: 'default',
27
+ size: 'default'
28
+ }
29
+ }
30
+ )
31
+
32
+ export interface ButtonProps
33
+ extends React.ButtonHTMLAttributes<HTMLButtonElement>,
34
+ VariantProps<typeof buttonVariants> {
35
+ asChild?: boolean
36
+ }
37
+
38
+ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
39
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
40
+ const Comp = asChild ? Slot : 'button'
41
+ return (
42
+ <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
43
+ )
44
+ }
45
+ )
46
+ Button.displayName = 'Button'
47
+
48
+ export { Button, buttonVariants }
@@ -0,0 +1,176 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@cms/utils/cn'
4
+ import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react'
5
+ import * as React from 'react'
6
+ import { type DayButton, DayPicker, getDefaultClassNames } from 'react-day-picker'
7
+ import { Button, buttonVariants } from './button'
8
+
9
+ function Calendar({
10
+ className,
11
+ classNames,
12
+ showOutsideDays = true,
13
+ captionLayout = 'label',
14
+ buttonVariant = 'ghost',
15
+ formatters,
16
+ components,
17
+ ...props
18
+ }: React.ComponentProps<typeof DayPicker> & {
19
+ buttonVariant?: React.ComponentProps<typeof Button>['variant']
20
+ }) {
21
+ const defaultClassNames = getDefaultClassNames()
22
+
23
+ return (
24
+ <DayPicker
25
+ showOutsideDays={showOutsideDays}
26
+ className={cn(
27
+ 'bg-background group/calendar p-3 [--cell-size:2rem] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent',
28
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
29
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
30
+ className
31
+ )}
32
+ captionLayout={captionLayout}
33
+ formatters={{
34
+ formatMonthDropdown: (date) => date.toLocaleString('default', { month: 'short' }),
35
+ ...formatters
36
+ }}
37
+ classNames={{
38
+ root: cn('w-fit', defaultClassNames.root),
39
+ months: cn('relative flex flex-col gap-4 md:flex-row', defaultClassNames.months),
40
+ month: cn('flex w-full flex-col gap-4', defaultClassNames.month),
41
+ nav: cn(
42
+ 'absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1',
43
+ defaultClassNames.nav
44
+ ),
45
+ button_previous: cn(
46
+ buttonVariants({ variant: buttonVariant }),
47
+ 'h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50',
48
+ defaultClassNames.button_previous
49
+ ),
50
+ button_next: cn(
51
+ buttonVariants({ variant: buttonVariant }),
52
+ 'h-[--cell-size] w-[--cell-size] select-none p-0 aria-disabled:opacity-50',
53
+ defaultClassNames.button_next
54
+ ),
55
+ month_caption: cn(
56
+ 'flex h-[--cell-size] w-full items-center justify-center px-[--cell-size]',
57
+ defaultClassNames.month_caption
58
+ ),
59
+ dropdowns: cn(
60
+ 'flex h-[--cell-size] w-full items-center justify-center gap-1.5 text-sm font-medium',
61
+ defaultClassNames.dropdowns
62
+ ),
63
+ dropdown_root: cn(
64
+ 'has-focus:border-ring border-input-border shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border',
65
+ defaultClassNames.dropdown_root
66
+ ),
67
+ dropdown: cn('bg-popover absolute inset-0 opacity-0', defaultClassNames.dropdown),
68
+ caption_label: cn(
69
+ 'select-none font-medium',
70
+ captionLayout === 'label'
71
+ ? 'text-sm'
72
+ : '[&>svg]:text-muted-foreground flex h-8 items-center gap-1 rounded-md pl-2 pr-1 text-sm [&>svg]:size-3.5',
73
+ defaultClassNames.caption_label
74
+ ),
75
+ table: 'w-full border-collapse',
76
+ weekdays: cn('flex', defaultClassNames.weekdays),
77
+ weekday: cn(
78
+ 'text-muted-foreground flex-1 select-none rounded-md text-[0.8rem] font-normal',
79
+ defaultClassNames.weekday
80
+ ),
81
+ week: cn('mt-2 flex w-full', defaultClassNames.week),
82
+ week_number_header: cn('w-[--cell-size] select-none', defaultClassNames.week_number_header),
83
+ week_number: cn(
84
+ 'text-muted-foreground select-none text-[0.8rem]',
85
+ defaultClassNames.week_number
86
+ ),
87
+ day: cn(
88
+ 'group/day relative aspect-square h-full w-full select-none p-0 text-center [&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md',
89
+ defaultClassNames.day
90
+ ),
91
+ range_start: cn('bg-accent rounded-l-md', defaultClassNames.range_start),
92
+ range_middle: cn('rounded-none', defaultClassNames.range_middle),
93
+ range_end: cn('bg-accent rounded-r-md', defaultClassNames.range_end),
94
+ today: cn(
95
+ 'bg-accent text-accent-foreground rounded-md data-[selected=true]:rounded-none',
96
+ defaultClassNames.today
97
+ ),
98
+ outside: cn(
99
+ 'text-muted-foreground aria-selected:text-muted-foreground',
100
+ defaultClassNames.outside
101
+ ),
102
+ disabled: cn('text-muted-foreground opacity-50', defaultClassNames.disabled),
103
+ hidden: cn('invisible', defaultClassNames.hidden),
104
+ ...classNames
105
+ }}
106
+ components={{
107
+ Root: ({ className, rootRef, ...props }) => {
108
+ return <div data-slot="calendar" ref={rootRef} className={cn(className)} {...props} />
109
+ },
110
+ Chevron: ({ className, orientation, ...props }) => {
111
+ if (orientation === 'left') {
112
+ return <ChevronLeftIcon className={cn('size-4', className)} {...props} />
113
+ }
114
+
115
+ if (orientation === 'right') {
116
+ return <ChevronRightIcon className={cn('size-4', className)} {...props} />
117
+ }
118
+
119
+ return <ChevronDownIcon className={cn('size-4', className)} {...props} />
120
+ },
121
+ DayButton: CalendarDayButton,
122
+ WeekNumber: ({ children, ...props }) => {
123
+ return (
124
+ <td {...props}>
125
+ <div className="flex size-[--cell-size] items-center justify-center text-center">
126
+ {children}
127
+ </div>
128
+ </td>
129
+ )
130
+ },
131
+ ...components
132
+ }}
133
+ {...props}
134
+ />
135
+ )
136
+ }
137
+
138
+ function CalendarDayButton({
139
+ className,
140
+ day,
141
+ modifiers,
142
+ ...props
143
+ }: React.ComponentProps<typeof DayButton>) {
144
+ const defaultClassNames = getDefaultClassNames()
145
+
146
+ const ref = React.useRef<HTMLButtonElement>(null)
147
+ React.useEffect(() => {
148
+ if (modifiers.focused) ref.current?.focus()
149
+ }, [modifiers.focused])
150
+
151
+ return (
152
+ <Button
153
+ ref={ref}
154
+ variant="ghost"
155
+ size="icon"
156
+ data-day={day.date.toLocaleDateString()}
157
+ data-selected-single={
158
+ modifiers.selected &&
159
+ !modifiers.range_start &&
160
+ !modifiers.range_end &&
161
+ !modifiers.range_middle
162
+ }
163
+ data-range-start={modifiers.range_start}
164
+ data-range-end={modifiers.range_end}
165
+ data-range-middle={modifiers.range_middle}
166
+ className={cn(
167
+ 'data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 font-normal leading-none data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] [&>span]:text-xs [&>span]:opacity-70',
168
+ defaultClassNames.day,
169
+ className
170
+ )}
171
+ {...props}
172
+ />
173
+ )
174
+ }
175
+
176
+ export { Calendar, CalendarDayButton }
@@ -0,0 +1,54 @@
1
+ import { cn } from '@cms/utils/cn'
2
+ import * as React from 'react'
3
+
4
+ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
5
+ ({ className, ...props }, ref) => (
6
+ <div
7
+ ref={ref}
8
+ className={cn('rounded-xl border bg-card text-card-foreground shadow', className)}
9
+ {...props}
10
+ />
11
+ )
12
+ )
13
+ Card.displayName = 'Card'
14
+
15
+ const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
16
+ ({ className, ...props }, ref) => (
17
+ <div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
18
+ )
19
+ )
20
+ CardHeader.displayName = 'CardHeader'
21
+
22
+ const CardTitle = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
23
+ ({ className, ...props }, ref) => (
24
+ <div
25
+ ref={ref}
26
+ className={cn('font-semibold leading-none tracking-tight', className)}
27
+ {...props}
28
+ />
29
+ )
30
+ )
31
+ CardTitle.displayName = 'CardTitle'
32
+
33
+ const CardDescription = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
34
+ ({ className, ...props }, ref) => (
35
+ <div ref={ref} className={cn('text-sm text-muted-foreground', className)} {...props} />
36
+ )
37
+ )
38
+ CardDescription.displayName = 'CardDescription'
39
+
40
+ const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
41
+ ({ className, ...props }, ref) => (
42
+ <div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
43
+ )
44
+ )
45
+ CardContent.displayName = 'CardContent'
46
+
47
+ const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
48
+ ({ className, ...props }, ref) => (
49
+ <div ref={ref} className={cn('flex items-center p-6 pt-0', className)} {...props} />
50
+ )
51
+ )
52
+ CardFooter.displayName = 'CardFooter'
53
+
54
+ export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
@@ -0,0 +1,234 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@cms/utils/cn'
4
+ import useEmblaCarousel, { type UseEmblaCarouselType } from 'embla-carousel-react'
5
+ import { ArrowLeft, ArrowRight } from 'lucide-react'
6
+ import * as React from 'react'
7
+ import { Button } from './button'
8
+
9
+ type CarouselApi = UseEmblaCarouselType[1]
10
+ type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
11
+ type CarouselOptions = UseCarouselParameters[0]
12
+ type CarouselPlugin = UseCarouselParameters[1]
13
+
14
+ type CarouselProps = {
15
+ opts?: CarouselOptions
16
+ plugins?: CarouselPlugin
17
+ orientation?: 'horizontal' | 'vertical'
18
+ setApi?: (api: CarouselApi) => void
19
+ }
20
+
21
+ type CarouselContextProps = {
22
+ carouselRef: ReturnType<typeof useEmblaCarousel>[0]
23
+ api: ReturnType<typeof useEmblaCarousel>[1]
24
+ scrollPrev: () => void
25
+ scrollNext: () => void
26
+ canScrollPrev: boolean
27
+ canScrollNext: boolean
28
+ } & CarouselProps
29
+
30
+ const CarouselContext = React.createContext<CarouselContextProps | null>(null)
31
+
32
+ function useCarousel() {
33
+ const context = React.useContext(CarouselContext)
34
+
35
+ if (!context) {
36
+ throw new Error('useCarousel must be used within a <Carousel />')
37
+ }
38
+
39
+ return context
40
+ }
41
+
42
+ const Carousel = React.forwardRef<
43
+ HTMLDivElement,
44
+ React.HTMLAttributes<HTMLDivElement> & CarouselProps
45
+ >(({ orientation = 'horizontal', opts, setApi, plugins, className, children, ...props }, ref) => {
46
+ const [carouselRef, api] = useEmblaCarousel(
47
+ {
48
+ ...opts,
49
+ axis: orientation === 'horizontal' ? 'x' : 'y'
50
+ },
51
+ plugins
52
+ )
53
+ const [canScrollPrev, setCanScrollPrev] = React.useState(false)
54
+ const [canScrollNext, setCanScrollNext] = React.useState(false)
55
+
56
+ const onSelect = React.useCallback((api: CarouselApi) => {
57
+ if (!api) {
58
+ return
59
+ }
60
+
61
+ setCanScrollPrev(api.canScrollPrev())
62
+ setCanScrollNext(api.canScrollNext())
63
+ }, [])
64
+
65
+ const scrollPrev = React.useCallback(() => {
66
+ api?.scrollPrev()
67
+ }, [api])
68
+
69
+ const scrollNext = React.useCallback(() => {
70
+ api?.scrollNext()
71
+ }, [api])
72
+
73
+ const handleKeyDown = React.useCallback(
74
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
75
+ if (event.key === 'ArrowLeft') {
76
+ event.preventDefault()
77
+ scrollPrev()
78
+ } else if (event.key === 'ArrowRight') {
79
+ event.preventDefault()
80
+ scrollNext()
81
+ }
82
+ },
83
+ [scrollPrev, scrollNext]
84
+ )
85
+
86
+ React.useEffect(() => {
87
+ if (!api || !setApi) {
88
+ return
89
+ }
90
+
91
+ setApi(api)
92
+ }, [api, setApi])
93
+
94
+ React.useEffect(() => {
95
+ if (!api) {
96
+ return
97
+ }
98
+
99
+ onSelect(api)
100
+ api.on('reInit', onSelect)
101
+ api.on('select', onSelect)
102
+
103
+ return () => {
104
+ api?.off('select', onSelect)
105
+ }
106
+ }, [api, onSelect])
107
+
108
+ return (
109
+ <CarouselContext.Provider
110
+ value={{
111
+ carouselRef,
112
+ api: api,
113
+ opts,
114
+ orientation: orientation || (opts?.axis === 'y' ? 'vertical' : 'horizontal'),
115
+ scrollPrev,
116
+ scrollNext,
117
+ canScrollPrev,
118
+ canScrollNext
119
+ }}
120
+ >
121
+ <div
122
+ ref={ref}
123
+ onKeyDownCapture={handleKeyDown}
124
+ className={cn('relative', className)}
125
+ role="region"
126
+ aria-roledescription="carousel"
127
+ {...props}
128
+ >
129
+ {children}
130
+ </div>
131
+ </CarouselContext.Provider>
132
+ )
133
+ })
134
+ Carousel.displayName = 'Carousel'
135
+
136
+ const CarouselContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
137
+ ({ className, ...props }, ref) => {
138
+ const { carouselRef, orientation } = useCarousel()
139
+
140
+ return (
141
+ <div ref={carouselRef} className="overflow-hidden">
142
+ <div
143
+ ref={ref}
144
+ className={cn(
145
+ 'flex',
146
+ orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',
147
+ className
148
+ )}
149
+ {...props}
150
+ />
151
+ </div>
152
+ )
153
+ }
154
+ )
155
+ CarouselContent.displayName = 'CarouselContent'
156
+
157
+ const CarouselItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
158
+ ({ className, ...props }, ref) => {
159
+ const { orientation } = useCarousel()
160
+
161
+ return (
162
+ <div
163
+ ref={ref}
164
+ role="group"
165
+ aria-roledescription="slide"
166
+ className={cn(
167
+ 'min-w-0 shrink-0 grow-0 basis-full',
168
+ orientation === 'horizontal' ? 'pl-4' : 'pt-4',
169
+ className
170
+ )}
171
+ {...props}
172
+ />
173
+ )
174
+ }
175
+ )
176
+ CarouselItem.displayName = 'CarouselItem'
177
+
178
+ const CarouselPrevious = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(
179
+ ({ className, variant = 'outline', size = 'icon', ...props }, ref) => {
180
+ const { orientation, scrollPrev, canScrollPrev } = useCarousel()
181
+
182
+ return (
183
+ <Button
184
+ ref={ref}
185
+ variant={variant}
186
+ size={size}
187
+ className={cn(
188
+ 'absolute h-8 w-8 rounded-full',
189
+ orientation === 'horizontal'
190
+ ? '-left-12 top-1/2 -translate-y-1/2'
191
+ : '-top-12 left-1/2 -translate-x-1/2 rotate-90',
192
+ className
193
+ )}
194
+ disabled={!canScrollPrev}
195
+ onClick={scrollPrev}
196
+ {...props}
197
+ >
198
+ <ArrowLeft className="h-4 w-4" />
199
+ <span className="sr-only">Previous slide</span>
200
+ </Button>
201
+ )
202
+ }
203
+ )
204
+ CarouselPrevious.displayName = 'CarouselPrevious'
205
+
206
+ const CarouselNext = React.forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(
207
+ ({ className, variant = 'outline', size = 'icon', ...props }, ref) => {
208
+ const { orientation, scrollNext, canScrollNext } = useCarousel()
209
+
210
+ return (
211
+ <Button
212
+ ref={ref}
213
+ variant={variant}
214
+ size={size}
215
+ className={cn(
216
+ 'absolute h-8 w-8 rounded-full',
217
+ orientation === 'horizontal'
218
+ ? '-right-12 top-1/2 -translate-y-1/2'
219
+ : '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',
220
+ className
221
+ )}
222
+ disabled={!canScrollNext}
223
+ onClick={scrollNext}
224
+ {...props}
225
+ >
226
+ <ArrowRight className="h-4 w-4" />
227
+ <span className="sr-only">Next slide</span>
228
+ </Button>
229
+ )
230
+ }
231
+ )
232
+ CarouselNext.displayName = 'CarouselNext'
233
+
234
+ export { type CarouselApi, Carousel, CarouselContent, CarouselItem, CarouselPrevious, CarouselNext }