@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,15 @@
1
+ import { cn } from '../../utils/cn';
2
+
3
+ function Skeleton({
4
+ className,
5
+ ...props
6
+ }: React.HTMLAttributes<HTMLDivElement>) {
7
+ return (
8
+ <div
9
+ className={cn("animate-pulse rounded-md bg-white/10", className)}
10
+ {...props}
11
+ />
12
+ )
13
+ }
14
+
15
+ export { Skeleton }
@@ -0,0 +1,34 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as SliderPrimitive from "@radix-ui/react-slider"
5
+ import { useMrigSurface } from '@mrigx/react';
6
+ import { cn } from '../../utils/cn';
7
+
8
+ const Slider = React.forwardRef<
9
+ React.ElementRef<typeof SliderPrimitive.Root>,
10
+ React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
11
+ >(({ className, ...props }, forwardedRef) => {
12
+ const mrigRef = useMrigSurface<HTMLSpanElement>({ material: 'none', isDynamic: true }, forwardedRef as any);
13
+
14
+ return (
15
+ <SliderPrimitive.Root
16
+ ref={mrigRef as any}
17
+ className={cn(
18
+ "relative flex w-full touch-none select-none items-center group",
19
+ className
20
+ )}
21
+ {...props}
22
+ >
23
+ <SliderPrimitive.Track className="relative h-2 w-full grow overflow-hidden rounded-full bg-white/[0.05] border border-white/10 shadow-[inset_0_1px_3px_rgba(0,0,0,0.8)]">
24
+ <SliderPrimitive.Range className="absolute h-full bg-gradient-to-r from-white/10 to-white/40 shadow-[0_0_10px_rgba(255,255,255,0.2)]" />
25
+ </SliderPrimitive.Track>
26
+ <SliderPrimitive.Thumb className="block h-6 w-6 rounded-full border border-white/30 bg-black/40 backdrop-blur-xl shadow-[0_4px_12px_rgba(0,0,0,0.8),inset_0_1px_2px_rgba(255,255,255,0.4)] transition-all hover:bg-white/10 hover:border-white/50 hover:scale-110 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/20 focus-visible:ring-offset-2 focus-visible:ring-offset-black disabled:pointer-events-none disabled:opacity-50 cursor-grab active:cursor-grabbing active:scale-95 flex items-center justify-center">
27
+ <div className="w-2 h-2 rounded-full bg-white/50 shadow-[0_0_5px_rgba(255,255,255,0.5)] transition-all group-hover:bg-white" />
28
+ </SliderPrimitive.Thumb>
29
+ </SliderPrimitive.Root>
30
+ );
31
+ })
32
+ Slider.displayName = SliderPrimitive.Root.displayName
33
+
34
+ export { Slider }
@@ -0,0 +1,45 @@
1
+ "use client"
2
+
3
+ import {
4
+ CircleCheck,
5
+ Info,
6
+ LoaderCircle,
7
+ OctagonX,
8
+ TriangleAlert,
9
+ } from "lucide-react"
10
+ import { useTheme } from "next-themes"
11
+ import { Toaster as Sonner } from "sonner"
12
+
13
+ type ToasterProps = React.ComponentProps<typeof Sonner>
14
+
15
+ const Toaster = ({ ...props }: ToasterProps) => {
16
+ const { theme = "system" } = useTheme()
17
+
18
+ return (
19
+ <Sonner
20
+ theme={theme as ToasterProps["theme"]}
21
+ className="toaster group"
22
+ icons={{
23
+ success: <CircleCheck className="h-4 w-4" />,
24
+ info: <Info className="h-4 w-4" />,
25
+ warning: <TriangleAlert className="h-4 w-4" />,
26
+ error: <OctagonX className="h-4 w-4" />,
27
+ loading: <LoaderCircle className="h-4 w-4 animate-spin" />,
28
+ }}
29
+ toastOptions={{
30
+ classNames: {
31
+ toast:
32
+ "group toast group-[.toaster]:bg-transparent group-[.toaster]:text-white group-[.toaster]:border-white/10 group-[.toaster]:shadow-lg",
33
+ description: "group-[.toast]:text-white/50",
34
+ actionButton:
35
+ "group-[.toast]:bg-white/20 group-[.toast]:text-white",
36
+ cancelButton:
37
+ "group-[.toast]:bg-white/10 group-[.toast]:text-white/50",
38
+ },
39
+ }}
40
+ {...props}
41
+ />
42
+ )
43
+ }
44
+
45
+ export { Toaster }
@@ -0,0 +1,16 @@
1
+ import { Loader2Icon } from "lucide-react"
2
+
3
+ import { cn } from '../../utils/cn';
4
+
5
+ function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
6
+ return (
7
+ <Loader2Icon
8
+ role="status"
9
+ aria-label="Loading"
10
+ className={cn("size-4 animate-spin", className)}
11
+ {...props}
12
+ />
13
+ )
14
+ }
15
+
16
+ export { Spinner }
@@ -0,0 +1,93 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { useMrigSurface, useMrigInteraction } from '@mrigx/react';
3
+ import { type OpticalMaterial } from '@mrigx/core';
4
+
5
+ export interface StainedGlassCardProps extends React.HTMLAttributes<HTMLDivElement> {
6
+ material?: OpticalMaterial;
7
+ materialStrength?: number;
8
+ glowColor?: string;
9
+ }
10
+
11
+ export const StainedGlassCard = forwardRef<HTMLDivElement, StainedGlassCardProps>(({
12
+ children,
13
+ material = 'glass',
14
+ materialStrength = 1.0,
15
+ glowColor = "rgba(217, 70, 239, 0.3)", // fuchsia-500/30
16
+ className = "",
17
+ style,
18
+ onClick,
19
+ ...props
20
+ }, forwardedRef) => {
21
+ // We use useMrigSurface to create a thick optical refractive layer
22
+ const rootRef = useMrigSurface<HTMLDivElement>({
23
+ material,
24
+ materialStrength: 1.0,
25
+ borderRadius: 16
26
+ }, forwardedRef);
27
+
28
+ const { pulseCenter } = useMrigInteraction();
29
+
30
+ const containerStyle: React.CSSProperties = {
31
+ minHeight: '16rem',
32
+ width: '100%',
33
+ border: '1px solid rgba(255, 255, 255, 0.05)',
34
+ backgroundColor: 'rgba(255, 255, 255, 0.01)',
35
+ borderRadius: '1rem',
36
+ display: 'flex',
37
+ alignItems: 'center',
38
+ justifyContent: 'center',
39
+ position: 'relative',
40
+ overflow: 'hidden',
41
+ cursor: 'crosshair',
42
+ ...style
43
+ };
44
+
45
+ const glowStyle: React.CSSProperties = {
46
+ position: 'absolute',
47
+ width: '50%',
48
+ height: '50%',
49
+ borderRadius: '9999px',
50
+ filter: 'blur(40px)',
51
+ pointerEvents: 'none',
52
+ backgroundColor: glowColor,
53
+ zIndex: 0,
54
+ };
55
+
56
+ const innerStyle: React.CSSProperties = {
57
+ position: 'relative',
58
+ zIndex: 1,
59
+ width: '80%',
60
+ minHeight: '8rem',
61
+ padding: '2rem',
62
+ border: '1px solid rgba(255, 255, 255, 0.1)',
63
+ borderRadius: '0.75rem',
64
+ backgroundColor: 'rgba(255, 255, 255, 0.02)',
65
+ display: 'flex',
66
+ flexDirection: 'column',
67
+ alignItems: 'center',
68
+ justifyContent: 'center',
69
+ pointerEvents: 'none', // let clicks fall through to root
70
+ };
71
+
72
+ return (
73
+ <div
74
+ ref={rootRef}
75
+ style={containerStyle}
76
+ className={className}
77
+ onClick={(e) => {
78
+ pulseCenter(e.currentTarget, 0.3);
79
+ onClick?.(e);
80
+ }}
81
+ {...props}
82
+ >
83
+ <div style={glowStyle} />
84
+ <div style={innerStyle}>
85
+ {children}
86
+ </div>
87
+ </div>
88
+ );
89
+ });
90
+
91
+ StainedGlassCard.displayName = 'StainedGlassCard';
92
+
93
+
@@ -0,0 +1,31 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as SwitchPrimitives from "@radix-ui/react-switch"
5
+
6
+ import { cn } from '../../utils/cn';
7
+
8
+ const Switch = React.forwardRef<
9
+ React.ElementRef<typeof SwitchPrimitives.Root>,
10
+ React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
11
+ >(({ className, ...props }, ref) => (
12
+ <SwitchPrimitives.Root
13
+ className={cn(
14
+ "peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border border-white/10 transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/20 focus-visible:ring-offset-2 focus-visible:ring-offset-black disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-white/20 data-[state=unchecked]:bg-white/5 data-[state=checked]:shadow-[inset_0_1px_3px_rgba(255,255,255,0.2)] data-[state=unchecked]:shadow-[inset_0_1px_3px_rgba(0,0,0,0.8)]",
15
+ className
16
+ )}
17
+ {...props}
18
+ ref={ref}
19
+ >
20
+ <SwitchPrimitives.Thumb
21
+ className={cn(
22
+ "pointer-events-none block h-5 w-5 rounded-full border border-white/30 bg-black/40 backdrop-blur-xl shadow-[0_4px_12px_rgba(0,0,0,0.8),inset_0_1px_2px_rgba(255,255,255,0.4)] ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0 flex items-center justify-center"
23
+ )}
24
+ >
25
+ <div className="w-1.5 h-1.5 rounded-full bg-white/50 transition-colors" />
26
+ </SwitchPrimitives.Thumb>
27
+ </SwitchPrimitives.Root>
28
+ ))
29
+ Switch.displayName = SwitchPrimitives.Root.displayName
30
+
31
+ export { Switch }
@@ -0,0 +1,83 @@
1
+ import * as React from "react"
2
+ import { GlassSurface } from '@mrigx/fx';
3
+
4
+ const OpticalTable = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(({ className = "", ...props }, ref) => (
5
+ <div className="relative w-full overflow-auto">
6
+ <table
7
+ ref={ref}
8
+ className={`w-full caption-bottom text-sm ${className}`}
9
+ {...props}
10
+ />
11
+ </div>
12
+ ))
13
+ OpticalTable.displayName = "OpticalTable"
14
+
15
+ const OpticalTableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(({ className = "", ...props }, ref) => (
16
+ <thead ref={ref} className={`[&_tr]:border-b border-white/10 ${className}`} {...props} />
17
+ ))
18
+ OpticalTableHeader.displayName = "OpticalTableHeader"
19
+
20
+ const OpticalTableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(({ className = "", ...props }, ref) => (
21
+ <tbody
22
+ ref={ref}
23
+ className={`[&_tr:last-child]:border-0 ${className}`}
24
+ {...props}
25
+ />
26
+ ))
27
+ OpticalTableBody.displayName = "OpticalTableBody"
28
+
29
+ const OpticalTableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(({ className = "", ...props }, ref) => (
30
+ <tfoot
31
+ ref={ref}
32
+ className={`border-t border-white/10 bg-white/[0.02] font-medium text-white/80 ${className}`}
33
+ {...props}
34
+ />
35
+ ))
36
+ OpticalTableFooter.displayName = "OpticalTableFooter"
37
+
38
+ const OpticalTableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(({ className = "", ...props }, ref) => (
39
+ <tr
40
+ ref={ref}
41
+ className={`border-b border-white/5 transition-colors hover:bg-white/[0.02] data-[state=selected]:bg-white/[0.05] ${className}`}
42
+ {...props}
43
+ />
44
+ ))
45
+ OpticalTableRow.displayName = "OpticalTableRow"
46
+
47
+ const OpticalTableHead = React.forwardRef<HTMLTableCellElement, React.ThHTMLAttributes<HTMLTableCellElement>>(({ className = "", ...props }, ref) => (
48
+ <th
49
+ ref={ref}
50
+ className={`h-12 px-4 text-left align-middle font-light text-white/50 [&:has([role=checkbox])]:pr-0 ${className}`}
51
+ {...props}
52
+ />
53
+ ))
54
+ OpticalTableHead.displayName = "OpticalTableHead"
55
+
56
+ const OpticalTableCell = React.forwardRef<HTMLTableCellElement, React.TdHTMLAttributes<HTMLTableCellElement>>(({ className = "", ...props }, ref) => (
57
+ <td
58
+ ref={ref}
59
+ className={`p-4 align-middle text-white/80 font-light [&:has([role=checkbox])]:pr-0 ${className}`}
60
+ {...props}
61
+ />
62
+ ))
63
+ OpticalTableCell.displayName = "OpticalTableCell"
64
+
65
+ const OpticalTableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>(({ className = "", ...props }, ref) => (
66
+ <caption
67
+ ref={ref}
68
+ className={`mt-4 text-sm text-white/50 ${className}`}
69
+ {...props}
70
+ />
71
+ ))
72
+ OpticalTableCaption.displayName = "OpticalTableCaption"
73
+
74
+ export {
75
+ OpticalTable,
76
+ OpticalTableHeader,
77
+ OpticalTableBody,
78
+ OpticalTableFooter,
79
+ OpticalTableHead,
80
+ OpticalTableRow,
81
+ OpticalTableCell,
82
+ OpticalTableCaption,
83
+ }
@@ -0,0 +1,56 @@
1
+ import * as React from "react"
2
+ import * as TabsPrimitive from "@radix-ui/react-tabs"
3
+ import { cn } from '../../utils/cn';
4
+ import { RippleSurface, GlassSurface } from '@mrigx/fx';
5
+
6
+ const OpticalTabs = TabsPrimitive.Root
7
+
8
+ const OpticalTabsList = React.forwardRef<
9
+ React.ElementRef<typeof TabsPrimitive.List>,
10
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.List> & { material?: string; materialStrength?: number }
11
+ >(({ className, material = "glass", materialStrength = 0.5, ...props }, ref) => (
12
+ <TabsPrimitive.List
13
+ ref={ref}
14
+ className={cn(
15
+ "inline-flex h-10 items-center justify-center rounded-lg p-1 text-white/50 relative",
16
+ className
17
+ )}
18
+ {...props}
19
+ >
20
+ <GlassSurface material={material} materialStrength={materialStrength} borderRadius={8} className="absolute inset-0 -z-10 border border-white/5" />
21
+ {props.children}
22
+ </TabsPrimitive.List>
23
+ ))
24
+ OpticalTabsList.displayName = TabsPrimitive.List.displayName
25
+
26
+ const OpticalTabsTrigger = React.forwardRef<
27
+ React.ElementRef<typeof TabsPrimitive.Trigger>,
28
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
29
+ >(({ className, ...props }, ref) => (
30
+ <TabsPrimitive.Trigger
31
+ ref={ref}
32
+ className={cn(
33
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-white/10 data-[state=active]:text-white data-[state=active]:shadow-sm cursor-pointer",
34
+ className
35
+ )}
36
+ {...props}
37
+ />
38
+ ))
39
+ OpticalTabsTrigger.displayName = TabsPrimitive.Trigger.displayName
40
+
41
+ const OpticalTabsContent = React.forwardRef<
42
+ React.ElementRef<typeof TabsPrimitive.Content>,
43
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
44
+ >(({ className, ...props }, ref) => (
45
+ <TabsPrimitive.Content
46
+ ref={ref}
47
+ className={cn(
48
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
49
+ className
50
+ )}
51
+ {...props}
52
+ />
53
+ ))
54
+ OpticalTabsContent.displayName = TabsPrimitive.Content.displayName
55
+
56
+ export { OpticalTabs, OpticalTabsList, OpticalTabsTrigger, OpticalTabsContent }
@@ -0,0 +1,65 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+
3
+ export function LiquidTensionText({ children, className = "", distance = 100, strength = 15, as: Component = "span" }: any) {
4
+ const ref = useRef<HTMLElement>(null);
5
+
6
+ useEffect(() => {
7
+ const el = ref.current;
8
+ if (!el) return;
9
+
10
+ let rect = el.getBoundingClientRect();
11
+ let centerX = rect.left + rect.width / 2;
12
+ let centerY = rect.top + rect.height / 2;
13
+ let isActive = false;
14
+ let rafId = 0;
15
+ let mouseX = 0;
16
+ let mouseY = 0;
17
+
18
+ const updateTransform = () => {
19
+ if (!isActive) return;
20
+ const distX = mouseX - centerX;
21
+ const distY = mouseY - centerY;
22
+ const dist = Math.sqrt(distX * distX + distY * distY);
23
+
24
+ if (dist < distance) {
25
+ const pull = (distance - dist) / strength;
26
+ el.style.transform = `translate(${distX > 0 ? pull : -pull}px, ${distY > 0 ? pull : -pull}px)`;
27
+ } else {
28
+ el.style.transform = 'translate(0px, 0px)';
29
+ }
30
+ rafId = 0;
31
+ };
32
+
33
+ const handleMove = (e: MouseEvent) => {
34
+ mouseX = e.clientX;
35
+ mouseY = e.clientY;
36
+ if (isActive && !rafId) rafId = requestAnimationFrame(updateTransform);
37
+ };
38
+
39
+ const handleEnter = () => {
40
+ isActive = true;
41
+ rect = el.getBoundingClientRect();
42
+ centerX = rect.left + rect.width / 2;
43
+ centerY = rect.top + rect.height / 2;
44
+ };
45
+
46
+ const handleLeave = () => {
47
+ isActive = false;
48
+ el.style.transform = 'translate(0px, 0px)';
49
+ if (rafId) { cancelAnimationFrame(rafId); rafId = 0; }
50
+ };
51
+
52
+ el.addEventListener('mouseenter', handleEnter);
53
+ el.addEventListener('mouseleave', handleLeave);
54
+ window.addEventListener('mousemove', handleMove, { passive: true });
55
+
56
+ return () => {
57
+ el.removeEventListener('mouseenter', handleEnter);
58
+ el.removeEventListener('mouseleave', handleLeave);
59
+ window.removeEventListener('mousemove', handleMove);
60
+ if (rafId) cancelAnimationFrame(rafId);
61
+ };
62
+ }, [distance, strength]);
63
+
64
+ return <Component ref={ref} className={`inline-block transition-transform duration-75 ease-out ${className}`}>{children}</Component>;
65
+ }
@@ -0,0 +1,65 @@
1
+ import { useEffect, useRef } from 'react';
2
+
3
+ export function LiquidTensionText({ children, className = "", distance = 100, strength = 15, as: Component = "span" }: any) {
4
+ const ref = useRef<HTMLElement>(null);
5
+
6
+ useEffect(() => {
7
+ const el = ref.current;
8
+ if (!el) return;
9
+
10
+ let rect = el.getBoundingClientRect();
11
+ let centerX = rect.left + rect.width / 2;
12
+ let centerY = rect.top + rect.height / 2;
13
+ let isActive = false;
14
+ let rafId = 0;
15
+ let mouseX = 0;
16
+ let mouseY = 0;
17
+
18
+ const updateTransform = () => {
19
+ if (!isActive) return;
20
+ const distX = mouseX - centerX;
21
+ const distY = mouseY - centerY;
22
+ const dist = Math.sqrt(distX * distX + distY * distY);
23
+
24
+ if (dist < distance) {
25
+ const pull = (distance - dist) / strength;
26
+ el.style.transform = `translate(${distX > 0 ? pull : -pull}px, ${distY > 0 ? pull : -pull}px)`;
27
+ } else {
28
+ el.style.transform = 'translate(0px, 0px)';
29
+ }
30
+ rafId = 0;
31
+ };
32
+
33
+ const handleMove = (e: MouseEvent) => {
34
+ mouseX = e.clientX;
35
+ mouseY = e.clientY;
36
+ if (isActive && !rafId) rafId = requestAnimationFrame(updateTransform);
37
+ };
38
+
39
+ const handleEnter = () => {
40
+ isActive = true;
41
+ rect = el.getBoundingClientRect();
42
+ centerX = rect.left + rect.width / 2;
43
+ centerY = rect.top + rect.height / 2;
44
+ };
45
+
46
+ const handleLeave = () => {
47
+ isActive = false;
48
+ el.style.transform = 'translate(0px, 0px)';
49
+ if (rafId) { cancelAnimationFrame(rafId); rafId = 0; }
50
+ };
51
+
52
+ el.addEventListener('mouseenter', handleEnter);
53
+ el.addEventListener('mouseleave', handleLeave);
54
+ window.addEventListener('mousemove', handleMove, { passive: true });
55
+
56
+ return () => {
57
+ el.removeEventListener('mouseenter', handleEnter);
58
+ el.removeEventListener('mouseleave', handleLeave);
59
+ window.removeEventListener('mousemove', handleMove);
60
+ if (rafId) cancelAnimationFrame(rafId);
61
+ };
62
+ }, [distance, strength]);
63
+
64
+ return <Component ref={ref} className={`inline-block transition-transform duration-75 ease-out ${className}`}>{children}</Component>;
65
+ }
@@ -0,0 +1,20 @@
1
+
2
+ import React, { forwardRef } from 'react';
3
+ import { useMrigSurface, useMrigInteraction } from '@mrigx/react';
4
+ export const OpticalText = forwardRef<any, any>(({ children, className = "", as = "span", ...props }, forwardedRef) => {
5
+ const Component = as;
6
+ const internalRef = useMrigSurface({ material: 'soft-glass', materialStrength: 0.5, borderRadius: 4 }, forwardedRef);
7
+ const { pulseCenter } = useMrigInteraction();
8
+
9
+ return (
10
+ <Component
11
+ ref={internalRef as any}
12
+ className={`inline-block px-1 rounded bg-white/5 ${className}`}
13
+ onMouseEnter={(e: any) => pulseCenter(e.currentTarget, 0.2)}
14
+ {...props}
15
+ >
16
+ {children}
17
+ </Component>
18
+ );
19
+ });
20
+ OpticalText.displayName = "OpticalText";
@@ -0,0 +1,5 @@
1
+ export function PrismaticSelection() {
2
+ // Logic migrated directly into MrigEngine's native event loop.
3
+ // Component kept for backward compatibility in the API.
4
+ return null;
5
+ }
@@ -0,0 +1,22 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from '../../utils/cn';
4
+
5
+ const Textarea = React.forwardRef<
6
+ HTMLTextAreaElement,
7
+ React.ComponentProps<"textarea">
8
+ >(({ className, ...props }, ref) => {
9
+ return (
10
+ <textarea
11
+ className={cn(
12
+ "flex min-h-[80px] w-full rounded-md border border-white/10 bg-transparent px-3 py-2 text-base ring-offset-black placeholder:text-white/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
13
+ className
14
+ )}
15
+ ref={ref}
16
+ {...props}
17
+ />
18
+ )
19
+ })
20
+ Textarea.displayName = "Textarea"
21
+
22
+ export { Textarea }
@@ -0,0 +1,45 @@
1
+ import React, { useState } from 'react';
2
+ import { useMrigSurface } from '@mrigx/react';
3
+
4
+ const THEMES = ['default', 'theme-cyan', 'theme-magenta', 'theme-toxic', 'theme-amber', 'theme-electric', 'theme-laser', 'theme-hotpink', 'theme-crimson'];
5
+ const THEME_COLORS = ['#ffffff', '#00ffcc', '#ff00cc', '#39ff14', '#ffb000', '#0077ff', '#ffff00', '#ff1493', '#ff0033'];
6
+
7
+ export function OpticalThemeToggle() {
8
+ const [themeIdx, setThemeIdx] = useState(0);
9
+ // Add an internal dynamic surface for the toggle itself so its glow updates cleanly
10
+ const toggleRef = useMrigSurface<HTMLButtonElement>({ isDynamic: true });
11
+
12
+ const toggleTheme = (e: React.MouseEvent) => {
13
+ e.preventDefault();
14
+ e.stopPropagation();
15
+ const nextIdx = (themeIdx + 1) % THEMES.length;
16
+ setThemeIdx(nextIdx);
17
+
18
+ THEMES.forEach(t => {
19
+ if (t !== 'default') document.documentElement.classList.remove(t); document.getElementById("mrig-app-root")?.classList.remove(t);
20
+ });
21
+
22
+ const nextTheme = THEMES[nextIdx];
23
+ if (nextTheme !== 'default') {
24
+ document.documentElement.classList.add(nextTheme); document.getElementById("mrig-app-root")?.classList.add(nextTheme);
25
+ }
26
+
27
+ // Force the optical engine to re-rasterize the entire DOM to capture the new colors
28
+ setTimeout(() => {
29
+ window.dispatchEvent(new Event('resize'));
30
+ }, 10);
31
+ };
32
+
33
+ return (
34
+ <button
35
+ ref={toggleRef}
36
+ onClick={(e) => toggleTheme(e)}
37
+ className="p-3 rounded-full border border-white/20 bg-white/5 hover:bg-white/20 transition-all cursor-pointer flex items-center justify-center text-white pointer-events-auto shadow-2xl hover:scale-110"
38
+ style={{ boxShadow: `0 0 15px ${THEME_COLORS[themeIdx]}50` }}
39
+ aria-label="Toggle Glass Theme"
40
+ >
41
+ <div className="w-5 h-5 rounded-full shadow-inner border border-black/30" style={{ backgroundColor: THEME_COLORS[themeIdx] }} />
42
+ </button>
43
+ );
44
+ }
45
+
@@ -0,0 +1,25 @@
1
+ import React, { useRef } from 'react';
2
+ import { useMrigSurface } from "@mrigx/react";
3
+
4
+ export interface OpticalToastProps extends React.HTMLAttributes<HTMLDivElement> {
5
+ material?: 'glass' | 'crystal' | 'abyss';
6
+ materialStrength?: number;
7
+ }
8
+
9
+ export function OpticalToast({ children, className = "", material = 'glass', materialStrength = 1.0, ...props }: OpticalToastProps) {
10
+ const localRef = useRef<HTMLDivElement>(null);
11
+ const ref = useMrigSurface<HTMLDivElement>({ material, materialStrength, borderRadius: 8 }, localRef);
12
+
13
+ return (
14
+ <div
15
+ ref={ref as any}
16
+ className={`p-6 border border-white/10 bg-white/5 rounded-xl shadow-lg backdrop-blur-md flex items-center justify-center text-white/80 font-light ${className}`}
17
+ {...props}
18
+ >
19
+ {children || 'Toast Interface'}
20
+ </div>
21
+ );
22
+ }
23
+
24
+
25
+