@eggspot/ui 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/eslint.config.js +4 -0
  2. package/package.json +66 -0
  3. package/postcss.config.mjs +1 -0
  4. package/src/components/Button.machine.tsx +50 -0
  5. package/src/components/Button.tsx +249 -0
  6. package/src/components/Button.variants.tsx +186 -0
  7. package/src/components/ButtonGroup.tsx +56 -0
  8. package/src/components/Calendar.tsx +275 -0
  9. package/src/components/Calendar.utils.tsx +22 -0
  10. package/src/components/Checkbox.tsx +199 -0
  11. package/src/components/ConfirmDialog.tsx +183 -0
  12. package/src/components/DashboardLayout/DashboardLayout.tsx +348 -0
  13. package/src/components/DashboardLayout/SidebarNav.tsx +509 -0
  14. package/src/components/DashboardLayout/index.ts +33 -0
  15. package/src/components/DataTable/DataTable.tsx +557 -0
  16. package/src/components/DataTable/DataTableColumnHeader.tsx +122 -0
  17. package/src/components/DataTable/DataTableDisplaySettings.tsx +265 -0
  18. package/src/components/DataTable/DataTableFloatingBar.tsx +44 -0
  19. package/src/components/DataTable/DataTablePagination.tsx +168 -0
  20. package/src/components/DataTable/DataTableStates.tsx +69 -0
  21. package/src/components/DataTable/DataTableToolbarContainer.tsx +47 -0
  22. package/src/components/DataTable/hooks/use-data-table-settings.ts +101 -0
  23. package/src/components/DataTable/index.ts +7 -0
  24. package/src/components/DataTable/types/data-table.ts +97 -0
  25. package/src/components/DatePicker.tsx +213 -0
  26. package/src/components/DatePicker.utils.tsx +38 -0
  27. package/src/components/Datefield.tsx +109 -0
  28. package/src/components/Datefield.utils.ts +10 -0
  29. package/src/components/Dialog.tsx +167 -0
  30. package/src/components/Field.tsx +49 -0
  31. package/src/components/Filter/Filter.store.tsx +122 -0
  32. package/src/components/Filter/Filter.tsx +11 -0
  33. package/src/components/Filter/Filter.types.ts +107 -0
  34. package/src/components/Filter/FilterBar.tsx +38 -0
  35. package/src/components/Filter/FilterBuilder.tsx +158 -0
  36. package/src/components/Filter/FilterField/DateModeRowValue.tsx +250 -0
  37. package/src/components/Filter/FilterField/FilterAsyncSelect.tsx +191 -0
  38. package/src/components/Filter/FilterField/FilterDateMode.tsx +241 -0
  39. package/src/components/Filter/FilterField/FilterDateRange.tsx +169 -0
  40. package/src/components/Filter/FilterField/FilterSelect.tsx +208 -0
  41. package/src/components/Filter/FilterField/FilterSingleDate.tsx +277 -0
  42. package/src/components/Filter/FilterField/OptionItem.tsx +112 -0
  43. package/src/components/Filter/FilterField/index.ts +6 -0
  44. package/src/components/Filter/FilterRow.tsx +527 -0
  45. package/src/components/Filter/index.ts +17 -0
  46. package/src/components/Form.tsx +195 -0
  47. package/src/components/Heading.tsx +41 -0
  48. package/src/components/Input.tsx +221 -0
  49. package/src/components/InputOTP.tsx +78 -0
  50. package/src/components/Label.tsx +65 -0
  51. package/src/components/Layout.tsx +129 -0
  52. package/src/components/ListBox.tsx +97 -0
  53. package/src/components/Menu.tsx +152 -0
  54. package/src/components/NativeSelect.tsx +77 -0
  55. package/src/components/NumberInput.tsx +114 -0
  56. package/src/components/Popover.tsx +44 -0
  57. package/src/components/Provider.tsx +22 -0
  58. package/src/components/RadioGroup.tsx +191 -0
  59. package/src/components/Resizable.tsx +71 -0
  60. package/src/components/ScrollArea.tsx +57 -0
  61. package/src/components/Select.tsx +626 -0
  62. package/src/components/Select.utils.tsx +64 -0
  63. package/src/components/Separator.tsx +25 -0
  64. package/src/components/Sheet.tsx +147 -0
  65. package/src/components/Sonner.tsx +96 -0
  66. package/src/components/Spinner.tsx +30 -0
  67. package/src/components/Switch.tsx +51 -0
  68. package/src/components/Text.tsx +35 -0
  69. package/src/components/Tooltip.tsx +58 -0
  70. package/src/consts/config.ts +2 -0
  71. package/src/hooks/.gitkeep +0 -0
  72. package/src/lib/utils.ts +10 -0
  73. package/tsconfig.json +11 -0
  74. package/tsconfig.lint.json +8 -0
