@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,349 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@cms/utils/cn'
4
+ import * as React from 'react'
5
+ import * as RechartsPrimitive from 'recharts'
6
+
7
+ // Format: { THEME_NAME: CSS_SELECTOR }
8
+ const THEMES = { light: '', dark: '.dark' } as const
9
+
10
+ export type ChartConfig = {
11
+ [k in string]: {
12
+ label?: React.ReactNode
13
+ icon?: React.ComponentType
14
+ } & (
15
+ | { color?: string; theme?: never }
16
+ | { color?: never; theme: Record<keyof typeof THEMES, string> }
17
+ )
18
+ }
19
+
20
+ type ChartContextProps = {
21
+ config: ChartConfig
22
+ }
23
+
24
+ const ChartContext = React.createContext<ChartContextProps | null>(null)
25
+
26
+ function useChart() {
27
+ const context = React.useContext(ChartContext)
28
+
29
+ if (!context) {
30
+ throw new Error('useChart must be used within a <ChartContainer />')
31
+ }
32
+
33
+ return context
34
+ }
35
+
36
+ const ChartContainer = React.forwardRef<
37
+ HTMLDivElement,
38
+ React.ComponentProps<'div'> & {
39
+ config: ChartConfig
40
+ children: React.ComponentProps<typeof RechartsPrimitive.ResponsiveContainer>['children']
41
+ }
42
+ >(({ id, className, children, config, ...props }, ref) => {
43
+ const uniqueId = React.useId()
44
+ const chartId = `chart-${id || uniqueId.replace(/:/g, '')}`
45
+
46
+ return (
47
+ <ChartContext.Provider value={{ config }}>
48
+ <div
49
+ data-chart={chartId}
50
+ ref={ref}
51
+ className={cn(
52
+ "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
53
+ className
54
+ )}
55
+ {...props}
56
+ >
57
+ <ChartStyle id={chartId} config={config} />
58
+ <RechartsPrimitive.ResponsiveContainer>{children}</RechartsPrimitive.ResponsiveContainer>
59
+ </div>
60
+ </ChartContext.Provider>
61
+ )
62
+ })
63
+ ChartContainer.displayName = 'Chart'
64
+
65
+ const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
66
+ const colorConfig = Object.entries(config).filter(([, config]) => config.theme || config.color)
67
+
68
+ if (!colorConfig.length) {
69
+ return null
70
+ }
71
+
72
+ return (
73
+ <style
74
+ dangerouslySetInnerHTML={{
75
+ __html: Object.entries(THEMES)
76
+ .map(
77
+ ([theme, prefix]) => `
78
+ ${prefix} [data-chart=${id}] {
79
+ ${colorConfig
80
+ .map(([key, itemConfig]) => {
81
+ const color = itemConfig.theme?.[theme as keyof typeof itemConfig.theme] || itemConfig.color
82
+ return color ? ` --color-${key}: ${color};` : null
83
+ })
84
+ .join('\n')}
85
+ }
86
+ `
87
+ )
88
+ .join('\n')
89
+ }}
90
+ />
91
+ )
92
+ }
93
+
94
+ const ChartTooltip = RechartsPrimitive.Tooltip
95
+
96
+ interface ChartTooltipContentProps extends React.HTMLAttributes<HTMLDivElement> {
97
+ active?: boolean
98
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
+ payload?: any[]
100
+ label?: string
101
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
102
+ labelFormatter?: (label: any, payload: any[]) => React.ReactNode
103
+ labelClassName?: string
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ formatter?: (
106
+ value: any,
107
+ name: string,
108
+ item: any,
109
+ index: number,
110
+ payload: any[]
111
+ ) => React.ReactNode
112
+ color?: string
113
+ hideLabel?: boolean
114
+ hideIndicator?: boolean
115
+ indicator?: 'line' | 'dot' | 'dashed'
116
+ nameKey?: string
117
+ labelKey?: string
118
+ }
119
+
120
+ const ChartTooltipContent = React.forwardRef<HTMLDivElement, ChartTooltipContentProps>(
121
+ (
122
+ {
123
+ active,
124
+ payload,
125
+ className,
126
+ indicator = 'dot',
127
+ hideLabel = false,
128
+ hideIndicator = false,
129
+ label,
130
+ labelFormatter,
131
+ labelClassName,
132
+ formatter,
133
+ color,
134
+ nameKey,
135
+ labelKey
136
+ },
137
+ ref
138
+ ) => {
139
+ const { config } = useChart()
140
+
141
+ const tooltipLabel = React.useMemo(() => {
142
+ if (hideLabel || !payload?.length) {
143
+ return null
144
+ }
145
+
146
+ const [item] = payload
147
+ const key = `${labelKey || item?.dataKey || item?.name || 'value'}`
148
+ const itemConfig = getPayloadConfigFromPayload(config, item, key)
149
+ const value =
150
+ !labelKey && typeof label === 'string'
151
+ ? config[label as keyof typeof config]?.label || label
152
+ : itemConfig?.label
153
+
154
+ if (labelFormatter) {
155
+ return (
156
+ <div className={cn('font-medium', labelClassName)}>{labelFormatter(value, payload)}</div>
157
+ )
158
+ }
159
+
160
+ if (!value) {
161
+ return null
162
+ }
163
+
164
+ return <div className={cn('font-medium', labelClassName)}>{value}</div>
165
+ }, [label, labelFormatter, payload, hideLabel, labelClassName, config, labelKey])
166
+
167
+ if (!active || !payload?.length) {
168
+ return null
169
+ }
170
+
171
+ const nestLabel = payload.length === 1 && indicator !== 'dot'
172
+
173
+ return (
174
+ <div
175
+ ref={ref}
176
+ className={cn(
177
+ 'grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl',
178
+ className
179
+ )}
180
+ >
181
+ {!nestLabel ? tooltipLabel : null}
182
+ <div className="grid gap-1.5">
183
+ {payload
184
+ .filter((item) => item.type !== 'none')
185
+ .map((item, index) => {
186
+ const key = `${nameKey || item.name || item.dataKey || 'value'}`
187
+ const itemConfig = getPayloadConfigFromPayload(config, item, key)
188
+ const indicatorColor = color || item.payload.fill || item.color
189
+
190
+ return (
191
+ <div
192
+ key={item.dataKey}
193
+ className={cn(
194
+ 'flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground',
195
+ indicator === 'dot' && 'items-center'
196
+ )}
197
+ >
198
+ {formatter && item?.value !== undefined && item.name ? (
199
+ formatter(item.value, item.name, item, index, item.payload)
200
+ ) : (
201
+ <>
202
+ {itemConfig?.icon ? (
203
+ <itemConfig.icon />
204
+ ) : (
205
+ !hideIndicator && (
206
+ <div
207
+ className={cn(
208
+ 'shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]',
209
+ {
210
+ 'h-2.5 w-2.5': indicator === 'dot',
211
+ 'w-1': indicator === 'line',
212
+ 'w-0 border-[1.5px] border-dashed bg-transparent':
213
+ indicator === 'dashed',
214
+ 'my-0.5': nestLabel && indicator === 'dashed'
215
+ }
216
+ )}
217
+ style={
218
+ {
219
+ '--color-bg': indicatorColor,
220
+ '--color-border': indicatorColor
221
+ } as React.CSSProperties
222
+ }
223
+ />
224
+ )
225
+ )}
226
+ <div
227
+ className={cn(
228
+ 'flex flex-1 justify-between leading-none',
229
+ nestLabel ? 'items-end' : 'items-center'
230
+ )}
231
+ >
232
+ <div className="grid gap-1.5">
233
+ {nestLabel ? tooltipLabel : null}
234
+ <span className="text-muted-foreground">
235
+ {itemConfig?.label || item.name}
236
+ </span>
237
+ </div>
238
+ {item.value && (
239
+ <span className="font-mono font-medium tabular-nums text-foreground">
240
+ {item.value.toLocaleString()}
241
+ </span>
242
+ )}
243
+ </div>
244
+ </>
245
+ )}
246
+ </div>
247
+ )
248
+ })}
249
+ </div>
250
+ </div>
251
+ )
252
+ }
253
+ )
254
+ ChartTooltipContent.displayName = 'ChartTooltip'
255
+
256
+ const ChartLegend = RechartsPrimitive.Legend
257
+
258
+ interface ChartLegendContentProps extends React.HTMLAttributes<HTMLDivElement> {
259
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
260
+ payload?: any[]
261
+ verticalAlign?: 'top' | 'bottom' | 'middle'
262
+ hideIcon?: boolean
263
+ nameKey?: string
264
+ }
265
+
266
+ const ChartLegendContent = React.forwardRef<HTMLDivElement, ChartLegendContentProps>(
267
+ ({ className, hideIcon = false, payload, verticalAlign = 'bottom', nameKey }, ref) => {
268
+ const { config } = useChart()
269
+
270
+ if (!payload?.length) {
271
+ return null
272
+ }
273
+
274
+ return (
275
+ <div
276
+ ref={ref}
277
+ className={cn(
278
+ 'flex items-center justify-center gap-4',
279
+ verticalAlign === 'top' ? 'pb-3' : 'pt-3',
280
+ className
281
+ )}
282
+ >
283
+ {payload
284
+ .filter((item) => item.type !== 'none')
285
+ .map((item) => {
286
+ const key = `${nameKey || item.dataKey || 'value'}`
287
+ const itemConfig = getPayloadConfigFromPayload(config, item, key)
288
+
289
+ return (
290
+ <div
291
+ key={item.value}
292
+ className={cn(
293
+ 'flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground'
294
+ )}
295
+ >
296
+ {itemConfig?.icon && !hideIcon ? (
297
+ <itemConfig.icon />
298
+ ) : (
299
+ <div
300
+ className="h-2 w-2 shrink-0 rounded-[2px]"
301
+ style={{
302
+ backgroundColor: item.color
303
+ }}
304
+ />
305
+ )}
306
+ {itemConfig?.label}
307
+ </div>
308
+ )
309
+ })}
310
+ </div>
311
+ )
312
+ }
313
+ )
314
+ ChartLegendContent.displayName = 'ChartLegend'
315
+
316
+ // Helper to extract item config from a payload.
317
+ function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key: string) {
318
+ if (typeof payload !== 'object' || payload === null) {
319
+ return undefined
320
+ }
321
+
322
+ const payloadPayload =
323
+ 'payload' in payload && typeof payload.payload === 'object' && payload.payload !== null
324
+ ? payload.payload
325
+ : undefined
326
+
327
+ let configLabelKey: string = key
328
+
329
+ if (key in payload && typeof payload[key as keyof typeof payload] === 'string') {
330
+ configLabelKey = payload[key as keyof typeof payload] as string
331
+ } else if (
332
+ payloadPayload &&
333
+ key in payloadPayload &&
334
+ typeof payloadPayload[key as keyof typeof payloadPayload] === 'string'
335
+ ) {
336
+ configLabelKey = payloadPayload[key as keyof typeof payloadPayload] as string
337
+ }
338
+
339
+ return configLabelKey in config ? config[configLabelKey] : config[key as keyof typeof config]
340
+ }
341
+
342
+ export {
343
+ ChartContainer,
344
+ ChartTooltip,
345
+ ChartTooltipContent,
346
+ ChartLegend,
347
+ ChartLegendContent,
348
+ ChartStyle
349
+ }
@@ -0,0 +1,27 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@cms/utils/cn'
4
+ import * as CheckboxPrimitive from '@radix-ui/react-checkbox'
5
+ import { Check } from 'lucide-react'
6
+ import * as React from 'react'
7
+
8
+ const Checkbox = React.forwardRef<
9
+ React.ElementRef<typeof CheckboxPrimitive.Root>,
10
+ React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
11
+ >(({ className, ...props }, ref) => (
12
+ <CheckboxPrimitive.Root
13
+ ref={ref}
14
+ className={cn(
15
+ 'grid place-content-center peer size-5 shrink-0 rounded-sm border border-input-border-border bg-input focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground',
16
+ className
17
+ )}
18
+ {...props}
19
+ >
20
+ <CheckboxPrimitive.Indicator className={cn('grid place-content-center text-current')}>
21
+ <Check className="size-3.5" />
22
+ </CheckboxPrimitive.Indicator>
23
+ </CheckboxPrimitive.Root>
24
+ ))
25
+ Checkbox.displayName = CheckboxPrimitive.Root.displayName
26
+
27
+ export { Checkbox }
@@ -0,0 +1,11 @@
1
+ 'use client'
2
+
3
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible'
4
+
5
+ const Collapsible = CollapsiblePrimitive.Root
6
+
7
+ const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
8
+
9
+ const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
10
+
11
+ export { Collapsible, CollapsibleTrigger, CollapsibleContent }
@@ -0,0 +1,142 @@
1
+ 'use client'
2
+
3
+ import { cn } from '@cms/utils/cn'
4
+ import type { DialogProps } from '@radix-ui/react-dialog'
5
+ import { Command as CommandPrimitive } from 'cmdk'
6
+ import { Search } from 'lucide-react'
7
+ import * as React from 'react'
8
+ import { Dialog, DialogContent } from './dialog'
9
+
10
+ const Command = React.forwardRef<
11
+ React.ElementRef<typeof CommandPrimitive>,
12
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive>
13
+ >(({ className, ...props }, ref) => (
14
+ <CommandPrimitive
15
+ ref={ref}
16
+ className={cn(
17
+ 'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
18
+ className
19
+ )}
20
+ {...props}
21
+ />
22
+ ))
23
+ Command.displayName = CommandPrimitive.displayName
24
+
25
+ const CommandDialog = ({ children, ...props }: DialogProps) => {
26
+ return (
27
+ <Dialog {...props}>
28
+ <DialogContent className="overflow-hidden p-0">
29
+ <Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
30
+ {children}
31
+ </Command>
32
+ </DialogContent>
33
+ </Dialog>
34
+ )
35
+ }
36
+
37
+ const CommandInput = React.forwardRef<
38
+ React.ElementRef<typeof CommandPrimitive.Input>,
39
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
40
+ >(({ className, ...props }, ref) => (
41
+ <div className="flex items-center border-b px-3" cmdk-input-wrapper="">
42
+ <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
43
+ <CommandPrimitive.Input
44
+ ref={ref}
45
+ className={cn(
46
+ 'flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50',
47
+ className
48
+ )}
49
+ {...props}
50
+ />
51
+ </div>
52
+ ))
53
+
54
+ CommandInput.displayName = CommandPrimitive.Input.displayName
55
+
56
+ const CommandList = React.forwardRef<
57
+ React.ElementRef<typeof CommandPrimitive.List>,
58
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
59
+ >(({ className, ...props }, ref) => (
60
+ <CommandPrimitive.List
61
+ ref={ref}
62
+ className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}
63
+ {...props}
64
+ />
65
+ ))
66
+
67
+ CommandList.displayName = CommandPrimitive.List.displayName
68
+
69
+ const CommandEmpty = React.forwardRef<
70
+ React.ElementRef<typeof CommandPrimitive.Empty>,
71
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
72
+ >((props, ref) => (
73
+ <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />
74
+ ))
75
+
76
+ CommandEmpty.displayName = CommandPrimitive.Empty.displayName
77
+
78
+ const CommandGroup = React.forwardRef<
79
+ React.ElementRef<typeof CommandPrimitive.Group>,
80
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
81
+ >(({ className, ...props }, ref) => (
82
+ <CommandPrimitive.Group
83
+ ref={ref}
84
+ className={cn(
85
+ 'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',
86
+ className
87
+ )}
88
+ {...props}
89
+ />
90
+ ))
91
+
92
+ CommandGroup.displayName = CommandPrimitive.Group.displayName
93
+
94
+ const CommandSeparator = React.forwardRef<
95
+ React.ElementRef<typeof CommandPrimitive.Separator>,
96
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
97
+ >(({ className, ...props }, ref) => (
98
+ <CommandPrimitive.Separator
99
+ ref={ref}
100
+ className={cn('-mx-1 h-px bg-border', className)}
101
+ {...props}
102
+ />
103
+ ))
104
+ CommandSeparator.displayName = CommandPrimitive.Separator.displayName
105
+
106
+ const CommandItem = React.forwardRef<
107
+ React.ElementRef<typeof CommandPrimitive.Item>,
108
+ React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
109
+ >(({ className, ...props }, ref) => (
110
+ <CommandPrimitive.Item
111
+ ref={ref}
112
+ className={cn(
113
+ 'relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
114
+ className
115
+ )}
116
+ {...props}
117
+ />
118
+ ))
119
+
120
+ CommandItem.displayName = CommandPrimitive.Item.displayName
121
+
122
+ const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
123
+ return (
124
+ <span
125
+ className={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}
126
+ {...props}
127
+ />
128
+ )
129
+ }
130
+ CommandShortcut.displayName = 'CommandShortcut'
131
+
132
+ export {
133
+ Command,
134
+ CommandDialog,
135
+ CommandInput,
136
+ CommandList,
137
+ CommandEmpty,
138
+ CommandGroup,
139
+ CommandItem,
140
+ CommandShortcut,
141
+ CommandSeparator
142
+ }