@gunjo/ui 0.0.1-alpha.0 → 0.0.1-alpha.2

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 (224) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +90 -0
  3. package/README.md +52 -91
  4. package/package.json +47 -6
  5. package/src/components/display/Accordion.tsx +185 -0
  6. package/src/components/display/AccordionGroup.tsx +155 -0
  7. package/src/components/display/ActionDataTable.tsx +413 -0
  8. package/src/components/display/ActivityTimelineCard.tsx +483 -0
  9. package/src/components/display/AnalyticsCard.tsx +167 -0
  10. package/src/components/display/AssetCard.tsx +242 -0
  11. package/src/components/display/AssetGrid.tsx +164 -0
  12. package/src/components/display/Avatar.tsx +127 -0
  13. package/src/components/display/AvatarGroup.tsx +131 -0
  14. package/src/components/{atoms → display}/Badge.tsx +3 -3
  15. package/src/components/display/BarChart.tsx +247 -0
  16. package/src/components/{molecules → display}/Card.tsx +1 -1
  17. package/src/components/display/Carousel.tsx +593 -0
  18. package/src/components/display/ChartLegend.tsx +124 -0
  19. package/src/components/display/ChatMessage.tsx +382 -0
  20. package/src/components/display/ChoroplethMap.tsx +613 -0
  21. package/src/components/display/Code.tsx +42 -0
  22. package/src/components/display/CodeBlock.tsx +338 -0
  23. package/src/components/display/ColorSwatch.tsx +71 -0
  24. package/src/components/display/ConcentricProgressCard.tsx +545 -0
  25. package/src/components/display/DataTable.tsx +522 -0
  26. package/src/components/display/DistributionBar.tsx +102 -0
  27. package/src/components/display/DocNote.tsx +36 -0
  28. package/src/components/display/DonutChart.tsx +257 -0
  29. package/src/components/display/EmptyState.tsx +44 -0
  30. package/src/components/display/FileTree.tsx +180 -0
  31. package/src/components/display/GaugeChart.tsx +219 -0
  32. package/src/components/display/HeatmapChart.tsx +266 -0
  33. package/src/components/display/Icon.tsx +66 -0
  34. package/src/components/display/ImagePreview.tsx +140 -0
  35. package/src/components/{atoms → display}/Img.tsx +46 -12
  36. package/src/components/display/LabeledDonutCard.tsx +475 -0
  37. package/src/components/display/LineChart.tsx +464 -0
  38. package/src/components/{molecules → display}/List.tsx +20 -13
  39. package/src/components/display/MarkdownRenderer.tsx +157 -0
  40. package/src/components/display/MetadataList.tsx +81 -0
  41. package/src/components/display/MiniDistributionBarCard.tsx +314 -0
  42. package/src/components/display/PieChart.tsx +234 -0
  43. package/src/components/display/QuadrantMatrix.tsx +330 -0
  44. package/src/components/display/RadarChart.tsx +335 -0
  45. package/src/components/display/RadialBarChart.tsx +264 -0
  46. package/src/components/display/RetentionCohortCard.tsx +350 -0
  47. package/src/components/display/RibbonChart.tsx +618 -0
  48. package/src/components/display/SearchableAccordion.tsx +270 -0
  49. package/src/components/display/SegmentTimelineCard.tsx +452 -0
  50. package/src/components/display/SegmentedGaugeCard.tsx +607 -0
  51. package/src/components/display/Spacer.tsx +51 -0
  52. package/src/components/display/SparklineChart.tsx +394 -0
  53. package/src/components/display/StackedBarChart.tsx +393 -0
  54. package/src/components/display/Statistic.tsx +70 -0
  55. package/src/components/{molecules → display}/Table.tsx +22 -7
  56. package/src/components/display/Tag.tsx +80 -0
  57. package/src/components/display/TagEditor.tsx +141 -0
  58. package/src/components/display/Timeline.tsx +121 -0
  59. package/src/components/{atoms → display}/ToolPill.tsx +42 -18
  60. package/src/components/display/TreeView.tsx +226 -0
  61. package/src/components/display/chart-tooltip.tsx +423 -0
  62. package/src/components/display/chart-utils.ts +71 -0
  63. package/src/components/display/circular-chart-utils.ts +147 -0
  64. package/src/components/display/generated/default-variant-keys.ts +90 -0
  65. package/src/components/display/generated/variant-keys.ts +169 -0
  66. package/src/components/{atoms → feedback}/Alert.tsx +12 -5
  67. package/src/components/feedback/Banner.tsx +90 -0
  68. package/src/components/{molecules → feedback}/NotificationCenter.tsx +64 -31
  69. package/src/components/feedback/ProgressWidget.tsx +44 -0
  70. package/src/components/{atoms → feedback}/Spinner.tsx +2 -2
  71. package/src/components/{molecules → feedback}/StatusBar.tsx +4 -4
  72. package/src/components/feedback/StatusScreen.tsx +148 -0
  73. package/src/components/{molecules → feedback}/Stepper.tsx +10 -5
  74. package/src/components/feedback/Toast.tsx +108 -0
  75. package/src/components/feedback/ToastProvider.tsx +78 -0
  76. package/src/components/feedback/generated/default-variant-keys.ts +16 -0
  77. package/src/components/feedback/generated/variant-keys.ts +21 -0
  78. package/src/components/generated/component-manifest.ts +1568 -454
  79. package/src/components/generated/component-style-hints.ts +1958 -718
  80. package/src/components/{atoms → inputs}/ButtonVariants.ts +13 -3
  81. package/src/components/inputs/Calendar.tsx +212 -0
  82. package/src/components/inputs/ChatComposer.tsx +75 -0
  83. package/src/components/inputs/ChatInput.tsx +528 -0
  84. package/src/components/{atoms → inputs}/Checkbox.tsx +2 -2
  85. package/src/components/inputs/Combobox.tsx +175 -0
  86. package/src/components/inputs/CopyButton.tsx +187 -0
  87. package/src/components/inputs/DatePicker.tsx +519 -0
  88. package/src/components/inputs/DateRangePicker.tsx +878 -0
  89. package/src/components/inputs/EditableField.tsx +182 -0
  90. package/src/components/{organisms → inputs}/FileUploader.tsx +24 -9
  91. package/src/components/inputs/FilterButton.tsx +163 -0
  92. package/src/components/{molecules → inputs}/Form.tsx +20 -3
  93. package/src/components/{atoms → inputs}/Input.tsx +2 -0
  94. package/src/components/inputs/InputOTP.tsx +75 -0
  95. package/src/components/inputs/Mention.tsx +279 -0
  96. package/src/components/inputs/NumberInput.tsx +109 -0
  97. package/src/components/inputs/PasswordGroup.tsx +138 -0
  98. package/src/components/inputs/PasswordInput.tsx +74 -0
  99. package/src/components/inputs/PasswordRequirementList.tsx +96 -0
  100. package/src/components/inputs/PasswordStrengthMeter.tsx +93 -0
  101. package/src/components/inputs/PhoneInput.tsx +99 -0
  102. package/src/components/inputs/PostalCodeInput.tsx +98 -0
  103. package/src/components/inputs/RangeSlider.tsx +129 -0
  104. package/src/components/inputs/SearchInput.tsx +76 -0
  105. package/src/components/inputs/Select.tsx +39 -0
  106. package/src/components/{atoms → inputs}/Slider.tsx +18 -5
  107. package/src/components/{molecules → inputs}/SortButton.tsx +5 -2
  108. package/src/components/{atoms → inputs}/Switch.tsx +15 -4
  109. package/src/components/inputs/TagInput.tsx +114 -0
  110. package/src/components/{atoms → inputs}/Textarea.tsx +1 -0
  111. package/src/components/inputs/TimePicker.tsx +150 -0
  112. package/src/components/inputs/Toggle.tsx +48 -0
  113. package/src/components/{atoms → inputs}/ToggleGroup.tsx +2 -2
  114. package/src/components/inputs/TooltipButton.tsx +148 -0
  115. package/src/components/inputs/VoiceInputButton.tsx +317 -0
  116. package/src/components/inputs/calendar-holidays.ts +56 -0
  117. package/src/components/inputs/generated/default-variant-keys.ts +32 -0
  118. package/src/components/{atoms → inputs}/generated/variant-keys.ts +19 -27
  119. package/src/components/layout/AspectRatio.tsx +12 -0
  120. package/src/components/layout/AssetInspectorPanel.tsx +416 -0
  121. package/src/components/layout/Cluster.tsx +56 -0
  122. package/src/components/layout/CollapsiblePanelToggle.tsx +94 -0
  123. package/src/components/layout/Container.tsx +43 -0
  124. package/src/components/layout/DeviceFrame.tsx +227 -0
  125. package/src/components/layout/Grid.tsx +65 -0
  126. package/src/components/layout/HStack.tsx +73 -0
  127. package/src/components/{organisms → layout}/InspectorPanel.tsx +6 -5
  128. package/src/components/layout/MarqueeFrame.tsx +158 -0
  129. package/src/components/layout/Resizable.tsx +94 -0
  130. package/src/components/layout/ScrollArea.tsx +71 -0
  131. package/src/components/{organisms → layout}/SpatialCanvas.tsx +12 -7
  132. package/src/components/layout/VStack.tsx +69 -0
  133. package/src/components/layout/generated/default-variant-keys.ts +16 -0
  134. package/src/components/layout/generated/variant-keys.ts +21 -0
  135. package/src/components/{molecules → navigation}/Breadcrumb.tsx +5 -4
  136. package/src/components/navigation/Command.tsx +266 -0
  137. package/src/components/navigation/CommandPalette.tsx +83 -0
  138. package/src/components/navigation/DocumentPager.tsx +171 -0
  139. package/src/components/navigation/Footer.tsx +88 -0
  140. package/src/components/navigation/Header.tsx +80 -0
  141. package/src/components/{molecules → navigation}/Menubar.tsx +45 -12
  142. package/src/components/navigation/NavigationMenu.tsx +128 -0
  143. package/src/components/navigation/PageAside.tsx +84 -0
  144. package/src/components/{molecules → navigation}/Pagination.tsx +60 -7
  145. package/src/components/{organisms → navigation}/RightRail.tsx +1 -1
  146. package/src/components/navigation/Sidebar.tsx +223 -0
  147. package/src/components/navigation/SidebarItem.tsx +160 -0
  148. package/src/components/{molecules → navigation}/Tabs.tsx +2 -2
  149. package/src/components/navigation/TextLink.tsx +71 -0
  150. package/src/components/navigation/generated/default-variant-keys.ts +12 -0
  151. package/src/components/navigation/generated/variant-keys.ts +13 -0
  152. package/src/components/overlay/AIChatInput.tsx +5 -0
  153. package/src/components/overlay/AIChatMessage.tsx +6 -0
  154. package/src/components/overlay/AlertDialog.tsx +145 -0
  155. package/src/components/overlay/ChatPanel.tsx +180 -0
  156. package/src/components/{molecules → overlay}/ContextMenu.tsx +65 -29
  157. package/src/components/{molecules → overlay}/Dialog.tsx +21 -13
  158. package/src/components/overlay/Drawer.tsx +131 -0
  159. package/src/components/{molecules → overlay}/DropdownMenu.tsx +52 -17
  160. package/src/components/overlay/FloatingPanel.tsx +90 -0
  161. package/src/components/overlay/HoverCard.tsx +36 -0
  162. package/src/components/overlay/MediaLightbox.tsx +403 -0
  163. package/src/components/overlay/MediaPickerDialog.tsx +198 -0
  164. package/src/components/overlay/Modal.tsx +103 -0
  165. package/src/components/overlay/OnboardingFlow.tsx +172 -0
  166. package/src/components/overlay/Popover.tsx +36 -0
  167. package/src/components/overlay/ShareModal.tsx +324 -0
  168. package/src/components/{molecules → overlay}/Sheet.tsx +76 -19
  169. package/src/components/overlay/Tooltip.tsx +130 -0
  170. package/src/components/overlay/generated/default-variant-keys.ts +14 -0
  171. package/src/components/overlay/generated/variant-keys.ts +17 -0
  172. package/src/components/patterns/BlogTemplate.tsx +46 -0
  173. package/src/components/{templates → patterns}/DashboardTemplate.tsx +2 -2
  174. package/src/components/patterns/DocsTemplate.tsx +41 -0
  175. package/src/components/{templates → patterns}/MediaLibraryTemplate.tsx +1 -1
  176. package/src/components/patterns/OnboardingTemplate.tsx +32 -0
  177. package/src/components/patterns/PricingTemplate.tsx +106 -0
  178. package/src/globals.css +173 -22
  179. package/src/index.ts +177 -76
  180. package/tailwind-theme-extend.cjs +48 -3
  181. package/design/atoms-metadata.json +0 -82
  182. package/design/molecules-metadata.json +0 -130
  183. package/design/organisms-metadata.json +0 -38
  184. package/design/templates-metadata.json +0 -38
  185. package/src/components/atoms/Avatar.tsx +0 -57
  186. package/src/components/atoms/Select.tsx +0 -28
  187. package/src/components/atoms/generated/default-variant-keys.ts +0 -36
  188. package/src/components/molecules/AIChatInput.tsx +0 -140
  189. package/src/components/molecules/AIChatMessage.tsx +0 -109
  190. package/src/components/molecules/Accordion.tsx +0 -99
  191. package/src/components/molecules/Calendar.tsx +0 -60
  192. package/src/components/molecules/Carousel.tsx +0 -261
  193. package/src/components/molecules/Command.tsx +0 -152
  194. package/src/components/molecules/FilterButton.tsx +0 -133
  195. package/src/components/molecules/HoverCard.tsx +0 -29
  196. package/src/components/molecules/Modal.tsx +0 -66
  197. package/src/components/molecules/Popover.tsx +0 -31
  198. package/src/components/molecules/ProgressWidget.tsx +0 -40
  199. package/src/components/molecules/Resizable.tsx +0 -47
  200. package/src/components/molecules/ScrollArea.tsx +0 -48
  201. package/src/components/molecules/SidebarItem.tsx +0 -134
  202. package/src/components/molecules/Toast.tsx +0 -57
  203. package/src/components/molecules/Tooltip.tsx +0 -30
  204. package/src/components/molecules/generated/default-variant-keys.ts +0 -22
  205. package/src/components/molecules/generated/variant-keys.ts +0 -33
  206. package/src/components/organisms/CommandPalette.tsx +0 -58
  207. package/src/components/organisms/FloatingPanel.tsx +0 -46
  208. package/src/components/organisms/ShareModal.tsx +0 -182
  209. package/src/components/organisms/ToastProvider.tsx +0 -49
  210. /package/src/components/{atoms → display}/Kbd.tsx +0 -0
  211. /package/src/components/{atoms → display}/Separator.tsx +0 -0
  212. /package/src/components/{atoms → display}/Skeleton.tsx +0 -0
  213. /package/src/components/{atoms → feedback}/Progress.tsx +0 -0
  214. /package/src/components/{atoms → inputs}/Button.tsx +0 -0
  215. /package/src/components/{atoms → inputs}/Label.tsx +0 -0
  216. /package/src/components/{atoms → inputs}/RadioGroup.tsx +0 -0
  217. /package/src/components/{organisms → navigation}/AppRail.tsx +0 -0
  218. /package/src/components/{templates → patterns}/AuthTemplate.tsx +0 -0
  219. /package/src/components/{templates → patterns}/BannalyzeTemplate.tsx +0 -0
  220. /package/src/components/{templates → patterns}/ChatTemplate.tsx +0 -0
  221. /package/src/components/{templates → patterns}/EditorTemplate.tsx +0 -0
  222. /package/src/components/{templates → patterns}/KanbanTemplate.tsx +0 -0
  223. /package/src/components/{templates → patterns}/LandingTemplate.tsx +0 -0
  224. /package/src/components/{templates → patterns}/SettingsTemplate.tsx +0 -0
