@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,45 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as TogglePrimitive from "@radix-ui/react-toggle"
5
+ import { cva, type VariantProps } from "class-variance-authority"
6
+
7
+ import { cn } from '../../utils/cn';
8
+
9
+ const toggleVariants = cva(
10
+ "inline-flex items-center justify-center rounded-md text-sm font-medium transition-all hover:bg-white/10 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/20 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-white/20 data-[state=on]:text-white data-[state=on]:shadow-[inset_0_1px_2px_rgba(255,255,255,0.2)] [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 gap-2",
11
+ {
12
+ variants: {
13
+ variant: {
14
+ default: "bg-transparent text-white/60",
15
+ outline:
16
+ "border border-white/10 bg-white/[0.02] text-white/60 hover:bg-white/10 shadow-sm",
17
+ },
18
+ size: {
19
+ default: "h-10 px-3 min-w-10",
20
+ sm: "h-9 px-2.5 min-w-9",
21
+ lg: "h-11 px-5 min-w-11",
22
+ },
23
+ },
24
+ defaultVariants: {
25
+ variant: "default",
26
+ size: "default",
27
+ },
28
+ }
29
+ )
30
+
31
+ const Toggle = React.forwardRef<
32
+ React.ElementRef<typeof TogglePrimitive.Root>,
33
+ React.ComponentPropsWithoutRef<typeof TogglePrimitive.Root> &
34
+ VariantProps<typeof toggleVariants>
35
+ >(({ className, variant, size, ...props }, ref) => (
36
+ <TogglePrimitive.Root
37
+ ref={ref}
38
+ className={cn(toggleVariants({ variant, size, className }))}
39
+ {...props}
40
+ />
41
+ ))
42
+
43
+ Toggle.displayName = TogglePrimitive.Root.displayName
44
+
45
+ export { Toggle, toggleVariants }
@@ -0,0 +1,61 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"
5
+ import { type VariantProps } from "class-variance-authority"
6
+
7
+ import { cn } from '../../utils/cn';
8
+ import { toggleVariants } from '../toggle/optical-toggle';
9
+
10
+ const ToggleGroupContext = React.createContext<
11
+ VariantProps<typeof toggleVariants>
12
+ >({
13
+ size: "default",
14
+ variant: "default",
15
+ })
16
+
17
+ const ToggleGroup = React.forwardRef<
18
+ React.ElementRef<typeof ToggleGroupPrimitive.Root>,
19
+ React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Root> &
20
+ VariantProps<typeof toggleVariants>
21
+ >(({ className, variant, size, children, ...props }, ref) => (
22
+ <ToggleGroupPrimitive.Root
23
+ ref={ref}
24
+ className={cn("flex items-center justify-center gap-1", className)}
25
+ {...props}
26
+ >
27
+ <ToggleGroupContext.Provider value={{ variant, size }}>
28
+ {children}
29
+ </ToggleGroupContext.Provider>
30
+ </ToggleGroupPrimitive.Root>
31
+ ))
32
+
33
+ ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName
34
+
35
+ const ToggleGroupItem = React.forwardRef<
36
+ React.ElementRef<typeof ToggleGroupPrimitive.Item>,
37
+ React.ComponentPropsWithoutRef<typeof ToggleGroupPrimitive.Item> &
38
+ VariantProps<typeof toggleVariants>
39
+ >(({ className, children, variant, size, ...props }, ref) => {
40
+ const context = React.useContext(ToggleGroupContext)
41
+
42
+ return (
43
+ <ToggleGroupPrimitive.Item
44
+ ref={ref}
45
+ className={cn(
46
+ toggleVariants({
47
+ variant: context.variant || variant,
48
+ size: context.size || size,
49
+ }),
50
+ className
51
+ )}
52
+ {...props}
53
+ >
54
+ {children}
55
+ </ToggleGroupPrimitive.Item>
56
+ )
57
+ })
58
+
59
+ ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName
60
+
61
+ export { ToggleGroup, ToggleGroupItem }
@@ -0,0 +1,33 @@
1
+ import * as React from "react"
2
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip"
3
+ import { cn } from '../../utils/cn';
4
+ import { GlassSurface } from '@mrigx/fx';
5
+
6
+ const OpticalTooltipProvider = TooltipPrimitive.Provider
7
+
8
+ const OpticalTooltip = TooltipPrimitive.Root
9
+
10
+ const OpticalTooltipTrigger = TooltipPrimitive.Trigger
11
+
12
+ const OpticalTooltipContent = React.forwardRef<
13
+ React.ElementRef<typeof TooltipPrimitive.Content>,
14
+ React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> & { material?: string; materialStrength?: number }
15
+ >(({ className, sideOffset = 4, material = "crystal", materialStrength = 0.5, ...props }, ref) => (
16
+ <TooltipPrimitive.Portal>
17
+ <TooltipPrimitive.Content
18
+ ref={ref}
19
+ sideOffset={sideOffset}
20
+ className={cn(
21
+ "z-50 overflow-hidden rounded-md border border-white/10 px-3 py-1.5 text-xs text-white shadow-2xl animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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",
22
+ className
23
+ )}
24
+ {...props}
25
+ >
26
+ <GlassSurface material={material} materialStrength={materialStrength} borderRadius={6} className="absolute inset-0 -z-10" />
27
+ {props.children}
28
+ </TooltipPrimitive.Content>
29
+ </TooltipPrimitive.Portal>
30
+ ))
31
+ OpticalTooltipContent.displayName = TooltipPrimitive.Content.displayName
32
+
33
+ export { OpticalTooltip, OpticalTooltipTrigger, OpticalTooltipContent, OpticalTooltipProvider }
@@ -0,0 +1,49 @@
1
+ import { forwardRef } from 'react';
2
+ import type { ElementType, HTMLAttributes, ReactNode } from 'react';
3
+
4
+ // Typography System
5
+ // Defines the strict optical hierarchy for the framework.
6
+
7
+ interface TextProps extends HTMLAttributes<HTMLElement> {
8
+ as?: ElementType;
9
+ children: ReactNode;
10
+ className?: string;
11
+ }
12
+
13
+ export const Text = {
14
+ Display: forwardRef<HTMLElement, TextProps>(({ as: Component = 'h1', className = "", children, ...props }, ref) => (
15
+ <Component ref={ref as any} className={`text-[3.5rem] md:text-[6.5rem] leading-[1.0] font-light tracking-tighter text-white/95 ${className}`} {...props}>
16
+ {children}
17
+ </Component>
18
+ )),
19
+
20
+ Heading: forwardRef<HTMLElement, TextProps>(({ as: Component = 'h2', className = "", children, ...props }, ref) => (
21
+ <Component ref={ref as any} className={`text-[2rem] md:text-[3.5rem] leading-[1.1] font-light tracking-tight text-white/90 ${className}`} {...props}>
22
+ {children}
23
+ </Component>
24
+ )),
25
+
26
+ Title: forwardRef<HTMLElement, TextProps>(({ as: Component = 'h3', className = "", children, ...props }, ref) => (
27
+ <Component ref={ref as any} className={`text-xl md:text-3xl leading-snug font-light tracking-tight text-white/80 ${className}`} {...props}>
28
+ {children}
29
+ </Component>
30
+ )),
31
+
32
+ Body: forwardRef<HTMLElement, TextProps>(({ as: Component = 'p', className = "", children, ...props }, ref) => (
33
+ <Component ref={ref as any} className={`text-lg md:text-xl font-normal leading-relaxed text-white/60 ${className}`} {...props}>
34
+ {children}
35
+ </Component>
36
+ )),
37
+
38
+ Metadata: forwardRef<HTMLElement, TextProps>(({ as: Component = 'span', className = "", children, ...props }, ref) => (
39
+ <Component ref={ref as any} className={`text-[10px] md:text-xs font-semibold uppercase tracking-[0.25em] text-white/40 ${className}`} {...props}>
40
+ {children}
41
+ </Component>
42
+ )),
43
+ };
44
+
45
+ Text.Display.displayName = "Text.Display";
46
+ Text.Heading.displayName = "Text.Heading";
47
+ Text.Title.displayName = "Text.Title";
48
+ Text.Body.displayName = "Text.Body";
49
+ Text.Metadata.displayName = "Text.Metadata";
@@ -0,0 +1,19 @@
1
+ import * as React from "react"
2
+
3
+ const MOBILE_BREAKPOINT = 768
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
+ }
13
+ mql.addEventListener("change", onChange)
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
+ return () => mql.removeEventListener("change", onChange)
16
+ }, [])
17
+
18
+ return !!isMobile
19
+ }
package/src/index.ts ADDED
@@ -0,0 +1,88 @@
1
+ export * from './blocks/ContactPanel';
2
+ export * from './blocks/FeatureGrid';
3
+ export * from './blocks/OpticalCTA';
4
+ export * from './blocks/OpticalHero';
5
+ export * from './blocks/styles';
6
+ export * from './components/ambient-light';
7
+ export * from './components/glass-card';
8
+ export * from './components/prism-button';
9
+ export * from './components/stained-glass-card';
10
+ export * from './components/accordion/optical-accordion';
11
+ export * from './components/alert/optical-alert';
12
+ export * from './components/alert-dialog/optical-alert-dialog';
13
+ export * from './components/aspect-ratio/optical-aspect-ratio';
14
+ export * from './components/attachment/optical-attachment';
15
+ export * from './components/avatar/optical-avatar';
16
+ export * from './components/badge/optical-badge';
17
+ export * from './components/breadcrumb/optical-breadcrumb';
18
+ export * from './components/bubble/optical-bubble';
19
+ export * from './components/button/optical-button';
20
+ export * from './components/button-group/optical-button-group';
21
+ export * from './components/calendar/optical-calendar';
22
+ export * from './components/card/optical-card';
23
+ export * from './components/carousel/optical-carousel';
24
+ export * from './components/chart/optical-chart';
25
+ export * from './components/checkbox/optical-checkbox';
26
+ export * from './components/collapsible/optical-collapsible';
27
+ export * from './components/combobox/optical-combobox';
28
+ export * from './components/command/optical-command';
29
+ export * from './components/context-menu/optical-context-menu';
30
+ export * from './components/cursor/optical-cursor';
31
+ export * from './components/data-table/optical-data-table';
32
+ export * from './components/date-picker/optical-date-picker';
33
+ export * from './components/dialog/optical-dialog';
34
+ export * from './components/direction/optical-direction';
35
+ export * from './components/drawer/optical-drawer';
36
+ export * from './components/dropdown-menu/optical-dropdown-menu';
37
+ export * from './components/empty/optical-empty';
38
+ export * from './components/field/optical-field';
39
+ export * from './components/hover-card/optical-hover-card';
40
+ export * from './components/icon-button/optical-icon-button';
41
+ export * from './components/input/optical-input';
42
+ export * from './components/input-group/optical-input-group';
43
+ export * from './components/input-otp/optical-input-otp';
44
+ export * from './components/item/optical-item';
45
+ export * from './components/kbd/optical-kbd';
46
+ export * from './components/label/optical-label';
47
+ export * from './components/marker/optical-marker';
48
+ export * from './components/menubar/optical-menubar';
49
+ export * from './components/message/optical-message';
50
+ export * from './components/message-scroller/optical-message-scroller';
51
+ export * from './components/native-select/optical-native-select';
52
+ export * from './components/navigation-menu/optical-navigation-menu';
53
+ export * from './components/pagination/optical-pagination';
54
+ export * from './components/panel/optical-panel';
55
+ export * from './components/popover/optical-popover';
56
+ export * from './components/progress/optical-progress';
57
+ export * from './components/questionnaire/optical-questionnaire';
58
+ export * from './components/radio-group/optical-radio-group';
59
+ export * from './components/resizable/optical-resizable';
60
+ export * from './components/scroll-area/optical-scroll-area';
61
+ export * from './components/select/optical-select';
62
+ export * from './components/separator/optical-separator';
63
+ export * from './components/sheet/optical-sheet';
64
+ export * from './components/sidebar/optical-sidebar';
65
+ export * from './components/skeleton/optical-skeleton';
66
+ export * from './components/slider/optical-slider';
67
+ export * from './components/sonner/optical-toast';
68
+ export * from './components/spinner/optical-spinner';
69
+ export * from './components/switch/optical-switch';
70
+ export * from './components/table/optical-table';
71
+ export * from './components/tabs/optical-tabs';
72
+ export * from './components/text/liquid-tension-text';
73
+ export * from './components/text/optical-tension-text';
74
+ export * from './components/text/optical-text';
75
+ export * from './components/text/prismatic-selection';
76
+ export * from './components/textarea/optical-textarea';
77
+ export * from './components/theme-toggle/optical-theme-toggle';
78
+ export * from './components/toast/optical-toast';
79
+ export * from './components/toggle/optical-toggle';
80
+ export * from './components/toggle-group/optical-toggle-group';
81
+ export * from './components/tooltip/optical-tooltip';
82
+ export * from './components/typography/optical-typography';
83
+ export * from './templates/ContactPageTemplate';
84
+ export * from './templates/LandingPageTemplate';
85
+ export * from './templates/ProductPageTemplate';
86
+ export * from './templates/styles';
87
+ export * from './utils/button-variants';
88
+ export * from './utils/cn';
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { injectMrigTemplateStyles } from './styles';
3
+ import { OpticalHero } from '../blocks/OpticalHero';
4
+ import { ContactPanel, type ContactData } from '../blocks/ContactPanel';
5
+ import { OpticalCTA, type OpticalCTAProps } from '../blocks/OpticalCTA';
6
+
7
+ export interface ContactPageTemplateProps extends React.HTMLAttributes<HTMLDivElement> {
8
+ hero: {
9
+ title: React.ReactNode;
10
+ description?: React.ReactNode;
11
+ };
12
+ contactForm: {
13
+ title?: string;
14
+ description?: string;
15
+ isSubmitting?: boolean;
16
+ onSubmit: (data: ContactData) => void;
17
+ };
18
+ cta?: Omit<OpticalCTAProps, 'className' | 'style'>;
19
+ }
20
+
21
+ export function ContactPageTemplate({
22
+ hero,
23
+ contactForm,
24
+ cta,
25
+ className = "",
26
+ ...props
27
+ }: ContactPageTemplateProps) {
28
+ injectMrigTemplateStyles();
29
+
30
+ return (
31
+ <div className={`mrig-template ${className}`} {...props}>
32
+ <OpticalHero
33
+ title={hero.title}
34
+ description={hero.description}
35
+ />
36
+ <div style={{ display: 'flex', justifyContent: 'center', width: '100%', padding: '0 1.5rem' }}>
37
+ <ContactPanel {...contactForm} style={{ width: '100%' }} />
38
+ </div>
39
+ {cta && <OpticalCTA {...cta} />}
40
+ </div>
41
+ );
42
+ }
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import { injectMrigTemplateStyles } from './styles';
3
+ import { OpticalHero, type OpticalHeroProps } from '../blocks/OpticalHero';
4
+ import { FeatureGrid, type FeatureItem } from '../blocks/FeatureGrid';
5
+ import { OpticalCTA, type OpticalCTAProps } from '../blocks/OpticalCTA';
6
+
7
+ export interface LandingPageTemplateProps extends React.HTMLAttributes<HTMLDivElement> {
8
+ hero: Omit<OpticalHeroProps, 'className' | 'style'>;
9
+ features: FeatureItem[];
10
+ cta: Omit<OpticalCTAProps, 'className' | 'style'>;
11
+ }
12
+
13
+ export function LandingPageTemplate({
14
+ hero,
15
+ features,
16
+ cta,
17
+ className = "",
18
+ ...props
19
+ }: LandingPageTemplateProps) {
20
+ injectMrigTemplateStyles();
21
+
22
+ return (
23
+ <div className={`mrig-template ${className}`} {...props}>
24
+ <OpticalHero {...hero} />
25
+ {features && features.length > 0 && <FeatureGrid features={features} />}
26
+ <OpticalCTA {...cta} />
27
+ </div>
28
+ );
29
+ }
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { injectMrigTemplateStyles } from './styles';
3
+ import { OpticalHero } from '../blocks/OpticalHero';
4
+ import { FeatureGrid, type FeatureItem } from '../blocks/FeatureGrid';
5
+ import { OpticalCTA, type OpticalCTAProps } from '../blocks/OpticalCTA';
6
+
7
+ export interface ProductPageTemplateProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
8
+ productName: string;
9
+ title: React.ReactNode;
10
+ description: React.ReactNode;
11
+ visual?: React.ReactNode;
12
+ primaryAction?: React.ReactNode;
13
+ secondaryAction?: React.ReactNode;
14
+ features: FeatureItem[];
15
+ cta: Omit<OpticalCTAProps, 'className' | 'style'>;
16
+ }
17
+
18
+ export function ProductPageTemplate({
19
+ productName,
20
+ title,
21
+ description,
22
+ visual,
23
+ primaryAction,
24
+ secondaryAction,
25
+ features,
26
+ cta,
27
+ className = "",
28
+ ...props
29
+ }: ProductPageTemplateProps) {
30
+ injectMrigTemplateStyles();
31
+
32
+ return (
33
+ <div className={`mrig-template ${className}`} {...props}>
34
+ <OpticalHero
35
+ eyebrow={productName}
36
+ title={title}
37
+ description={description}
38
+ visualArea={visual}
39
+ primaryAction={primaryAction}
40
+ secondaryAction={secondaryAction}
41
+ />
42
+ {features && features.length > 0 && <FeatureGrid features={features} />}
43
+ <OpticalCTA {...cta} />
44
+ </div>
45
+ );
46
+ }
@@ -0,0 +1,23 @@
1
+ const TEMPLATE_STYLES = `
2
+ .mrig-template {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: 4rem;
6
+ width: 100%;
7
+ }
8
+ @media (min-width: 768px) {
9
+ .mrig-template {
10
+ gap: 8rem;
11
+ }
12
+ }
13
+ `;
14
+
15
+ let injected = false;
16
+ export function injectMrigTemplateStyles() {
17
+ if (typeof window === 'undefined' || injected) return;
18
+ const style = document.createElement('style');
19
+ style.id = 'mrig-template-styles';
20
+ style.innerHTML = TEMPLATE_STYLES;
21
+ document.head.appendChild(style);
22
+ injected = true;
23
+ }
@@ -0,0 +1,26 @@
1
+ import { cva } from 'class-variance-authority';
2
+ export const buttonVariants = cva(
3
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
4
+ {
5
+ variants: {
6
+ variant: {
7
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
8
+ destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
9
+ outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
10
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
11
+ ghost: "hover:bg-accent hover:text-accent-foreground",
12
+ link: "text-primary underline-offset-4 hover:underline",
13
+ },
14
+ size: {
15
+ default: "h-10 px-4 py-2",
16
+ sm: "h-9 rounded-md px-3",
17
+ lg: "h-11 rounded-md px-8",
18
+ icon: "h-10 w-10",
19
+ },
20
+ },
21
+ defaultVariants: {
22
+ variant: "default",
23
+ size: "default",
24
+ },
25
+ }
26
+ )
@@ -0,0 +1,6 @@
1
+ import { type ClassValue, clsx } from "clsx"
2
+ import { twMerge } from "tailwind-merge"
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": [
6
+ "ES2020",
7
+ "DOM",
8
+ "DOM.Iterable"
9
+ ],
10
+ "module": "ESNext",
11
+ "skipLibCheck": true,
12
+ "moduleResolution": "bundler",
13
+ "allowImportingTsExtensions": true,
14
+ "resolveJsonModule": true,
15
+ "isolatedModules": true,
16
+ "noEmit": true,
17
+ "jsx": "react-jsx",
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "noFallthroughCasesInSwitch": true,
22
+ "baseUrl": "."
23
+ },
24
+ "include": [
25
+ "src"
26
+ ]
27
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,42 @@
1
+ import { defineConfig } from 'vite';
2
+ import react from '@vitejs/plugin-react';
3
+ import dts from 'vite-plugin-dts';
4
+ import { resolve } from 'path';
5
+ import url from 'url';
6
+
7
+ const dirname = url.fileURLToPath(new URL('.', import.meta.url));
8
+
9
+ export default defineConfig({
10
+ publicDir: false,
11
+ plugins: [
12
+ react(),
13
+ dts({
14
+ include: ['src/**/*'],
15
+ outDir: 'dist',
16
+ insertTypesEntry: true,
17
+ tsconfigPath: './tsconfig.json',
18
+ rollupTypes: true
19
+ })
20
+ ],
21
+ build: {
22
+ outDir: 'dist',
23
+ emptyOutDir: true,
24
+ lib: {
25
+ entry: resolve(dirname, 'src/index.ts'),
26
+ name: 'MrigUi',
27
+ fileName: (format) => 'ui.' + format + '.js'
28
+ },
29
+ rollupOptions: {
30
+ external: ['react', 'react-dom', 'framer-motion', '@mrigx/core', '@mrigx/react', '@mrigx/fx'],
31
+ output: {
32
+ globals: {
33
+ 'react': 'React',
34
+ 'react-dom': 'ReactDOM',
35
+ '@mrigx/core': 'MrigCore',
36
+ '@mrigx/react': 'MrigReact',
37
+ '@mrigx/fx': 'MrigFx'
38
+ }
39
+ }
40
+ }
41
+ }
42
+ });