@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.
Files changed (93) hide show
  1. package/package.json +73 -0
  2. package/src/blocks/ContactPanel.tsx +99 -0
  3. package/src/blocks/FeatureGrid.tsx +38 -0
  4. package/src/blocks/OpticalCTA.tsx +33 -0
  5. package/src/blocks/OpticalHero.tsx +51 -0
  6. package/src/blocks/styles.ts +175 -0
  7. package/src/components/accordion/optical-accordion.tsx +199 -0
  8. package/src/components/alert/optical-alert.tsx +59 -0
  9. package/src/components/alert-dialog/optical-alert-dialog.tsx +143 -0
  10. package/src/components/ambient-light.tsx +27 -0
  11. package/src/components/aspect-ratio/optical-aspect-ratio.tsx +7 -0
  12. package/src/components/attachment/optical-attachment.tsx +25 -0
  13. package/src/components/avatar/optical-avatar.tsx +50 -0
  14. package/src/components/badge/optical-badge.tsx +36 -0
  15. package/src/components/breadcrumb/optical-breadcrumb.tsx +115 -0
  16. package/src/components/bubble/optical-bubble.tsx +25 -0
  17. package/src/components/button/optical-button.tsx +67 -0
  18. package/src/components/button-group/optical-button-group.tsx +83 -0
  19. package/src/components/calendar/optical-calendar.tsx +214 -0
  20. package/src/components/card/optical-card.tsx +44 -0
  21. package/src/components/carousel/optical-carousel.tsx +262 -0
  22. package/src/components/chart/optical-chart.tsx +369 -0
  23. package/src/components/checkbox/optical-checkbox.tsx +42 -0
  24. package/src/components/collapsible/optical-collapsible.tsx +11 -0
  25. package/src/components/combobox/optical-combobox.tsx +25 -0
  26. package/src/components/command/optical-command.tsx +153 -0
  27. package/src/components/context-menu/optical-context-menu.tsx +201 -0
  28. package/src/components/cursor/optical-cursor.tsx +10 -0
  29. package/src/components/data-table/optical-data-table.tsx +25 -0
  30. package/src/components/date-picker/optical-date-picker.tsx +25 -0
  31. package/src/components/dialog/optical-dialog.tsx +110 -0
  32. package/src/components/direction/optical-direction.tsx +25 -0
  33. package/src/components/drawer/optical-drawer.tsx +120 -0
  34. package/src/components/dropdown-menu/optical-dropdown-menu.tsx +194 -0
  35. package/src/components/empty/optical-empty.tsx +104 -0
  36. package/src/components/field/optical-field.tsx +244 -0
  37. package/src/components/glass-card.tsx +13 -0
  38. package/src/components/hover-card/optical-hover-card.tsx +30 -0
  39. package/src/components/icon-button/optical-icon-button.tsx +22 -0
  40. package/src/components/input/optical-input.tsx +29 -0
  41. package/src/components/input-group/optical-input-group.tsx +170 -0
  42. package/src/components/input-otp/optical-input-otp.tsx +71 -0
  43. package/src/components/item/optical-item.tsx +193 -0
  44. package/src/components/kbd/optical-kbd.tsx +28 -0
  45. package/src/components/label/optical-label.tsx +25 -0
  46. package/src/components/marker/optical-marker.tsx +25 -0
  47. package/src/components/menubar/optical-menubar.tsx +257 -0
  48. package/src/components/message/optical-message.tsx +25 -0
  49. package/src/components/message-scroller/optical-message-scroller.tsx +25 -0
  50. package/src/components/native-select/optical-native-select.tsx +25 -0
  51. package/src/components/navigation-menu/optical-navigation-menu.tsx +68 -0
  52. package/src/components/pagination/optical-pagination.tsx +118 -0
  53. package/src/components/panel/optical-panel.tsx +26 -0
  54. package/src/components/popover/optical-popover.tsx +32 -0
  55. package/src/components/prism-button.tsx +17 -0
  56. package/src/components/progress/optical-progress.tsx +28 -0
  57. package/src/components/questionnaire/optical-questionnaire.tsx +25 -0
  58. package/src/components/radio-group/optical-radio-group.tsx +25 -0
  59. package/src/components/resizable/optical-resizable.tsx +45 -0
  60. package/src/components/scroll-area/optical-scroll-area.tsx +48 -0
  61. package/src/components/select/optical-select.tsx +110 -0
  62. package/src/components/separator/optical-separator.tsx +31 -0
  63. package/src/components/sheet/optical-sheet.tsx +143 -0
  64. package/src/components/sidebar/optical-sidebar.tsx +762 -0
  65. package/src/components/skeleton/optical-skeleton.tsx +15 -0
  66. package/src/components/slider/optical-slider.tsx +34 -0
  67. package/src/components/sonner/optical-toast.tsx +45 -0
  68. package/src/components/spinner/optical-spinner.tsx +16 -0
  69. package/src/components/stained-glass-card.tsx +93 -0
  70. package/src/components/switch/optical-switch.tsx +31 -0
  71. package/src/components/table/optical-table.tsx +83 -0
  72. package/src/components/tabs/optical-tabs.tsx +56 -0
  73. package/src/components/text/liquid-tension-text.tsx +65 -0
  74. package/src/components/text/optical-tension-text.tsx +65 -0
  75. package/src/components/text/optical-text.tsx +20 -0
  76. package/src/components/text/prismatic-selection.tsx +5 -0
  77. package/src/components/textarea/optical-textarea.tsx +22 -0
  78. package/src/components/theme-toggle/optical-theme-toggle.tsx +45 -0
  79. package/src/components/toast/optical-toast.tsx +25 -0
  80. package/src/components/toggle/optical-toggle.tsx +45 -0
  81. package/src/components/toggle-group/optical-toggle-group.tsx +61 -0
  82. package/src/components/tooltip/optical-tooltip.tsx +33 -0
  83. package/src/components/typography/optical-typography.tsx +49 -0
  84. package/src/hooks/use-mobile.ts +19 -0
  85. package/src/index.ts +88 -0
  86. package/src/templates/ContactPageTemplate.tsx +42 -0
  87. package/src/templates/LandingPageTemplate.tsx +29 -0
  88. package/src/templates/ProductPageTemplate.tsx +46 -0
  89. package/src/templates/styles.ts +23 -0
  90. package/src/utils/button-variants.ts +26 -0
  91. package/src/utils/cn.ts +6 -0
  92. package/tsconfig.json +27 -0
  93. 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
+