@@ -1,261 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import useEmblaCarousel, {
5
- type UseEmblaCarouselType,
6
- } from "embla-carousel-react"
7
- import { ArrowLeft, ArrowRight } from "lucide-react"
8
-
9
- import { cn } from "../../lib/utils"
10
- import { Button } from "../atoms/Button"
11
-
12
- type CarouselApi = UseEmblaCarouselType[1]
13
- type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
14
- type CarouselOptions = UseCarouselParameters[0]
15
- type CarouselPlugin = UseCarouselParameters[1]
16
-
17
- type CarouselProps = {
18
- opts?: CarouselOptions
19
- plugins?: CarouselPlugin
20
- orientation?: "horizontal" | "vertical"
21
- setApi?: (api: CarouselApi) => void
22
- }
23
-
24
- type CarouselContextProps = {
25
- carouselRef: ReturnType<typeof useEmblaCarousel>[0]
26
- api: CarouselApi
27
- scrollPrev: () => void
28
- scrollNext: () => void
29
- canScrollPrev: boolean
30
- canScrollNext: boolean
31
- } & CarouselProps
32
-
33
- const CarouselContext = React.createContext<CarouselContextProps | null>(null)
34
-
35
- function useCarousel() {
36
- const context = React.useContext(CarouselContext)
37
-
38
- if (!context) {
39
- throw new Error("useCarousel must be used within a <Carousel />")
40
- }
41
-
42
- return context
43
- }
44
-
45
- const Carousel = React.forwardRef<
46
- HTMLDivElement,
47
- React.HTMLAttributes<HTMLDivElement> & CarouselProps
48
- >(
49
- (
50
- {
51
- orientation = "horizontal",
52
- opts,
53
- setApi,
54
- plugins,
55
- className,
56
- children,
57
- ...props
58
- },
59
- ref
60
- ) => {
61
- const [carouselRef, api] = useEmblaCarousel(
62
- {
63
- ...opts,
64
- axis: orientation === "horizontal" ? "x" : "y",
65
- },
66
- plugins
67
- )
68
- const [canScrollPrev, setCanScrollPrev] = React.useState(false)
69
- const [canScrollNext, setCanScrollNext] = React.useState(false)
70
-
71
- const onSelect = React.useCallback((api: CarouselApi) => {
72
- if (!api) {
73
- return
74
- }
75
-
76
- setCanScrollPrev(api.canScrollPrev())
77
- setCanScrollNext(api.canScrollNext())
78
- }, [])
79
-
80
- const scrollPrev = React.useCallback(() => {
81
- api?.scrollPrev()
82
- }, [api])
83
-
84
- const scrollNext = React.useCallback(() => {
85
- api?.scrollNext()
86
- }, [api])
87
-
88
- const handleKeyDown = React.useCallback(
89
- (event: React.KeyboardEvent<HTMLDivElement>) => {
90
- if (event.key === "ArrowLeft") {
91
- event.preventDefault()
92
- scrollPrev()
93
- } else if (event.key === "ArrowRight") {
94
- event.preventDefault()
95
- scrollNext()
96
- }
97
- },
98
- [scrollPrev, scrollNext]
99
- )
100
-
101
- React.useEffect(() => {
102
- if (!api || !setApi) {
103
- return
104
- }
105
-
106
- setApi(api)
107
- }, [api, setApi])
108
-
109
- React.useEffect(() => {
110
- if (!api) {
111
- return
112
- }
113
-
114
- onSelect(api)
115
- api.on("reInit", onSelect)
116
- api.on("select", onSelect)
117
-
118
- return () => {
119
- api?.off("select", onSelect)
120
- }
121
- }, [api, onSelect])
122
-
123
- return (
124
- <CarouselContext.Provider
125
- value={{
126
- carouselRef,
127
- api: api,
128
- opts,
129
- orientation: orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
130
- scrollPrev,
131
- scrollNext,
132
- canScrollPrev,
133
- canScrollNext,
134
- }}
135
- >
136
- <div
137
- ref={ref}
138
- onKeyDown={handleKeyDown}
139
- className={cn("relative w-[640px]", className)}
140
- role="region"
141
- aria-roledescription="carousel"
142
- {...props}
143
- >
144
- {children}
145
- </div>
146
- </CarouselContext.Provider>
147
- )
148
- }
149
- )
150
- Carousel.displayName = "Carousel"
151
-
152
- const CarouselContent = React.forwardRef<
153
- HTMLDivElement,
154
- React.HTMLAttributes<HTMLDivElement>
155
- >(({ className, ...props }, ref) => {
156
- const { carouselRef, orientation } = useCarousel()
157
-
158
- return (
159
- <div ref={carouselRef} className="overflow-hidden">
160
- <div
161
- ref={ref}
162
- className={cn(
163
- "flex",
164
- orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
165
- className
166
- )}
167
- {...props}
168
- />
169
- </div>
170
- )
171
- })
172
- CarouselContent.displayName = "CarouselContent"
173
-
174
- const CarouselItem = React.forwardRef<
175
- HTMLDivElement,
176
- React.HTMLAttributes<HTMLDivElement>
177
- >(({ className, ...props }, ref) => {
178
- const { orientation } = useCarousel()
179
-
180
- return (
181
- <div
182
- ref={ref}
183
- role="group"
184
- aria-roledescription="slide"
185
- className={cn(
186
- "min-w-0 shrink-0 grow-0 basis-full",
187
- orientation === "horizontal" ? "pl-4" : "pt-4",
188
- className
189
- )}
190
- {...props}
191
- />
192
- )
193
- })
194
- CarouselItem.displayName = "CarouselItem"
195
-
196
- const CarouselPrevious = React.forwardRef<
197
- HTMLButtonElement,
198
- React.ComponentProps<typeof Button>
199
- >(({ className, variant = "outline", size = "icon", ...props }, ref) => {
200
- const { orientation, scrollPrev, canScrollPrev } = useCarousel()
201
-
202
- return (
203
- <Button
204
- ref={ref}
205
- variant={variant}
206
- size={size}
207
- className={cn(
208
- "absolute h-8 w-8 rounded-full",
209
- orientation === "horizontal"
210
- ? "-left-12 top-1/2 -translate-y-1/2"
211
- : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
212
- className
213
- )}
214
- disabled={!canScrollPrev}
215
- onClick={scrollPrev}
216
- {...props}
217
- >
218
- <ArrowLeft className="h-4 w-4" />
219
- <span className="sr-only">Previous slide</span>
220
- </Button>
221
- )
222
- })
223
- CarouselPrevious.displayName = "CarouselPrevious"
224
-
225
- const CarouselNext = React.forwardRef<
226
- HTMLButtonElement,
227
- React.ComponentProps<typeof Button>
228
- >(({ className, variant = "outline", size = "icon", ...props }, ref) => {
229
- const { orientation, scrollNext, canScrollNext } = useCarousel()
230
-
231
- return (
232
- <Button
233
- ref={ref}
234
- variant={variant}
235
- size={size}
236
- className={cn(
237
- "absolute h-8 w-8 rounded-full",
238
- orientation === "horizontal"
239
- ? "-right-12 top-1/2 -translate-y-1/2"
240
- : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
241
- className
242
- )}
243
- disabled={!canScrollNext}
244
- onClick={scrollNext}
245
- {...props}
246
- >
247
- <ArrowRight className="h-4 w-4" />
248
- <span className="sr-only">Next slide</span>
249
- </Button>
250
- )
251
- })
252
- CarouselNext.displayName = "CarouselNext"
253
-
254
- export {
255
- type CarouselApi,
256
- Carousel,
257
- CarouselContent,
258
- CarouselItem,
259
- CarouselPrevious,
260
- CarouselNext,
261
- }
@@ -1,152 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { Command as CommandPrimitive } from "cmdk"
5
- import * as DialogPrimitive from "@radix-ui/react-dialog"
6
- import { Search } from "lucide-react"
7
-
8
- import { cn } from "../../lib/utils"
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-[320px] w-full flex-col overflow-hidden rounded-md border bg-popover text-popover-foreground",
18
- className
19
- )}
20
- {...props}
21
- />
22
- ))
23
- Command.displayName = CommandPrimitive.displayName
24
-
25
- const CommandDialog = ({ children, ...props }: React.ComponentProps<typeof CommandPrimitive.Dialog>) => {
26
- return (
27
- <CommandPrimitive.Dialog
28
- {...props}
29
- className={cn(
30
- "fixed inset-0 z-50 flex items-start justify-center bg-overlay/80 p-4 pt-[10%]",
31
- props.className
32
- )}
33
- >
34
- <DialogPrimitive.Title className="hidden">Command Menu</DialogPrimitive.Title>
35
- <div className="w-full max-w-lg overflow-hidden rounded-lg bg-popover text-popover-foreground shadow-lg">
36
- {children}
37
- </div>
38
- </CommandPrimitive.Dialog>
39
- )
40
- }
41
-
42
- const CommandInput = React.forwardRef<
43
- React.ElementRef<typeof CommandPrimitive.Input>,
44
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
45
- >(({ className, ...props }, ref) => (
46
- <div className="flex items-center border-b px-3 py-2" cmdk-input-wrapper="">
47
- <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
48
- <CommandPrimitive.Input
49
- ref={ref}
50
- className={cn(
51
- "flex h-10 w-full rounded-md bg-transparent text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
52
- className
53
- )}
54
- {...props}
55
- />
56
- </div>
57
- ))
58
- CommandInput.displayName = CommandPrimitive.Input.displayName
59
-
60
- const CommandList = React.forwardRef<
61
- React.ElementRef<typeof CommandPrimitive.List>,
62
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
63
- >(({ className, ...props }, ref) => (
64
- <CommandPrimitive.List
65
- ref={ref}
66
- className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
67
- {...props}
68
- />
69
- ))
70
- CommandList.displayName = CommandPrimitive.List.displayName
71
-
72
- const CommandEmpty = React.forwardRef<
73
- React.ElementRef<typeof CommandPrimitive.Empty>,
74
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
75
- >((props, ref) => (
76
- <CommandPrimitive.Empty
77
- ref={ref}
78
- className="py-6 text-center text-sm"
79
- {...props}
80
- />
81
- ))
82
- CommandEmpty.displayName = CommandPrimitive.Empty.displayName
83
-
84
- const CommandGroup = React.forwardRef<
85
- React.ElementRef<typeof CommandPrimitive.Group>,
86
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
87
- >(({ className, ...props }, ref) => (
88
- <CommandPrimitive.Group
89
- ref={ref}
90
- className={cn(
91
- "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-semibold [&_[cmdk-group-heading]]:text-muted-foreground",
92
- className
93
- )}
94
- {...props}
95
- />
96
- ))
97
- CommandGroup.displayName = CommandPrimitive.Group.displayName
98
-
99
- const CommandSeparator = React.forwardRef<
100
- React.ElementRef<typeof CommandPrimitive.Separator>,
101
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
102
- >(({ className, ...props }, ref) => (
103
- <CommandPrimitive.Separator
104
- ref={ref}
105
- className={cn("-mx-1 h-px bg-border", className)}
106
- {...props}
107
- />
108
- ))
109
- CommandSeparator.displayName = CommandPrimitive.Separator.displayName
110
-
111
- const CommandItem = React.forwardRef<
112
- React.ElementRef<typeof CommandPrimitive.Item>,
113
- React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
114
- >(({ className, ...props }, ref) => (
115
- <CommandPrimitive.Item
116
- ref={ref}
117
- className={cn(
118
- "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
119
- className
120
- )}
121
- {...props}
122
- />
123
- ))
124
- CommandItem.displayName = CommandPrimitive.Item.displayName
125
-
126
- const CommandShortcut = ({
127
- className,
128
- ...props
129
- }: React.HTMLAttributes<HTMLSpanElement>) => {
130
- return (
131
- <span
132
- className={cn(
133
- "ml-auto text-xs tracking-widest text-muted-foreground",
134
- className
135
- )}
136
- {...props}
137
- />
138
- )
139
- }
140
- CommandShortcut.displayName = "CommandShortcut"
141
-
142
- export {
143
- Command,
144
- CommandDialog,
145
- CommandInput,
146
- CommandList,
147
- CommandEmpty,
148
- CommandGroup,
149
- CommandItem,
150
- CommandShortcut,
151
- CommandSeparator,
152
- }
@@ -1,133 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { Filter as FilterIcon, Check } from "lucide-react"
5
- import { Button, ButtonProps } from "../atoms/Button"
6
- import { Popover, PopoverTrigger, PopoverContent } from "./Popover"
7
- import { Command, CommandGroup, CommandItem, CommandList } from "./Command"
8
- import { cn } from "../../lib/utils"
9
- import { Badge } from "../atoms/Badge"
10
- import type { FilterButtonVariantKey } from "./generated/variant-keys"
11
- import { filterButtonDefaultVariantKey } from "./generated/default-variant-keys"
12
-
13
- export interface FilterOption {
14
- label: string
15
- value: string
16
- }
17
-
18
- export interface FilterButtonProps extends ButtonProps {
19
- title?: string
20
- options: FilterOption[]
21
- selectedValues: Set<string>
22
- onFilterChange: (values: Set<string>) => void
23
- }
24
-
25
- const FilterButton = React.forwardRef<HTMLButtonElement, FilterButtonProps>(
26
- ({ className, title = "Filter", options, selectedValues, onFilterChange, variant = "outline", size = "sm", ...props }, ref) => {
27
- const [isOpen, setIsOpen] = React.useState(false)
28
-
29
- const triggerStyles: Record<FilterButtonVariantKey, string> = {
30
- default: "flex flex-col items-center h-9 py-2 px-3 gap-2 rounded-md border border-dashed",
31
- popover: "flex flex-col w-[200px] rounded-lg border border-primary/40 bg-primary/5 text-primary",
32
- selected: "flex flex-col items-center h-9 py-2 px-3 gap-2 rounded-md border border-primary bg-primary/10 text-primary",
33
- }
34
-
35
- const triggerVariant: FilterButtonVariantKey =
36
- selectedValues.size > 0 ? "selected" : isOpen ? "popover" : filterButtonDefaultVariantKey
37
-
38
- const handleSelect = (value: string) => {
39
- const newSet = new Set(selectedValues)
40
- if (newSet.has(value)) {
41
- newSet.delete(value)
42
- } else {
43
- newSet.add(value)
44
- }
45
- onFilterChange(newSet)
46
- }
47
-
48
- return (
49
- <Popover open={isOpen} onOpenChange={setIsOpen}>
50
- <PopoverTrigger asChild>
51
- <Button
52
- ref={ref}
53
- variant={variant}
54
- size={size}
55
- className={cn(triggerStyles[triggerVariant], className)}
56
- {...props}
57
- >
58
- <FilterIcon className="h-4 w-4" />
59
- <span>{title}</span>
60
- {selectedValues.size > 0 && (
61
- <>
62
- <div className="hidden space-x-1 lg:flex bg-transparent">
63
- {selectedValues.size > 2 ? (
64
- <Badge variant="secondary" className="rounded-sm px-1 font-normal">
65
- {selectedValues.size} selected
66
- </Badge>
67
- ) : (
68
- options
69
- .filter((option) => selectedValues.has(option.value))
70
- .map((option) => (
71
- <Badge
72
- key={option.value}
73
- variant="secondary"
74
- className="rounded-sm px-1 font-normal text-[10px]"
75
- >
76
- {option.label}
77
- </Badge>
78
- ))
79
- )}
80
- </div>
81
- </>
82
- )}
83
- </Button>
84
- </PopoverTrigger>
85
- <PopoverContent className="w-[200px] p-0" align="start">
86
- <Command>
87
- <CommandList>
88
- <CommandGroup>
89
- {options.map((option) => {
90
- const isSelected = selectedValues.has(option.value)
91
- return (
92
- <CommandItem
93
- key={option.value}
94
- onSelect={() => handleSelect(option.value)}
95
- >
96
- <div
97
- className={cn(
98
- "mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary",
99
- isSelected
100
- ? "bg-primary text-primary-foreground"
101
- : "opacity-50 [&_svg]:invisible"
102
- )}
103
- >
104
- <Check className={cn("h-4 w-4")} />
105
- </div>
106
- <span>{option.label}</span>
107
- </CommandItem>
108
- )
109
- })}
110
- </CommandGroup>
111
- {selectedValues.size > 0 && (
112
- <>
113
- <div className="h-px bg-border mx-1 my-1" />
114
- <CommandGroup>
115
- <CommandItem
116
- onSelect={() => onFilterChange(new Set())}
117
- className="justify-center text-center"
118
- >
119
- Clear filters
120
- </CommandItem>
121
- </CommandGroup>
122
- </>
123
- )}
124
- </CommandList>
125
- </Command>
126
- </PopoverContent>
127
- </Popover>
128
- )
129
- }
130
- )
131
- FilterButton.displayName = "FilterButton"
132
-
133
- export { FilterButton }
@@ -1,29 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
5
-
6
- import { cn } from "../../lib/utils"
7
-
8
- const HoverCard = HoverCardPrimitive.Root
9
-
10
- const HoverCardTrigger = HoverCardPrimitive.Trigger
11
-
12
- const HoverCardContent = React.forwardRef<
13
- React.ElementRef<typeof HoverCardPrimitive.Content>,
14
- React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
15
- >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
16
- <HoverCardPrimitive.Content
17
- ref={ref}
18
- align={align}
19
- sideOffset={sideOffset}
20
- className={cn(
21
- "z-50 flex flex-col items-center w-64 w-[256px] gap-2 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
22
- className
23
- )}
24
- {...props}
25
- />
26
- ))
27
- HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
28
-
29
- export { HoverCard, HoverCardTrigger, HoverCardContent }
@@ -1,66 +0,0 @@
1
- "use client"
2
- import React, { useEffect, useRef } from 'react';
3
- import { X } from 'lucide-react';
4
- import { cn } from '../../lib/utils';
5
-
6
- export interface ModalProps {
7
- isOpen: boolean;
8
- onClose: () => void;
9
- title: string;
10
- children: React.ReactNode;
11
- footer?: React.ReactNode;
12
- }
13
-
14
- export function Modal({ isOpen, onClose, title, children, footer }: ModalProps) {
15
- const modalRef = useRef<HTMLDivElement>(null);
16
-
17
- useEffect(() => {
18
- const handleEscape = (e: KeyboardEvent) => {
19
- if (e.key === 'Escape') onClose();
20
- };
21
-
22
- if (isOpen) {
23
- document.addEventListener('keydown', handleEscape);
24
- document.body.style.overflow = 'hidden';
25
- }
26
-
27
- return () => {
28
- document.removeEventListener('keydown', handleEscape);
29
- document.body.style.overflow = 'unset';
30
- };
31
- }, [isOpen, onClose]);
32
-
33
- if (!isOpen) return null;
34
-
35
- const content = (
36
- <div data-prevent-deselect="true" className="fixed inset-0 z-[9999] flex items-center justify-center bg-overlay/60 backdrop-blur-sm animate-in fade-in duration-200" onClick={(e) => e.stopPropagation()}>
37
- <div
38
- ref={modalRef}
39
- onClick={(e) => e.stopPropagation()}
40
- className="flex flex-col w-[448px] bg-card border border-border rounded-lg shadow-xl w-full max-w-md mx-4 overflow-hidden animate-in zoom-in-95 duration-200"
41
- >
42
- <div className="flex items-center justify-between px-4 py-3 border-b border-border">
43
- <h3 className="font-semibold text-foreground">{title}</h3>
44
- <button onClick={onClose} className="text-muted-foreground hover:text-foreground transition-colors">
45
- <X size={18} />
46
- </button>
47
- </div>
48
- <div className="p-4">
49
- {children}
50
- </div>
51
- {footer && (
52
- <div className="px-4 py-3 bg-muted/50 border-t border-border flex justify-end gap-2">
53
- {footer}
54
- </div>
55
- )}
56
- </div>
57
- </div>
58
- );
59
-
60
- // Use Portal if available
61
- if (typeof document !== 'undefined') {
62
- const { createPortal } = require('react-dom');
63
- return createPortal(content, document.body);
64
- }
65
- return content;
66
- }
@@ -1,31 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as PopoverPrimitive from "@radix-ui/react-popover"
5
-
6
- import { cn } from "../../lib/utils"
7
-
8
- const Popover = PopoverPrimitive.Root
9
-
10
- const PopoverTrigger = PopoverPrimitive.Trigger
11
-
12
- const PopoverContent = React.forwardRef<
13
- React.ElementRef<typeof PopoverPrimitive.Content>,
14
- React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
15
- >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
16
- <PopoverPrimitive.Portal>
17
- <PopoverPrimitive.Content
18
- ref={ref}
19
- align={align}
20
- sideOffset={sideOffset}
21
- className={cn(
22
- "z-50 flex flex-col w-72 w-[288px] rounded-md rounded-lg border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
23
- className
24
- )}
25
- {...props}
26
- />
27
- </PopoverPrimitive.Portal>
28
- ))
29
- PopoverContent.displayName = PopoverPrimitive.Content.displayName
30
-
31
- export { Popover, PopoverTrigger, PopoverContent }