@mrigx/ui 0.1.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.
- package/package.json +73 -0
- package/src/blocks/ContactPanel.tsx +99 -0
- package/src/blocks/FeatureGrid.tsx +38 -0
- package/src/blocks/OpticalCTA.tsx +33 -0
- package/src/blocks/OpticalHero.tsx +51 -0
- package/src/blocks/styles.ts +175 -0
- package/src/components/accordion/optical-accordion.tsx +199 -0
- package/src/components/alert/optical-alert.tsx +59 -0
- package/src/components/alert-dialog/optical-alert-dialog.tsx +143 -0
- package/src/components/ambient-light.tsx +27 -0
- package/src/components/aspect-ratio/optical-aspect-ratio.tsx +7 -0
- package/src/components/attachment/optical-attachment.tsx +25 -0
- package/src/components/avatar/optical-avatar.tsx +50 -0
- package/src/components/badge/optical-badge.tsx +36 -0
- package/src/components/breadcrumb/optical-breadcrumb.tsx +115 -0
- package/src/components/bubble/optical-bubble.tsx +25 -0
- package/src/components/button/optical-button.tsx +67 -0
- package/src/components/button-group/optical-button-group.tsx +83 -0
- package/src/components/calendar/optical-calendar.tsx +214 -0
- package/src/components/card/optical-card.tsx +44 -0
- package/src/components/carousel/optical-carousel.tsx +262 -0
- package/src/components/chart/optical-chart.tsx +369 -0
- package/src/components/checkbox/optical-checkbox.tsx +42 -0
- package/src/components/collapsible/optical-collapsible.tsx +11 -0
- package/src/components/combobox/optical-combobox.tsx +25 -0
- package/src/components/command/optical-command.tsx +153 -0
- package/src/components/context-menu/optical-context-menu.tsx +201 -0
- package/src/components/cursor/optical-cursor.tsx +10 -0
- package/src/components/data-table/optical-data-table.tsx +25 -0
- package/src/components/date-picker/optical-date-picker.tsx +25 -0
- package/src/components/dialog/optical-dialog.tsx +110 -0
- package/src/components/direction/optical-direction.tsx +25 -0
- package/src/components/drawer/optical-drawer.tsx +120 -0
- package/src/components/dropdown-menu/optical-dropdown-menu.tsx +194 -0
- package/src/components/empty/optical-empty.tsx +104 -0
- package/src/components/field/optical-field.tsx +244 -0
- package/src/components/glass-card.tsx +13 -0
- package/src/components/hover-card/optical-hover-card.tsx +30 -0
- package/src/components/icon-button/optical-icon-button.tsx +22 -0
- package/src/components/input/optical-input.tsx +29 -0
- package/src/components/input-group/optical-input-group.tsx +170 -0
- package/src/components/input-otp/optical-input-otp.tsx +71 -0
- package/src/components/item/optical-item.tsx +193 -0
- package/src/components/kbd/optical-kbd.tsx +28 -0
- package/src/components/label/optical-label.tsx +25 -0
- package/src/components/marker/optical-marker.tsx +25 -0
- package/src/components/menubar/optical-menubar.tsx +257 -0
- package/src/components/message/optical-message.tsx +25 -0
- package/src/components/message-scroller/optical-message-scroller.tsx +25 -0
- package/src/components/native-select/optical-native-select.tsx +25 -0
- package/src/components/navigation-menu/optical-navigation-menu.tsx +68 -0
- package/src/components/pagination/optical-pagination.tsx +118 -0
- package/src/components/panel/optical-panel.tsx +26 -0
- package/src/components/popover/optical-popover.tsx +32 -0
- package/src/components/prism-button.tsx +17 -0
- package/src/components/progress/optical-progress.tsx +28 -0
- package/src/components/questionnaire/optical-questionnaire.tsx +25 -0
- package/src/components/radio-group/optical-radio-group.tsx +25 -0
- package/src/components/resizable/optical-resizable.tsx +45 -0
- package/src/components/scroll-area/optical-scroll-area.tsx +48 -0
- package/src/components/select/optical-select.tsx +110 -0
- package/src/components/separator/optical-separator.tsx +31 -0
- package/src/components/sheet/optical-sheet.tsx +143 -0
- package/src/components/sidebar/optical-sidebar.tsx +762 -0
- package/src/components/skeleton/optical-skeleton.tsx +15 -0
- package/src/components/slider/optical-slider.tsx +34 -0
- package/src/components/sonner/optical-toast.tsx +45 -0
- package/src/components/spinner/optical-spinner.tsx +16 -0
- package/src/components/stained-glass-card.tsx +93 -0
- package/src/components/switch/optical-switch.tsx +31 -0
- package/src/components/table/optical-table.tsx +83 -0
- package/src/components/tabs/optical-tabs.tsx +56 -0
- package/src/components/text/liquid-tension-text.tsx +65 -0
- package/src/components/text/optical-tension-text.tsx +65 -0
- package/src/components/text/optical-text.tsx +20 -0
- package/src/components/text/prismatic-selection.tsx +5 -0
- package/src/components/textarea/optical-textarea.tsx +22 -0
- package/src/components/theme-toggle/optical-theme-toggle.tsx +45 -0
- package/src/components/toast/optical-toast.tsx +25 -0
- package/src/components/toggle/optical-toggle.tsx +45 -0
- package/src/components/toggle-group/optical-toggle-group.tsx +61 -0
- package/src/components/tooltip/optical-tooltip.tsx +33 -0
- package/src/components/typography/optical-typography.tsx +49 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/index.ts +88 -0
- package/src/templates/ContactPageTemplate.tsx +42 -0
- package/src/templates/LandingPageTemplate.tsx +29 -0
- package/src/templates/ProductPageTemplate.tsx +46 -0
- package/src/templates/styles.ts +23 -0
- package/src/utils/button-variants.ts +26 -0
- package/src/utils/cn.ts +6 -0
- package/tsconfig.json +27 -0
- package/vite.config.ts +42 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
|
|
3
|
+
import { Check, ChevronRight, Circle } from "lucide-react"
|
|
4
|
+
import { cn } from '../../utils/cn';
|
|
5
|
+
import { GlassSurface } from '@mrigx/fx';
|
|
6
|
+
|
|
7
|
+
const OpticalDropdownMenu = DropdownMenuPrimitive.Root
|
|
8
|
+
const OpticalDropdownMenuTrigger = DropdownMenuPrimitive.Trigger
|
|
9
|
+
const OpticalDropdownMenuGroup = DropdownMenuPrimitive.Group
|
|
10
|
+
const OpticalDropdownMenuPortal = DropdownMenuPrimitive.Portal
|
|
11
|
+
const OpticalDropdownMenuSub = DropdownMenuPrimitive.Sub
|
|
12
|
+
const OpticalDropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
|
|
13
|
+
|
|
14
|
+
const OpticalDropdownMenuSubTrigger = React.forwardRef<
|
|
15
|
+
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
|
16
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
|
17
|
+
inset?: boolean
|
|
18
|
+
}
|
|
19
|
+
>(({ className, inset, children, ...props }, ref) => (
|
|
20
|
+
<DropdownMenuPrimitive.SubTrigger
|
|
21
|
+
ref={ref}
|
|
22
|
+
className={cn(
|
|
23
|
+
"flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-white/10 data-[state=open]:bg-white/10 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-white",
|
|
24
|
+
inset && "pl-8",
|
|
25
|
+
className
|
|
26
|
+
)}
|
|
27
|
+
{...props}
|
|
28
|
+
>
|
|
29
|
+
{children}
|
|
30
|
+
<ChevronRight className="ml-auto opacity-50" />
|
|
31
|
+
</DropdownMenuPrimitive.SubTrigger>
|
|
32
|
+
))
|
|
33
|
+
OpticalDropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName
|
|
34
|
+
|
|
35
|
+
const OpticalDropdownMenuSubContent = React.forwardRef<
|
|
36
|
+
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
|
37
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent> & { material?: string; materialStrength?: number }
|
|
38
|
+
>(({ className, material = "glass", materialStrength = 0.5, ...props }, ref) => (
|
|
39
|
+
<DropdownMenuPrimitive.SubContent
|
|
40
|
+
ref={ref}
|
|
41
|
+
className={cn(
|
|
42
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-white/10 p-1 text-white shadow-2xl 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 relative",
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
>
|
|
47
|
+
<GlassSurface material={material} materialStrength={materialStrength} borderRadius={6} className="absolute inset-0 -z-10" />
|
|
48
|
+
{props.children}
|
|
49
|
+
</DropdownMenuPrimitive.SubContent>
|
|
50
|
+
))
|
|
51
|
+
OpticalDropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName
|
|
52
|
+
|
|
53
|
+
const OpticalDropdownMenuContent = React.forwardRef<
|
|
54
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
|
55
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> & { material?: string; materialStrength?: number }
|
|
56
|
+
>(({ className, sideOffset = 4, material = "crystal", materialStrength = 1.0, ...props }, ref) => (
|
|
57
|
+
<DropdownMenuPrimitive.Portal>
|
|
58
|
+
<DropdownMenuPrimitive.Content
|
|
59
|
+
ref={ref}
|
|
60
|
+
sideOffset={sideOffset}
|
|
61
|
+
className={cn(
|
|
62
|
+
"z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-xl border border-white/10 p-1 text-white shadow-2xl 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 relative",
|
|
63
|
+
className
|
|
64
|
+
)}
|
|
65
|
+
{...props}
|
|
66
|
+
>
|
|
67
|
+
<GlassSurface material={material} materialStrength={materialStrength} borderRadius={12} className="absolute inset-0 -z-10" />
|
|
68
|
+
{props.children}
|
|
69
|
+
</DropdownMenuPrimitive.Content>
|
|
70
|
+
</DropdownMenuPrimitive.Portal>
|
|
71
|
+
))
|
|
72
|
+
OpticalDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
|
|
73
|
+
|
|
74
|
+
const OpticalDropdownMenuItem = React.forwardRef<
|
|
75
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
|
76
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
|
77
|
+
inset?: boolean
|
|
78
|
+
}
|
|
79
|
+
>(({ className, inset, ...props }, ref) => (
|
|
80
|
+
<DropdownMenuPrimitive.Item
|
|
81
|
+
ref={ref}
|
|
82
|
+
className={cn(
|
|
83
|
+
"relative flex cursor-pointer select-none items-center gap-2 rounded-lg px-2 py-1.5 text-sm outline-none transition-colors focus:bg-white/10 focus:text-white data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 text-white/80",
|
|
84
|
+
inset && "pl-8",
|
|
85
|
+
className
|
|
86
|
+
)}
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
89
|
+
))
|
|
90
|
+
OpticalDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
|
|
91
|
+
|
|
92
|
+
const OpticalDropdownMenuCheckboxItem = React.forwardRef<
|
|
93
|
+
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
|
94
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
|
95
|
+
>(({ className, children, checked, ...props }, ref) => (
|
|
96
|
+
<DropdownMenuPrimitive.CheckboxItem
|
|
97
|
+
ref={ref}
|
|
98
|
+
className={cn(
|
|
99
|
+
"relative flex cursor-pointer select-none items-center rounded-lg py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-white/10 focus:text-white data-[disabled]:pointer-events-none data-[disabled]:opacity-50 text-white/80",
|
|
100
|
+
className
|
|
101
|
+
)}
|
|
102
|
+
checked={checked}
|
|
103
|
+
{...props}
|
|
104
|
+
>
|
|
105
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
106
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
107
|
+
<Check className="h-4 w-4" />
|
|
108
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
109
|
+
</span>
|
|
110
|
+
{children}
|
|
111
|
+
</DropdownMenuPrimitive.CheckboxItem>
|
|
112
|
+
))
|
|
113
|
+
OpticalDropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName
|
|
114
|
+
|
|
115
|
+
const OpticalDropdownMenuRadioItem = React.forwardRef<
|
|
116
|
+
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
|
117
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
|
118
|
+
>(({ className, children, ...props }, ref) => (
|
|
119
|
+
<DropdownMenuPrimitive.RadioItem
|
|
120
|
+
ref={ref}
|
|
121
|
+
className={cn(
|
|
122
|
+
"relative flex cursor-pointer select-none items-center rounded-lg py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-white/10 focus:text-white data-[disabled]:pointer-events-none data-[disabled]:opacity-50 text-white/80",
|
|
123
|
+
className
|
|
124
|
+
)}
|
|
125
|
+
{...props}
|
|
126
|
+
>
|
|
127
|
+
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
128
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
129
|
+
<Circle className="h-2 w-2 fill-current" />
|
|
130
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
131
|
+
</span>
|
|
132
|
+
{children}
|
|
133
|
+
</DropdownMenuPrimitive.RadioItem>
|
|
134
|
+
))
|
|
135
|
+
OpticalDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
|
|
136
|
+
|
|
137
|
+
const OpticalDropdownMenuLabel = React.forwardRef<
|
|
138
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
|
139
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
|
140
|
+
inset?: boolean
|
|
141
|
+
}
|
|
142
|
+
>(({ className, inset, ...props }, ref) => (
|
|
143
|
+
<DropdownMenuPrimitive.Label
|
|
144
|
+
ref={ref}
|
|
145
|
+
className={cn(
|
|
146
|
+
"px-2 py-1.5 text-xs font-semibold uppercase tracking-widest text-white/40",
|
|
147
|
+
inset && "pl-8",
|
|
148
|
+
className
|
|
149
|
+
)}
|
|
150
|
+
{...props}
|
|
151
|
+
/>
|
|
152
|
+
))
|
|
153
|
+
OpticalDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
|
|
154
|
+
|
|
155
|
+
const OpticalDropdownMenuSeparator = React.forwardRef<
|
|
156
|
+
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
|
157
|
+
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
|
158
|
+
>(({ className, ...props }, ref) => (
|
|
159
|
+
<DropdownMenuPrimitive.Separator
|
|
160
|
+
ref={ref}
|
|
161
|
+
className={cn("-mx-1 my-1 h-px bg-white/10", className)}
|
|
162
|
+
{...props}
|
|
163
|
+
/>
|
|
164
|
+
))
|
|
165
|
+
OpticalDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
|
|
166
|
+
|
|
167
|
+
const OpticalDropdownMenuShortcut = ({
|
|
168
|
+
className,
|
|
169
|
+
...props
|
|
170
|
+
}: React.HTMLAttributes<HTMLSpanElement>) => (
|
|
171
|
+
<span
|
|
172
|
+
className={cn("ml-auto text-xs tracking-widest opacity-40", className)}
|
|
173
|
+
{...props}
|
|
174
|
+
/>
|
|
175
|
+
)
|
|
176
|
+
OpticalDropdownMenuShortcut.displayName = "OpticalDropdownMenuShortcut"
|
|
177
|
+
|
|
178
|
+
export {
|
|
179
|
+
OpticalDropdownMenu,
|
|
180
|
+
OpticalDropdownMenuTrigger,
|
|
181
|
+
OpticalDropdownMenuContent,
|
|
182
|
+
OpticalDropdownMenuItem,
|
|
183
|
+
OpticalDropdownMenuCheckboxItem,
|
|
184
|
+
OpticalDropdownMenuRadioItem,
|
|
185
|
+
OpticalDropdownMenuLabel,
|
|
186
|
+
OpticalDropdownMenuSeparator,
|
|
187
|
+
OpticalDropdownMenuShortcut,
|
|
188
|
+
OpticalDropdownMenuGroup,
|
|
189
|
+
OpticalDropdownMenuPortal,
|
|
190
|
+
OpticalDropdownMenuSub,
|
|
191
|
+
OpticalDropdownMenuSubContent,
|
|
192
|
+
OpticalDropdownMenuSubTrigger,
|
|
193
|
+
OpticalDropdownMenuRadioGroup,
|
|
194
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
2
|
+
|
|
3
|
+
import { cn } from '../../utils/cn';
|
|
4
|
+
|
|
5
|
+
function Empty({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="empty"
|
|
9
|
+
className={cn(
|
|
10
|
+
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 text-balance rounded-lg border-dashed p-6 text-center md:p-12",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
data-slot="empty-header"
|
|
22
|
+
className={cn(
|
|
23
|
+
"flex max-w-sm flex-col items-center gap-2 text-center",
|
|
24
|
+
className
|
|
25
|
+
)}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const emptyMediaVariants = cva(
|
|
32
|
+
"mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
33
|
+
{
|
|
34
|
+
variants: {
|
|
35
|
+
variant: {
|
|
36
|
+
default: "bg-transparent",
|
|
37
|
+
icon: "bg-white/10 text-white flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
defaultVariants: {
|
|
41
|
+
variant: "default",
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
function EmptyMedia({
|
|
47
|
+
className,
|
|
48
|
+
variant = "default",
|
|
49
|
+
...props
|
|
50
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
|
|
51
|
+
return (
|
|
52
|
+
<div
|
|
53
|
+
data-slot="empty-icon"
|
|
54
|
+
data-variant={variant}
|
|
55
|
+
className={cn(emptyMediaVariants({ variant, className }))}
|
|
56
|
+
{...props}
|
|
57
|
+
/>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
62
|
+
return (
|
|
63
|
+
<div
|
|
64
|
+
data-slot="empty-title"
|
|
65
|
+
className={cn("text-lg font-medium tracking-tight", className)}
|
|
66
|
+
{...props}
|
|
67
|
+
/>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
72
|
+
return (
|
|
73
|
+
<div
|
|
74
|
+
data-slot="empty-description"
|
|
75
|
+
className={cn(
|
|
76
|
+
"text-white/50 [&>a:hover]:text-white text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
|
|
77
|
+
className
|
|
78
|
+
)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
85
|
+
return (
|
|
86
|
+
<div
|
|
87
|
+
data-slot="empty-content"
|
|
88
|
+
className={cn(
|
|
89
|
+
"flex w-full min-w-0 max-w-sm flex-col items-center gap-4 text-balance text-sm",
|
|
90
|
+
className
|
|
91
|
+
)}
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export {
|
|
98
|
+
Empty,
|
|
99
|
+
EmptyHeader,
|
|
100
|
+
EmptyTitle,
|
|
101
|
+
EmptyDescription,
|
|
102
|
+
EmptyContent,
|
|
103
|
+
EmptyMedia,
|
|
104
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useMemo } from "react"
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
5
|
+
|
|
6
|
+
import { cn } from '../../utils/cn';
|
|
7
|
+
import { OpticalLabel as Label } from '../label/optical-label';
|
|
8
|
+
import { Separator } from '../separator/optical-separator';
|
|
9
|
+
|
|
10
|
+
function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) {
|
|
11
|
+
return (
|
|
12
|
+
<fieldset
|
|
13
|
+
data-slot="field-set"
|
|
14
|
+
className={cn(
|
|
15
|
+
"flex flex-col gap-6",
|
|
16
|
+
"has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3",
|
|
17
|
+
className
|
|
18
|
+
)}
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function FieldLegend({
|
|
25
|
+
className,
|
|
26
|
+
variant = "legend",
|
|
27
|
+
...props
|
|
28
|
+
}: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) {
|
|
29
|
+
return (
|
|
30
|
+
<legend
|
|
31
|
+
data-slot="field-legend"
|
|
32
|
+
data-variant={variant}
|
|
33
|
+
className={cn(
|
|
34
|
+
"mb-3 font-medium",
|
|
35
|
+
"data-[variant=legend]:text-base",
|
|
36
|
+
"data-[variant=label]:text-sm",
|
|
37
|
+
className
|
|
38
|
+
)}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function FieldGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
data-slot="field-group"
|
|
48
|
+
className={cn(
|
|
49
|
+
"group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4",
|
|
50
|
+
className
|
|
51
|
+
)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const fieldVariants = cva(
|
|
58
|
+
"group/field data-[invalid=true]:text-destructive flex w-full gap-3",
|
|
59
|
+
{
|
|
60
|
+
variants: {
|
|
61
|
+
orientation: {
|
|
62
|
+
vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"],
|
|
63
|
+
horizontal: [
|
|
64
|
+
"flex-row items-center",
|
|
65
|
+
"[&>[data-slot=field-label]]:flex-auto",
|
|
66
|
+
"has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px has-[>[data-slot=field-content]]:items-start",
|
|
67
|
+
],
|
|
68
|
+
responsive: [
|
|
69
|
+
"@md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto flex-col [&>*]:w-full [&>.sr-only]:w-auto",
|
|
70
|
+
"@md/field-group:[&>[data-slot=field-label]]:flex-auto",
|
|
71
|
+
"@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px",
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
defaultVariants: {
|
|
76
|
+
orientation: "vertical",
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
function Field({
|
|
82
|
+
className,
|
|
83
|
+
orientation = "vertical",
|
|
84
|
+
...props
|
|
85
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) {
|
|
86
|
+
return (
|
|
87
|
+
<div
|
|
88
|
+
role="group"
|
|
89
|
+
data-slot="field"
|
|
90
|
+
data-orientation={orientation}
|
|
91
|
+
className={cn(fieldVariants({ orientation }), className)}
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function FieldContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
98
|
+
return (
|
|
99
|
+
<div
|
|
100
|
+
data-slot="field-content"
|
|
101
|
+
className={cn(
|
|
102
|
+
"group/field-content flex flex-1 flex-col gap-1.5 leading-snug",
|
|
103
|
+
className
|
|
104
|
+
)}
|
|
105
|
+
{...props}
|
|
106
|
+
/>
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function FieldLabel({
|
|
111
|
+
className,
|
|
112
|
+
...props
|
|
113
|
+
}: React.ComponentProps<typeof Label>) {
|
|
114
|
+
return (
|
|
115
|
+
<Label
|
|
116
|
+
data-slot="field-label"
|
|
117
|
+
className={cn(
|
|
118
|
+
"group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50",
|
|
119
|
+
"has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>[data-slot=field]]:p-4",
|
|
120
|
+
"has-data-[state=checked]:bg-white/20/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-white/20/10",
|
|
121
|
+
className
|
|
122
|
+
)}
|
|
123
|
+
{...props}
|
|
124
|
+
/>
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function FieldTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
129
|
+
return (
|
|
130
|
+
<div
|
|
131
|
+
data-slot="field-label"
|
|
132
|
+
className={cn(
|
|
133
|
+
"flex w-fit items-center gap-2 text-sm font-medium leading-snug group-data-[disabled=true]/field:opacity-50",
|
|
134
|
+
className
|
|
135
|
+
)}
|
|
136
|
+
{...props}
|
|
137
|
+
/>
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function FieldDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
142
|
+
return (
|
|
143
|
+
<p
|
|
144
|
+
data-slot="field-description"
|
|
145
|
+
className={cn(
|
|
146
|
+
"text-white/50 text-sm font-normal leading-normal group-has-[[data-orientation=horizontal]]/field:text-balance",
|
|
147
|
+
"nth-last-2:-mt-1 last:mt-0 [[data-variant=legend]+&]:-mt-1.5",
|
|
148
|
+
"[&>a:hover]:text-white [&>a]:underline [&>a]:underline-offset-4",
|
|
149
|
+
className
|
|
150
|
+
)}
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function FieldSeparator({
|
|
157
|
+
children,
|
|
158
|
+
className,
|
|
159
|
+
...props
|
|
160
|
+
}: React.ComponentProps<"div"> & {
|
|
161
|
+
children?: React.ReactNode
|
|
162
|
+
}) {
|
|
163
|
+
return (
|
|
164
|
+
<div
|
|
165
|
+
data-slot="field-separator"
|
|
166
|
+
data-content={!!children}
|
|
167
|
+
className={cn(
|
|
168
|
+
"relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2",
|
|
169
|
+
className
|
|
170
|
+
)}
|
|
171
|
+
{...props}
|
|
172
|
+
>
|
|
173
|
+
<Separator className="absolute inset-0 top-1/2" />
|
|
174
|
+
{children && (
|
|
175
|
+
<span
|
|
176
|
+
className="bg-transparent text-white/50 relative mx-auto block w-fit px-2"
|
|
177
|
+
data-slot="field-separator-content"
|
|
178
|
+
>
|
|
179
|
+
{children}
|
|
180
|
+
</span>
|
|
181
|
+
)}
|
|
182
|
+
</div>
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function FieldError({
|
|
187
|
+
className,
|
|
188
|
+
children,
|
|
189
|
+
errors,
|
|
190
|
+
...props
|
|
191
|
+
}: React.ComponentProps<"div"> & {
|
|
192
|
+
errors?: Array<{ message?: string } | undefined>
|
|
193
|
+
}) {
|
|
194
|
+
const content = useMemo(() => {
|
|
195
|
+
if (children) {
|
|
196
|
+
return children
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (!errors) {
|
|
200
|
+
return null
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (errors?.length === 1 && errors[0]?.message) {
|
|
204
|
+
return errors[0].message
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return (
|
|
208
|
+
<ul className="ml-4 flex list-disc flex-col gap-1">
|
|
209
|
+
{errors.map(
|
|
210
|
+
(error, index) =>
|
|
211
|
+
error?.message && <li key={index}>{error.message}</li>
|
|
212
|
+
)}
|
|
213
|
+
</ul>
|
|
214
|
+
)
|
|
215
|
+
}, [children, errors])
|
|
216
|
+
|
|
217
|
+
if (!content) {
|
|
218
|
+
return null
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<div
|
|
223
|
+
role="alert"
|
|
224
|
+
data-slot="field-error"
|
|
225
|
+
className={cn("text-destructive text-sm font-normal", className)}
|
|
226
|
+
{...props}
|
|
227
|
+
>
|
|
228
|
+
{content}
|
|
229
|
+
</div>
|
|
230
|
+
)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export {
|
|
234
|
+
Field,
|
|
235
|
+
FieldLabel,
|
|
236
|
+
FieldDescription,
|
|
237
|
+
FieldError,
|
|
238
|
+
FieldGroup,
|
|
239
|
+
FieldLegend,
|
|
240
|
+
FieldSeparator,
|
|
241
|
+
FieldSet,
|
|
242
|
+
FieldContent,
|
|
243
|
+
FieldTitle,
|
|
244
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { GlassSurface } from '@mrigx/fx';
|
|
3
|
+
|
|
4
|
+
export function GlassCard({ title, description, children, className = "" }: { title: string, description?: string, children?: React.ReactNode, className?: string }) {
|
|
5
|
+
return (
|
|
6
|
+
<GlassSurface className={`p-6 rounded-2xl flex flex-col gap-2 ${className}`}>
|
|
7
|
+
<h3 className="text-xl font-bold text-white tracking-wide">{title}</h3>
|
|
8
|
+
{description && <p className="text-white/60 text-sm leading-relaxed">{description}</p>}
|
|
9
|
+
{children && <div className="mt-4">{children}</div>}
|
|
10
|
+
</GlassSurface>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
|
|
3
|
+
import { cn } from '../../utils/cn';
|
|
4
|
+
import { GlassSurface } from '@mrigx/fx';
|
|
5
|
+
|
|
6
|
+
const OpticalHoverCard = HoverCardPrimitive.Root
|
|
7
|
+
|
|
8
|
+
const OpticalHoverCardTrigger = HoverCardPrimitive.Trigger
|
|
9
|
+
|
|
10
|
+
const OpticalHoverCardContent = React.forwardRef<
|
|
11
|
+
React.ElementRef<typeof HoverCardPrimitive.Content>,
|
|
12
|
+
React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content> & { material?: string; materialStrength?: number }
|
|
13
|
+
>(({ className, align = "center", sideOffset = 4, material = "glass", materialStrength = 1.0, ...props }, ref) => (
|
|
14
|
+
<HoverCardPrimitive.Content
|
|
15
|
+
ref={ref}
|
|
16
|
+
align={align}
|
|
17
|
+
sideOffset={sideOffset}
|
|
18
|
+
className={cn(
|
|
19
|
+
"z-50 w-64 rounded-xl border border-white/10 p-4 text-white shadow-2xl 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 relative",
|
|
20
|
+
className
|
|
21
|
+
)}
|
|
22
|
+
{...props}
|
|
23
|
+
>
|
|
24
|
+
<GlassSurface material={material} materialStrength={materialStrength} borderRadius={12} className="absolute inset-0 -z-10" />
|
|
25
|
+
{props.children}
|
|
26
|
+
</HoverCardPrimitive.Content>
|
|
27
|
+
))
|
|
28
|
+
OpticalHoverCardContent.displayName = HoverCardPrimitive.Content.displayName
|
|
29
|
+
|
|
30
|
+
export { OpticalHoverCard, OpticalHoverCardTrigger, OpticalHoverCardContent }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
|
|
2
|
+
import React, { forwardRef } from 'react';
|
|
3
|
+
import { RippleSurface } from '@mrigx/fx';
|
|
4
|
+
|
|
5
|
+
export interface OpticalIconButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
|
|
6
|
+
|
|
7
|
+
export const OpticalIconButton = forwardRef<HTMLButtonElement, OpticalIconButtonProps>(({ className = "", ...props }, ref) => {
|
|
8
|
+
return (
|
|
9
|
+
<RippleSurface
|
|
10
|
+
ref={ref as any}
|
|
11
|
+
material={0}
|
|
12
|
+
materialStrength={2.0}
|
|
13
|
+
borderRadius={9999}
|
|
14
|
+
className={`inline-flex items-center justify-center rounded-full h-10 w-10 text-sm font-medium transition-colors border border-white/10 bg-white/5 hover:bg-white/10 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-white/50 disabled:pointer-events-none disabled:opacity-50 ${className}`}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
OpticalIconButton.displayName = "OpticalIconButton";
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
|
|
2
|
+
import React, { forwardRef } from 'react';
|
|
3
|
+
import { useMrigSurface, useMrigInteraction } from '@mrigx/react';
|
|
4
|
+
|
|
5
|
+
export interface OpticalInputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
|
|
6
|
+
|
|
7
|
+
export const OpticalInput = forwardRef<HTMLInputElement, OpticalInputProps>(({ className = "", onChange, onFocus, ...props }, forwardedRef) => {
|
|
8
|
+
const ref = useMrigSurface<HTMLInputElement>({ material: 'glass', materialStrength: 1.0, borderRadius: 8 }, forwardedRef);
|
|
9
|
+
const { pulsePointer, pulseCenter } = useMrigInteraction();
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<input
|
|
13
|
+
ref={ref}
|
|
14
|
+
className={`flex h-10 w-full rounded-lg border border-white/10 bg-black/20 px-3 py-2 text-sm text-white transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-white/40 focus-visible:outline-none focus-visible:border-white/30 disabled:cursor-not-allowed disabled:opacity-50 ${className}`}
|
|
15
|
+
onChange={(e) => {
|
|
16
|
+
pulseCenter(e.currentTarget, 0.1);
|
|
17
|
+
onChange?.(e);
|
|
18
|
+
}}
|
|
19
|
+
onFocus={(e) => {
|
|
20
|
+
pulseCenter(e.currentTarget, 0.3);
|
|
21
|
+
onFocus?.(e);
|
|
22
|
+
}}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
26
|
+
});
|
|
27
|
+
OpticalInput.displayName = "OpticalInput";
|
|
28
|
+
|
|
29
|
+
|