@@ -0,0 +1,191 @@
1
+ "use client"
2
+
3
+ import { Label } from "@eggspot/ui/components/Label"
4
+ import { cn } from "@eggspot/ui/lib/utils"
5
+ import { useControllableState } from "@radix-ui/react-use-controllable-state"
6
+ import { cva, VariantProps } from "class-variance-authority"
7
+ import { Circle } from "lucide-react"
8
+ import {
9
+ Radio as AriaRadio,
10
+ RadioGroup as AriaRadioGroup,
11
+ RadioGroupProps as AriaRadioGroupProps,
12
+ RadioProps as AriaRadioProps,
13
+ composeRenderProps,
14
+ } from "react-aria-components"
15
+
16
+ function BaseRadioGroup({ className, ...props }: AriaRadioGroupProps) {
17
+ return (
18
+ <AriaRadioGroup
19
+ aria-label="radio"
20
+ className={composeRenderProps(className, (className, renderProps) =>
21
+ cn("group/radiogroup flex flex-col flex-wrap gap-2", className)
22
+ )}
23
+ {...props}
24
+ />
25
+ )
26
+ }
27
+
28
+ const radioVariants = cva(
29
+ [
30
+ "group/radio flex cursor-pointer items-center text-sm",
31
+ /* Disabled */
32
+ "data-[disabled]:cursor-not-allowed data-[disabled]:opacity-70",
33
+ /* Invalid */
34
+ "data-[invalid]:text-error-11",
35
+ ],
36
+ {
37
+ variants: {
38
+ variant: {
39
+ default: ["group/default gap-x-2"],
40
+ card: [
41
+ "gap-x-3.5",
42
+ "border-gray-7 rounded-md border p-3.5 transition-all duration-200",
43
+ /* Selected */
44
+ "bg-gray-2 data-selected:border-accent-9 data-selected:bg-accent-2 data-selected:border-1",
45
+ /* Hovered */
46
+ "data-hovered:border-gray-8",
47
+ /* Focus Visible */
48
+ "ring-offset-2 data-focus-visible:ring-2 data-pressed:scale-[0.99]",
49
+ ],
50
+ },
51
+ },
52
+ }
53
+ )
54
+
55
+ function Radio({
56
+ className,
57
+ children,
58
+ variant = "default",
59
+ ...props
60
+ }: AriaRadioProps & VariantProps<typeof radioVariants>) {
61
+ return (
62
+ <AriaRadio className={radioVariants({ variant })} {...props}>
63
+ {composeRenderProps(children, (children, renderProps) => (
64
+ <>
65
+ <span
66
+ className={cn(
67
+ "transition-colors",
68
+ "bg-gray-2 text-accent-contrast ring-offset-gray-1 flex aspect-square size-4 items-center justify-center rounded-full border",
69
+ /* Focus */
70
+ "group-data-[focused]/radio:outline-none",
71
+ /* Focus Visible */
72
+ "group-data-[focus-visible]/default:ring-2 group-data-[focus-visible]/default:ring-offset-2",
73
+ /* Selected */
74
+ "group-data-[selected]/radio:bg-accent-9 group-data-[selected]/radio:border-accent-9",
75
+ /* Hovered */
76
+ "group-data-hovered/radio:border-gray-8",
77
+ /* Pressed */
78
+ "group-data-pressed/radio:scale-[0.95]",
79
+ /* Selected Dark */
80
+ "dark:group-data-[selected]/radio:border-none",
81
+ /* Disabled */
82
+ "group-data-[disabled]/radio:cursor-not-allowed group-data-[disabled]/radio:opacity-50"
83
+ )}
84
+ >
85
+ {renderProps.isSelected && (
86
+ <Circle
87
+ className={cn(
88
+ "animate-in fade-in-0 zoom-in-60 size-1.5 fill-current text-current"
89
+ )}
90
+ />
91
+ )}
92
+ </span>
93
+ {children}
94
+ </>
95
+ ))}
96
+ </AriaRadio>
97
+ )
98
+ }
99
+
100
+ interface RadioOption {
101
+ value: string | number
102
+ label: string
103
+ }
104
+
105
+ interface RadioGroupProps<T extends RadioOption>
106
+ extends Omit<AriaRadioGroupProps, "value" | "onChange" | "defaultValue"> {
107
+ /** The label for the radio group. */
108
+ label?: string
109
+
110
+ /** The options for the radio group. */
111
+ options: Array<T>
112
+
113
+ /** The variant for the radio group. */
114
+ variant?: "default" | "card"
115
+
116
+ /** The class name for the radio group. */
117
+ className?: string
118
+
119
+ /** Whether to show an asterisk for the label. */
120
+ withAsterisk?: boolean
121
+
122
+ /** The tooltip for the radio group. */
123
+ tooltip?: React.ReactNode
124
+
125
+ /** Custom rendering function for each option in the radio group. */
126
+ renderOption?: (option: T) => React.ReactNode
127
+
128
+ /** If this prop is set, the radio group operates in a controlled manner and uses this value as its state. */
129
+ value?: T
130
+
131
+ /** If this prop is set, the radio group will call this function with the new value whenever the value changes. */
132
+ onChange?: (value: T | undefined) => void
133
+
134
+ /** Initial value used when the component is uncontrolled. */
135
+ defaultValue?: T
136
+ }
137
+
138
+ function RadioGroup<T extends RadioOption>({
139
+ options,
140
+ renderOption,
141
+ variant = "default",
142
+ className,
143
+ label,
144
+ withAsterisk,
145
+ tooltip,
146
+ value: controlledValue,
147
+ onChange: controlledOnChange,
148
+ defaultValue,
149
+ ...props
150
+ }: RadioGroupProps<T>) {
151
+ const [value, onChange] = useControllableState<T | undefined>({
152
+ prop: controlledValue,
153
+ defaultProp: defaultValue,
154
+ onChange: controlledOnChange,
155
+ })
156
+
157
+ return (
158
+ <BaseRadioGroup
159
+ value={JSON.stringify(value)}
160
+ onChange={(v) => onChange(JSON.parse(v))}
161
+ {...props}
162
+ >
163
+ {label && (
164
+ <Label withAsterisk={withAsterisk} tooltip={tooltip}>
165
+ {label}
166
+ </Label>
167
+ )}
168
+ <div
169
+ className={cn(
170
+ "grid",
171
+ variant === "card" && "gap-2.5",
172
+ variant === "default" && "gap-1.5",
173
+ className
174
+ )}
175
+ >
176
+ {options.map((option) => (
177
+ <Radio
178
+ key={option.value}
179
+ value={JSON.stringify(option)}
180
+ variant={variant}
181
+ >
182
+ {renderOption ? renderOption(option) : option.label}
183
+ </Radio>
184
+ ))}
185
+ </div>
186
+ </BaseRadioGroup>
187
+ )
188
+ }
189
+
190
+ export { BaseRadioGroup, Radio, RadioGroup }
191
+ export type { RadioGroupProps, RadioOption }
@@ -0,0 +1,71 @@
1
+ import * as React from "react"
2
+ import { cn } from "@eggspot/ui/lib/utils"
3
+ import { GripVerticalIcon } from "lucide-react"
4
+ import * as AriaResizable from "react-resizable-panels"
5
+
6
+ function ResizablePanelGroup({
7
+ className,
8
+ ...props
9
+ }: React.ComponentProps<typeof AriaResizable.PanelGroup>) {
10
+ return (
11
+ <AriaResizable.PanelGroup
12
+ data-slot="resizable-panel-group"
13
+ className={cn(
14
+ "flex h-full w-full",
15
+ "data-[panel-group-direction=vertical]:flex-col",
16
+ className
17
+ )}
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ const ResizablePanel = React.forwardRef<
24
+ React.ComponentRef<typeof AriaResizable.Panel>,
25
+ React.ComponentProps<typeof AriaResizable.Panel>
26
+ >((props, ref) => {
27
+ return (
28
+ <AriaResizable.Panel ref={ref} data-slot="resizable-panel" {...props} />
29
+ )
30
+ })
31
+
32
+ ResizablePanel.displayName = "ResizablePanel"
33
+
34
+ function ResizableHandle({
35
+ withHandle,
36
+ className,
37
+ ...props
38
+ }: React.ComponentProps<typeof AriaResizable.PanelResizeHandle> & {
39
+ withHandle?: boolean
40
+ }) {
41
+ return (
42
+ <AriaResizable.PanelResizeHandle
43
+ data-slot="resizable-handle"
44
+ className={cn(
45
+ "relative flex items-center justify-center",
46
+ "data-[panel-group-direction=horizontal]:h-full data-[panel-group-direction=horizontal]:w-px data-[panel-group-direction=horizontal]:self-center",
47
+ "data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full",
48
+ "bg-gray-6",
49
+ // "cursor-grab! data-resize-handle-active:cursor-grabbing!",
50
+ "hover:bg-gray-7 data-resize-handle-active:bg-accent-9",
51
+ "transition-colors duration-150",
52
+ className
53
+ )}
54
+ {...props}
55
+ >
56
+ {withHandle && (
57
+ <div
58
+ className={cn(
59
+ "bg-gray-5 text-gray-11 pointer-events-none z-10 flex h-5 w-3 items-center justify-center rounded-full shadow-sm",
60
+ "opacity-0 transition-opacity group-hover:opacity-100",
61
+ "data-[panel-group-direction=vertical]:rotate-90"
62
+ )}
63
+ >
64
+ <GripVerticalIcon className="size-3" aria-hidden="true" />
65
+ </div>
66
+ )}
67
+ </AriaResizable.PanelResizeHandle>
68
+ )
69
+ }
70
+
71
+ export { ResizableHandle, ResizablePanel, ResizablePanelGroup }
@@ -0,0 +1,57 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { cn } from "@eggspot/ui/lib/utils"
5
+ import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
6
+
7
+ function ScrollArea({
8
+ className,
9
+ children,
10
+ ...props
11
+ }: React.ComponentProps<typeof ScrollAreaPrimitive.Root>) {
12
+ return (
13
+ <ScrollAreaPrimitive.Root
14
+ data-slot="scroll-area"
15
+ className={cn("relative", className)}
16
+ {...props}
17
+ >
18
+ <ScrollAreaPrimitive.Viewport
19
+ data-slot="scroll-area-viewport"
20
+ className="focus-visible:ring-ring/50 size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:outline-1"
21
+ >
22
+ {children}
23
+ </ScrollAreaPrimitive.Viewport>
24
+ <ScrollBar />
25
+ <ScrollAreaPrimitive.Corner />
26
+ </ScrollAreaPrimitive.Root>
27
+ )
28
+ }
29
+
30
+ function ScrollBar({
31
+ className,
32
+ orientation = "vertical",
33
+ ...props
34
+ }: React.ComponentProps<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>) {
35
+ return (
36
+ <ScrollAreaPrimitive.ScrollAreaScrollbar
37
+ data-slot="scroll-area-scrollbar"
38
+ orientation={orientation}
39
+ className={cn(
40
+ "flex touch-none p-px transition-colors select-none",
41
+ orientation === "vertical" &&
42
+ "h-full w-2.5 border-l border-l-transparent",
43
+ orientation === "horizontal" &&
44
+ "h-2.5 flex-col border-t border-t-transparent",
45
+ className
46
+ )}
47
+ {...props}
48
+ >
49
+ <ScrollAreaPrimitive.ScrollAreaThumb
50
+ data-slot="scroll-area-thumb"
51
+ className="bg-gray-11/20 relative flex-1 rounded-full"
52
+ />
53
+ </ScrollAreaPrimitive.ScrollAreaScrollbar>
54
+ )
55
+ }
56
+
57
+ export { ScrollArea, ScrollBar }