@nationaldesignstudio/react 0.6.1 → 0.7.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 (105) hide show
  1. package/dist/accordion/index.d.ts +95 -0
  2. package/dist/accordion/index.js +143 -0
  3. package/dist/accordion/index.js.map +1 -0
  4. package/dist/background/index.d.ts +149 -0
  5. package/dist/background/index.js +200 -0
  6. package/dist/background/index.js.map +1 -0
  7. package/dist/banner/index.d.ts +101 -0
  8. package/dist/banner/index.js +81 -0
  9. package/dist/banner/index.js.map +1 -0
  10. package/dist/blurred-video-backdrop/index.d.ts +233 -0
  11. package/dist/blurred-video-backdrop/index.js +266 -0
  12. package/dist/blurred-video-backdrop/index.js.map +1 -0
  13. package/dist/button/index.d.ts +180 -0
  14. package/dist/button/index.js +169 -0
  15. package/dist/button/index.js.map +1 -0
  16. package/dist/button-B2g5fH9b.d.ts +152 -0
  17. package/dist/card/index.d.ts +406 -0
  18. package/dist/card/index.js +219 -0
  19. package/dist/card/index.js.map +1 -0
  20. package/dist/card-grid/index.d.ts +90 -0
  21. package/dist/card-grid/index.js +74 -0
  22. package/dist/card-grid/index.js.map +1 -0
  23. package/dist/component-registry.md +136 -2
  24. package/dist/dev-toolbar/index.d.ts +8 -0
  25. package/dist/dev-toolbar/index.js +206 -0
  26. package/dist/dev-toolbar/index.js.map +1 -0
  27. package/dist/dialog/index.d.ts +268 -0
  28. package/dist/dialog/index.js +288 -0
  29. package/dist/dialog/index.js.map +1 -0
  30. package/dist/faq-section/index.d.ts +47 -0
  31. package/dist/faq-section/index.js +152 -0
  32. package/dist/faq-section/index.js.map +1 -0
  33. package/dist/grid-overlay/index.d.ts +10 -0
  34. package/dist/grid-overlay/index.js +38 -0
  35. package/dist/grid-overlay/index.js.map +1 -0
  36. package/dist/hero/index.d.ts +462 -0
  37. package/dist/hero/index.js +494 -0
  38. package/dist/hero/index.js.map +1 -0
  39. package/dist/hooks/index.d.ts +150 -0
  40. package/dist/hooks/index.js +339 -0
  41. package/dist/hooks/index.js.map +1 -0
  42. package/dist/index.d.ts +46 -5339
  43. package/dist/index.js +157 -4080
  44. package/dist/index.js.map +1 -1
  45. package/dist/input/index.d.ts +404 -0
  46. package/dist/input/index.js +393 -0
  47. package/dist/input/index.js.map +1 -0
  48. package/dist/navbar/index.d.ts +68 -0
  49. package/dist/navbar/index.js +227 -0
  50. package/dist/navbar/index.js.map +1 -0
  51. package/dist/ndstudio-footer/index.d.ts +32 -0
  52. package/dist/ndstudio-footer/index.js +35 -0
  53. package/dist/ndstudio-footer/index.js.map +1 -0
  54. package/dist/pager-control/index.d.ts +173 -0
  55. package/dist/pager-control/index.js +267 -0
  56. package/dist/pager-control/index.js.map +1 -0
  57. package/dist/popover/index.d.ts +200 -0
  58. package/dist/popover/index.js +290 -0
  59. package/dist/popover/index.js.map +1 -0
  60. package/dist/prose/index.d.ts +39 -0
  61. package/dist/prose/index.js +56 -0
  62. package/dist/prose/index.js.map +1 -0
  63. package/dist/quote-block/index.d.ts +156 -0
  64. package/dist/quote-block/index.js +321 -0
  65. package/dist/quote-block/index.js.map +1 -0
  66. package/dist/river/index.d.ts +100 -0
  67. package/dist/river/index.js +107 -0
  68. package/dist/river/index.js.map +1 -0
  69. package/dist/select/index.d.ts +188 -0
  70. package/dist/select/index.js +295 -0
  71. package/dist/select/index.js.map +1 -0
  72. package/dist/theme/index.d.ts +149 -0
  73. package/dist/theme/index.js +211 -0
  74. package/dist/theme/index.js.map +1 -0
  75. package/dist/theme-CzBPUlh_.d.ts +332 -0
  76. package/dist/tooltip/index.d.ts +166 -0
  77. package/dist/tooltip/index.js +200 -0
  78. package/dist/tooltip/index.js.map +1 -0
  79. package/dist/tout/index.d.ts +157 -0
  80. package/dist/tout/index.js +315 -0
  81. package/dist/tout/index.js.map +1 -0
  82. package/dist/two-column-section/index.d.ts +122 -0
  83. package/dist/two-column-section/index.js +121 -0
  84. package/dist/two-column-section/index.js.map +1 -0
  85. package/dist/us-gov-banner/index.d.ts +141 -0
  86. package/dist/us-gov-banner/index.js +74 -0
  87. package/dist/us-gov-banner/index.js.map +1 -0
  88. package/dist/use-captions-AkKlJhov.d.ts +71 -0
  89. package/dist/utils/index.d.ts +7 -0
  90. package/dist/utils/index.js +12 -0
  91. package/dist/utils/index.js.map +1 -0
  92. package/dist/video-dialog/index.d.ts +106 -0
  93. package/dist/video-dialog/index.js +1305 -0
  94. package/dist/video-dialog/index.js.map +1 -0
  95. package/dist/video-player/index.d.ts +115 -0
  96. package/dist/video-player/index.js +879 -0
  97. package/dist/video-player/index.js.map +1 -0
  98. package/dist/video-player-qxf-BURH.d.ts +236 -0
  99. package/dist/video-with-backdrop/index.d.ts +267 -0
  100. package/dist/video-with-backdrop/index.js +1284 -0
  101. package/dist/video-with-backdrop/index.js.map +1 -0
  102. package/package.json +13 -2
  103. package/src/components/organisms/us-gov-banner/us-gov-banner.tsx +5 -27
  104. package/src/theme/hooks.ts +2 -0
  105. package/src/theme/theme-provider.tsx +2 -0
@@ -0,0 +1,101 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import { VariantProps } from 'tailwind-variants';
3
+ import * as tailwind_variants_dist_config_js from 'tailwind-variants/dist/config.js';
4
+ import * as React from 'react';
5
+
6
+ /**
7
+ * Banner component based on Figma BaseKit / Banners
8
+ *
9
+ * Used to surface short, important updates or a single key action
10
+ * without disrupting the main page content.
11
+ *
12
+ * Responsive behavior using 24-column grid:
13
+ * - Mobile (sm): Stacked layout, 20px horizontal / 32px vertical padding
14
+ * - Tablet (md): Horizontal layout, 56px padding
15
+ * - Desktop (lg): Horizontal layout, 72px padding
16
+ *
17
+ * Must be placed inside a `grid-container`. Uses `col-full` to span all columns.
18
+ */
19
+ declare const bannerVariants: tailwind_variants.TVReturnType<{
20
+ colorScheme: {
21
+ light: string;
22
+ dark: string;
23
+ };
24
+ }, undefined, string[], tailwind_variants_dist_config_js.TVConfig<{
25
+ colorScheme: {
26
+ light: string;
27
+ dark: string;
28
+ };
29
+ }, {
30
+ colorScheme: {
31
+ light: string;
32
+ dark: string;
33
+ };
34
+ }>, {
35
+ colorScheme: {
36
+ light: string;
37
+ dark: string;
38
+ };
39
+ }, undefined, tailwind_variants.TVReturnType<{
40
+ colorScheme: {
41
+ light: string;
42
+ dark: string;
43
+ };
44
+ }, undefined, string[], tailwind_variants_dist_config_js.TVConfig<{
45
+ colorScheme: {
46
+ light: string;
47
+ dark: string;
48
+ };
49
+ }, {
50
+ colorScheme: {
51
+ light: string;
52
+ dark: string;
53
+ };
54
+ }>, unknown, unknown, undefined>>;
55
+ interface BannerProps extends React.HTMLAttributes<HTMLElement>, VariantProps<typeof bannerVariants> {
56
+ /**
57
+ * The heading text displayed in the banner
58
+ */
59
+ heading: string;
60
+ /**
61
+ * The description text displayed below the heading
62
+ */
63
+ description: string;
64
+ /**
65
+ * Optional action element (typically a Button component)
66
+ */
67
+ action?: React.ReactNode;
68
+ }
69
+ /**
70
+ * Banner component for surfacing important updates or CTAs.
71
+ *
72
+ * Uses the 24-column grid system - must be placed inside a `grid-container`.
73
+ * Spans full width with `col-full`.
74
+ *
75
+ * Responsive across breakpoints:
76
+ * - Mobile: Stacked layout with smaller padding
77
+ * - Tablet: Horizontal layout with medium padding
78
+ * - Desktop: Horizontal layout with larger padding
79
+ *
80
+ * @example
81
+ * ```tsx
82
+ * <div className="grid-container">
83
+ * <Banner
84
+ * heading="Important Update"
85
+ * description="Check out our new features."
86
+ * action={<Button>Learn More</Button>}
87
+ * />
88
+ * </div>
89
+ *
90
+ * // Dark colorScheme
91
+ * <Banner
92
+ * colorScheme="dark"
93
+ * heading="Still Have Questions?"
94
+ * description="Contact us at support@example.com"
95
+ * action={<Button variant="secondary">Email Us</Button>}
96
+ * />
97
+ * ```
98
+ */
99
+ declare const Banner: React.ForwardRefExoticComponent<BannerProps & React.RefAttributes<HTMLElement>>;
100
+
101
+ export { Banner, type BannerProps, bannerVariants };
@@ -0,0 +1,81 @@
1
+ import * as React from 'react';
2
+ import { tv, cnBase } from 'tailwind-variants';
3
+ import { clsx } from 'clsx';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ // src/components/sections/banner/banner.tsx
7
+ function cn(...inputs) {
8
+ return cnBase(clsx(inputs));
9
+ }
10
+ var bannerVariants = tv({
11
+ base: [
12
+ // Grid alignment - full width
13
+ "col-full",
14
+ // Responsive padding: mobile -> tablet -> desktop
15
+ // Uses primitive spacing tokens
16
+ "px-20 py-32",
17
+ "md:p-56",
18
+ "lg:px-72 lg:pb-72 lg:pt-0"
19
+ ],
20
+ variants: {
21
+ colorScheme: {
22
+ light: "bg-gray-50",
23
+ dark: "bg-gray-1200"
24
+ }
25
+ },
26
+ defaultVariants: {
27
+ colorScheme: "light"
28
+ }
29
+ });
30
+ var Banner = React.forwardRef(
31
+ ({ className, colorScheme, heading, description, action, ...props }, ref) => {
32
+ return /* @__PURE__ */ jsx(
33
+ "section",
34
+ {
35
+ ref,
36
+ className: bannerVariants({ colorScheme, class: className }),
37
+ ...props,
38
+ children: /* @__PURE__ */ jsxs(
39
+ "div",
40
+ {
41
+ className: cn(
42
+ // Uses primitive spacing tokens
43
+ "flex flex-col md:flex-row gap-20 items-start md:items-center md:justify-between",
44
+ colorScheme === "dark" && "border-t border-gray-700 py-36"
45
+ ),
46
+ children: [
47
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6 items-start", children: [
48
+ /* @__PURE__ */ jsx(
49
+ "h2",
50
+ {
51
+ className: cn(
52
+ "typography-subheading-small",
53
+ colorScheme === "dark" ? "text-gray-100" : "text-gray-900"
54
+ ),
55
+ children: heading
56
+ }
57
+ ),
58
+ /* @__PURE__ */ jsx(
59
+ "p",
60
+ {
61
+ className: cn(
62
+ "typography-body-small",
63
+ colorScheme === "dark" ? "text-gray-500" : "text-gray-800"
64
+ ),
65
+ children: description
66
+ }
67
+ )
68
+ ] }),
69
+ action
70
+ ]
71
+ }
72
+ )
73
+ }
74
+ );
75
+ }
76
+ );
77
+ Banner.displayName = "Banner";
78
+
79
+ export { Banner, bannerVariants };
80
+ //# sourceMappingURL=index.js.map
81
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/utils.ts","../../src/components/sections/banner/banner.tsx"],"names":["twMerge"],"mappings":";;;;;;AAKO,SAAS,MAAM,MAAA,EAAsB;AAC3C,EAAA,OAAOA,MAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC5B;ACUA,IAAM,iBAAiB,EAAA,CAAG;AAAA,EACzB,IAAA,EAAM;AAAA;AAAA,IAEL,UAAA;AAAA;AAAA;AAAA,IAGA,aAAA;AAAA,IACA,SAAA;AAAA,IACA;AAAA,GACD;AAAA,EACA,QAAA,EAAU;AAAA,IACT,WAAA,EAAa;AAAA,MACZ,KAAA,EAAO,YAAA;AAAA,MACP,IAAA,EAAM;AAAA;AACP,GACD;AAAA,EACA,eAAA,EAAiB;AAAA,IAChB,WAAA,EAAa;AAAA;AAEf,CAAC;AAiDD,IAAM,MAAA,GAAe,KAAA,CAAA,UAAA;AAAA,EACpB,CAAC,EAAE,SAAA,EAAW,WAAA,EAAa,OAAA,EAAS,aAAa,MAAA,EAAQ,GAAG,KAAA,EAAM,EAAG,GAAA,KAAQ;AAC5E,IAAA,uBACC,GAAA;AAAA,MAAC,SAAA;AAAA,MAAA;AAAA,QACA,GAAA;AAAA,QACA,WAAW,cAAA,CAAe,EAAE,WAAA,EAAa,KAAA,EAAO,WAAW,CAAA;AAAA,QAC1D,GAAG,KAAA;AAAA,QAGJ,QAAA,kBAAA,IAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACA,SAAA,EAAW,EAAA;AAAA;AAAA,cAEV,iFAAA;AAAA,cACA,gBAAgB,MAAA,IAAU;AAAA,aAC3B;AAAA,YAGA,QAAA,EAAA;AAAA,8BAAA,IAAA,CAAC,KAAA,EAAA,EAAI,WAAU,iCAAA,EACd,QAAA,EAAA;AAAA,gCAAA,GAAA;AAAA,kBAAC,IAAA;AAAA,kBAAA;AAAA,oBACA,SAAA,EAAW,EAAA;AAAA,sBACV,6BAAA;AAAA,sBACA,WAAA,KAAgB,SAAS,eAAA,GAAkB;AAAA,qBAC5C;AAAA,oBAEC,QAAA,EAAA;AAAA;AAAA,iBACF;AAAA,gCACA,GAAA;AAAA,kBAAC,GAAA;AAAA,kBAAA;AAAA,oBACA,SAAA,EAAW,EAAA;AAAA,sBACV,uBAAA;AAAA,sBACA,WAAA,KAAgB,SAAS,eAAA,GAAkB;AAAA,qBAC5C;AAAA,oBAEC,QAAA,EAAA;AAAA;AAAA;AACF,eAAA,EACD,CAAA;AAAA,cAEC;AAAA;AAAA;AAAA;AACF;AAAA,KACD;AAAA,EAEF;AACD;AACA,MAAA,CAAO,WAAA,GAAc,QAAA","file":"index.js","sourcesContent":["import { type ClassValue, clsx } from \"clsx\";\nimport { cnBase as twMerge } from \"tailwind-variants\";\n\nexport { twMerge };\n\nexport function cn(...inputs: ClassValue[]) {\n\treturn twMerge(clsx(inputs));\n}\n","import * as React from \"react\";\nimport { tv, type VariantProps } from \"tailwind-variants\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Banner component based on Figma BaseKit / Banners\n *\n * Used to surface short, important updates or a single key action\n * without disrupting the main page content.\n *\n * Responsive behavior using 24-column grid:\n * - Mobile (sm): Stacked layout, 20px horizontal / 32px vertical padding\n * - Tablet (md): Horizontal layout, 56px padding\n * - Desktop (lg): Horizontal layout, 72px padding\n *\n * Must be placed inside a `grid-container`. Uses `col-full` to span all columns.\n */\nconst bannerVariants = tv({\n\tbase: [\n\t\t// Grid alignment - full width\n\t\t\"col-full\",\n\t\t// Responsive padding: mobile -> tablet -> desktop\n\t\t// Uses primitive spacing tokens\n\t\t\"px-20 py-32\",\n\t\t\"md:p-56\",\n\t\t\"lg:px-72 lg:pb-72 lg:pt-0\",\n\t],\n\tvariants: {\n\t\tcolorScheme: {\n\t\t\tlight: \"bg-gray-50\",\n\t\t\tdark: \"bg-gray-1200\",\n\t\t},\n\t},\n\tdefaultVariants: {\n\t\tcolorScheme: \"light\",\n\t},\n});\n\nexport interface BannerProps\n\textends React.HTMLAttributes<HTMLElement>,\n\t\tVariantProps<typeof bannerVariants> {\n\t/**\n\t * The heading text displayed in the banner\n\t */\n\theading: string;\n\t/**\n\t * The description text displayed below the heading\n\t */\n\tdescription: string;\n\t/**\n\t * Optional action element (typically a Button component)\n\t */\n\taction?: React.ReactNode;\n}\n\n/**\n * Banner component for surfacing important updates or CTAs.\n *\n * Uses the 24-column grid system - must be placed inside a `grid-container`.\n * Spans full width with `col-full`.\n *\n * Responsive across breakpoints:\n * - Mobile: Stacked layout with smaller padding\n * - Tablet: Horizontal layout with medium padding\n * - Desktop: Horizontal layout with larger padding\n *\n * @example\n * ```tsx\n * <div className=\"grid-container\">\n * <Banner\n * heading=\"Important Update\"\n * description=\"Check out our new features.\"\n * action={<Button>Learn More</Button>}\n * />\n * </div>\n *\n * // Dark colorScheme\n * <Banner\n * colorScheme=\"dark\"\n * heading=\"Still Have Questions?\"\n * description=\"Contact us at support@example.com\"\n * action={<Button variant=\"secondary\">Email Us</Button>}\n * />\n * ```\n */\nconst Banner = React.forwardRef<HTMLElement, BannerProps>(\n\t({ className, colorScheme, heading, description, action, ...props }, ref) => {\n\t\treturn (\n\t\t\t<section\n\t\t\t\tref={ref}\n\t\t\t\tclassName={bannerVariants({ colorScheme, class: className })}\n\t\t\t\t{...props}\n\t\t\t>\n\t\t\t\t{/* Inner container with border-top for dark colorScheme */}\n\t\t\t\t<div\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t// Uses primitive spacing tokens\n\t\t\t\t\t\t\"flex flex-col md:flex-row gap-20 items-start md:items-center md:justify-between\",\n\t\t\t\t\t\tcolorScheme === \"dark\" && \"border-t border-gray-700 py-36\",\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t{/* Copy section */}\n\t\t\t\t\t<div className=\"flex flex-col gap-6 items-start\">\n\t\t\t\t\t\t<h2\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"typography-subheading-small\",\n\t\t\t\t\t\t\t\tcolorScheme === \"dark\" ? \"text-gray-100\" : \"text-gray-900\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{heading}\n\t\t\t\t\t\t</h2>\n\t\t\t\t\t\t<p\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"typography-body-small\",\n\t\t\t\t\t\t\t\tcolorScheme === \"dark\" ? \"text-gray-500\" : \"text-gray-800\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{description}\n\t\t\t\t\t\t</p>\n\t\t\t\t\t</div>\n\t\t\t\t\t{/* Action slot */}\n\t\t\t\t\t{action}\n\t\t\t\t</div>\n\t\t\t</section>\n\t\t);\n\t},\n);\nBanner.displayName = \"Banner\";\n\nexport { Banner, bannerVariants };\n"]}
@@ -0,0 +1,233 @@
1
+ import * as tailwind_variants from 'tailwind-variants';
2
+ import { VariantProps } from 'tailwind-variants';
3
+ import * as tailwind_variants_dist_config_js from 'tailwind-variants/dist/config.js';
4
+ import * as React from 'react';
5
+
6
+ type BlurIntensity = "low" | "medium" | "high" | "extreme";
7
+ type OverlayType = "none" | "vignette" | "top-bottom";
8
+ /**
9
+ * Blurred video backdrop wrapper variants.
10
+ *
11
+ * The wrapper extends beyond its bounds (inset: -120px) to cover
12
+ * blur artifacts at the edges.
13
+ */
14
+ declare const blurredVideoBackdropVariants: tailwind_variants.TVReturnType<{
15
+ /**
16
+ * Blur intensity level.
17
+ * Higher values provide more diffused backgrounds.
18
+ */
19
+ blur: {
20
+ low: string;
21
+ medium: string;
22
+ high: string;
23
+ extreme: string;
24
+ };
25
+ /**
26
+ * Gradient overlay for visual depth.
27
+ */
28
+ overlay: {
29
+ none: string;
30
+ vignette: string;
31
+ "top-bottom": string;
32
+ };
33
+ }, undefined, string[], tailwind_variants_dist_config_js.TVConfig<{
34
+ /**
35
+ * Blur intensity level.
36
+ * Higher values provide more diffused backgrounds.
37
+ */
38
+ blur: {
39
+ low: string;
40
+ medium: string;
41
+ high: string;
42
+ extreme: string;
43
+ };
44
+ /**
45
+ * Gradient overlay for visual depth.
46
+ */
47
+ overlay: {
48
+ none: string;
49
+ vignette: string;
50
+ "top-bottom": string;
51
+ };
52
+ }, {
53
+ /**
54
+ * Blur intensity level.
55
+ * Higher values provide more diffused backgrounds.
56
+ */
57
+ blur: {
58
+ low: string;
59
+ medium: string;
60
+ high: string;
61
+ extreme: string;
62
+ };
63
+ /**
64
+ * Gradient overlay for visual depth.
65
+ */
66
+ overlay: {
67
+ none: string;
68
+ vignette: string;
69
+ "top-bottom": string;
70
+ };
71
+ }>, {
72
+ /**
73
+ * Blur intensity level.
74
+ * Higher values provide more diffused backgrounds.
75
+ */
76
+ blur: {
77
+ low: string;
78
+ medium: string;
79
+ high: string;
80
+ extreme: string;
81
+ };
82
+ /**
83
+ * Gradient overlay for visual depth.
84
+ */
85
+ overlay: {
86
+ none: string;
87
+ vignette: string;
88
+ "top-bottom": string;
89
+ };
90
+ }, undefined, tailwind_variants.TVReturnType<{
91
+ /**
92
+ * Blur intensity level.
93
+ * Higher values provide more diffused backgrounds.
94
+ */
95
+ blur: {
96
+ low: string;
97
+ medium: string;
98
+ high: string;
99
+ extreme: string;
100
+ };
101
+ /**
102
+ * Gradient overlay for visual depth.
103
+ */
104
+ overlay: {
105
+ none: string;
106
+ vignette: string;
107
+ "top-bottom": string;
108
+ };
109
+ }, undefined, string[], tailwind_variants_dist_config_js.TVConfig<{
110
+ /**
111
+ * Blur intensity level.
112
+ * Higher values provide more diffused backgrounds.
113
+ */
114
+ blur: {
115
+ low: string;
116
+ medium: string;
117
+ high: string;
118
+ extreme: string;
119
+ };
120
+ /**
121
+ * Gradient overlay for visual depth.
122
+ */
123
+ overlay: {
124
+ none: string;
125
+ vignette: string;
126
+ "top-bottom": string;
127
+ };
128
+ }, {
129
+ /**
130
+ * Blur intensity level.
131
+ * Higher values provide more diffused backgrounds.
132
+ */
133
+ blur: {
134
+ low: string;
135
+ medium: string;
136
+ high: string;
137
+ extreme: string;
138
+ };
139
+ /**
140
+ * Gradient overlay for visual depth.
141
+ */
142
+ overlay: {
143
+ none: string;
144
+ vignette: string;
145
+ "top-bottom": string;
146
+ };
147
+ }>, unknown, unknown, undefined>>;
148
+ /**
149
+ * Canvas element styles.
150
+ */
151
+ declare const canvasVariants: tailwind_variants.TVReturnType<{} | {} | {}, undefined, string[], tailwind_variants_dist_config_js.TVConfig<unknown, {} | {}>, {} | {}, undefined, tailwind_variants.TVReturnType<unknown, undefined, string[], tailwind_variants_dist_config_js.TVConfig<unknown, {} | {}>, unknown, unknown, undefined>>;
152
+ /**
153
+ * Gradient overlay base styles.
154
+ * Gradient backgrounds are applied via inline styles to avoid arbitrary values.
155
+ */
156
+ declare const gradientOverlayVariants: tailwind_variants.TVReturnType<{} | {} | {}, undefined, string[], tailwind_variants_dist_config_js.TVConfig<unknown, {} | {}>, {} | {}, undefined, tailwind_variants.TVReturnType<unknown, undefined, string[], tailwind_variants_dist_config_js.TVConfig<unknown, {} | {}>, unknown, unknown, undefined>>;
157
+ declare const BLUR_AMOUNTS: Record<BlurIntensity, number>;
158
+ interface UseCanvasBlurOptions {
159
+ /** Ref to the source video element */
160
+ videoRef: React.RefObject<HTMLVideoElement | null>;
161
+ /** Blur amount in pixels */
162
+ blurAmount: number;
163
+ /** Whether rendering is enabled */
164
+ enabled?: boolean;
165
+ /** Target FPS (lower = better performance, default: 30) */
166
+ targetFps?: number;
167
+ /** Canvas scale factor (lower = better performance, default: 0.5) */
168
+ scale?: number;
169
+ }
170
+ interface UseCanvasBlurReturn {
171
+ /** Ref to attach to the canvas element */
172
+ canvasRef: React.RefObject<HTMLCanvasElement | null>;
173
+ /** Whether the canvas is currently rendering */
174
+ isRendering: boolean;
175
+ /** Performance metrics */
176
+ metrics: {
177
+ fps: number;
178
+ frameTime: number;
179
+ };
180
+ }
181
+ /**
182
+ * Hook for rendering a blurred video to canvas.
183
+ *
184
+ * Performance optimizations:
185
+ * - Renders at reduced resolution (scale factor)
186
+ * - Throttled to target FPS
187
+ * - Uses CSS scale to fill container
188
+ * - Single video decoder (no sync needed)
189
+ */
190
+ declare function useCanvasBlur({ videoRef, blurAmount, enabled, targetFps, scale, }: UseCanvasBlurOptions): UseCanvasBlurReturn;
191
+ interface BlurredVideoBackdropProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "children">, VariantProps<typeof blurredVideoBackdropVariants> {
192
+ /** Ref to the primary video element to create backdrop from (required) */
193
+ videoRef: React.RefObject<HTMLVideoElement | null>;
194
+ /** Opacity of the backdrop (0-1, default: 0.6) */
195
+ opacity?: number;
196
+ /** Extension amount in pixels to cover blur artifacts (default: 120) */
197
+ extension?: number;
198
+ /** Target FPS for canvas rendering (default: 30) */
199
+ targetFps?: number;
200
+ /** Canvas scale factor - lower = better performance (default: 0.5) */
201
+ scale?: number;
202
+ /** Whether to show debug metrics */
203
+ showMetrics?: boolean;
204
+ }
205
+ /**
206
+ * BlurredVideoBackdrop - A high-performance blurred video backdrop using canvas.
207
+ *
208
+ * Renders a blurred copy of a video element to create an ambient backdrop effect.
209
+ * Uses canvas rendering for optimal performance - no video sync needed.
210
+ *
211
+ * Performance features:
212
+ * - Single video decoder (draws from existing video element)
213
+ * - Reduced resolution rendering (configurable scale)
214
+ * - Throttled frame rate (configurable FPS)
215
+ * - GPU-accelerated canvas scaling
216
+ *
217
+ * @example
218
+ * ```tsx
219
+ * const videoRef = useRef<HTMLVideoElement>(null);
220
+ *
221
+ * <div className="relative">
222
+ * <BlurredVideoBackdrop
223
+ * videoRef={videoRef}
224
+ * blur="high"
225
+ * overlay="vignette"
226
+ * />
227
+ * <VideoPlayer videoRef={videoRef} src="/video.mp4" />
228
+ * </div>
229
+ * ```
230
+ */
231
+ declare const BlurredVideoBackdrop: React.ForwardRefExoticComponent<BlurredVideoBackdropProps & React.RefAttributes<HTMLDivElement>>;
232
+
233
+ export { BLUR_AMOUNTS, type BlurIntensity, BlurredVideoBackdrop, type BlurredVideoBackdropProps, type OverlayType, type UseCanvasBlurOptions, type UseCanvasBlurReturn, blurredVideoBackdropVariants, canvasVariants, gradientOverlayVariants, useCanvasBlur };
@@ -0,0 +1,266 @@
1
+ "use client";
2
+ import * as React from 'react';
3
+ import { tv, cnBase } from 'tailwind-variants';
4
+ import { clsx } from 'clsx';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ // src/components/atoms/blurred-video-backdrop/blurred-video-backdrop.tsx
8
+ function cn(...inputs) {
9
+ return cnBase(clsx(inputs));
10
+ }
11
+ var blurredVideoBackdropVariants = tv({
12
+ base: [
13
+ "absolute",
14
+ "pointer-events-none",
15
+ "select-none",
16
+ "will-change-contents",
17
+ "transform-gpu"
18
+ ],
19
+ variants: {
20
+ /**
21
+ * Blur intensity level.
22
+ * Higher values provide more diffused backgrounds.
23
+ */
24
+ blur: {
25
+ low: "",
26
+ medium: "",
27
+ high: "",
28
+ extreme: ""
29
+ },
30
+ /**
31
+ * Gradient overlay for visual depth.
32
+ */
33
+ overlay: {
34
+ none: "",
35
+ vignette: "",
36
+ "top-bottom": ""
37
+ }
38
+ },
39
+ defaultVariants: {
40
+ blur: "high",
41
+ overlay: "none"
42
+ }
43
+ });
44
+ var canvasVariants = tv({
45
+ base: ["w-full", "h-full", "object-cover"]
46
+ });
47
+ var gradientOverlayVariants = tv({
48
+ base: ["absolute", "inset-0", "pointer-events-none"]
49
+ });
50
+ var OVERLAY_GRADIENTS = {
51
+ vignette: "radial-gradient(ellipse at center, transparent 40%, rgba(0, 0, 0, 0.4) 100%)",
52
+ "top-bottom": "linear-gradient(180deg, rgba(0, 0, 0, 0.4) 0%, transparent 30%, transparent 70%, rgba(0, 0, 0, 0.4) 100%)"
53
+ };
54
+ var BLUR_AMOUNTS = {
55
+ low: 40,
56
+ medium: 80,
57
+ high: 100,
58
+ extreme: 120
59
+ };
60
+ function useCanvasBlur({
61
+ videoRef,
62
+ blurAmount,
63
+ enabled = true,
64
+ targetFps = 30,
65
+ scale = 0.5
66
+ }) {
67
+ const canvasRef = React.useRef(null);
68
+ const ctxRef = React.useRef(null);
69
+ const [isRendering, setIsRendering] = React.useState(false);
70
+ const [metrics, setMetrics] = React.useState({ fps: 0, frameTime: 0 });
71
+ const [videoReady, setVideoReady] = React.useState(false);
72
+ const lastFrameTimeRef = React.useRef(0);
73
+ const frameCountRef = React.useRef(0);
74
+ const fpsIntervalRef = React.useRef(0);
75
+ const frameInterval = 1e3 / targetFps;
76
+ React.useEffect(() => {
77
+ if (!enabled) return;
78
+ const checkRef = () => {
79
+ if (videoRef.current && canvasRef.current) {
80
+ setVideoReady(true);
81
+ }
82
+ };
83
+ checkRef();
84
+ const frameId = requestAnimationFrame(checkRef);
85
+ const timeoutId = setTimeout(checkRef, 100);
86
+ const timeoutId2 = setTimeout(checkRef, 500);
87
+ return () => {
88
+ cancelAnimationFrame(frameId);
89
+ clearTimeout(timeoutId);
90
+ clearTimeout(timeoutId2);
91
+ };
92
+ }, [enabled, videoRef]);
93
+ React.useEffect(() => {
94
+ if (!enabled || !videoReady) return;
95
+ const video = videoRef.current;
96
+ const canvas = canvasRef.current;
97
+ if (!video || !canvas) return;
98
+ const ctx = canvas.getContext("2d", {
99
+ alpha: false,
100
+ desynchronized: true
101
+ // Reduces latency
102
+ });
103
+ if (!ctx) return;
104
+ ctxRef.current = ctx;
105
+ let animationFrameId;
106
+ let isActive = true;
107
+ const updateCanvasSize = () => {
108
+ if (video.videoWidth && video.videoHeight) {
109
+ canvas.width = Math.floor(video.videoWidth * scale);
110
+ canvas.height = Math.floor(video.videoHeight * scale);
111
+ }
112
+ };
113
+ const render = (timestamp) => {
114
+ if (!isActive || !video || !ctx) return;
115
+ const elapsed = timestamp - lastFrameTimeRef.current;
116
+ if (elapsed >= frameInterval) {
117
+ const frameStart = performance.now();
118
+ if (canvas.width === 0 || canvas.height === 0) {
119
+ updateCanvasSize();
120
+ }
121
+ if (video.readyState >= 2 && !video.paused) {
122
+ ctx.filter = `blur(${blurAmount * scale}px)`;
123
+ ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
124
+ setIsRendering(true);
125
+ }
126
+ const frameTime = performance.now() - frameStart;
127
+ frameCountRef.current++;
128
+ if (timestamp - fpsIntervalRef.current >= 1e3) {
129
+ setMetrics({
130
+ fps: frameCountRef.current,
131
+ frameTime: Math.round(frameTime * 100) / 100
132
+ });
133
+ frameCountRef.current = 0;
134
+ fpsIntervalRef.current = timestamp;
135
+ }
136
+ lastFrameTimeRef.current = timestamp - elapsed % frameInterval;
137
+ }
138
+ animationFrameId = requestAnimationFrame(render);
139
+ };
140
+ const handleLoadedMetadata = () => {
141
+ updateCanvasSize();
142
+ };
143
+ const handlePlay = () => {
144
+ if (isActive) {
145
+ animationFrameId = requestAnimationFrame(render);
146
+ }
147
+ };
148
+ const handlePause = () => {
149
+ setIsRendering(false);
150
+ };
151
+ video.addEventListener("loadedmetadata", handleLoadedMetadata);
152
+ video.addEventListener("play", handlePlay);
153
+ video.addEventListener("pause", handlePause);
154
+ if (video.readyState >= 1) {
155
+ updateCanvasSize();
156
+ }
157
+ if (!video.paused) {
158
+ animationFrameId = requestAnimationFrame(render);
159
+ }
160
+ return () => {
161
+ isActive = false;
162
+ cancelAnimationFrame(animationFrameId);
163
+ video.removeEventListener("loadedmetadata", handleLoadedMetadata);
164
+ video.removeEventListener("play", handlePlay);
165
+ video.removeEventListener("pause", handlePause);
166
+ setIsRendering(false);
167
+ };
168
+ }, [enabled, videoReady, videoRef, blurAmount, frameInterval, scale]);
169
+ return {
170
+ canvasRef,
171
+ isRendering,
172
+ metrics
173
+ };
174
+ }
175
+ var BlurredVideoBackdrop = React.forwardRef(
176
+ ({
177
+ className,
178
+ videoRef,
179
+ blur = "high",
180
+ overlay = "none",
181
+ opacity = 0.6,
182
+ extension = 120,
183
+ targetFps = 30,
184
+ scale = 0.5,
185
+ showMetrics = false,
186
+ style,
187
+ ...props
188
+ }, ref) => {
189
+ const blurAmount = BLUR_AMOUNTS[blur ?? "high"];
190
+ const { canvasRef, isRendering, metrics } = useCanvasBlur({
191
+ videoRef,
192
+ blurAmount,
193
+ enabled: true,
194
+ targetFps,
195
+ scale
196
+ });
197
+ return /* @__PURE__ */ jsxs(
198
+ "div",
199
+ {
200
+ ref,
201
+ className: cn(
202
+ blurredVideoBackdropVariants({ blur, overlay }),
203
+ className
204
+ ),
205
+ style: {
206
+ inset: `-${extension}px`,
207
+ opacity,
208
+ contain: "layout style paint",
209
+ ...style
210
+ },
211
+ "data-blur": blur ?? "high",
212
+ "data-overlay": overlay ?? "none",
213
+ "data-rendering": isRendering,
214
+ "aria-hidden": "true",
215
+ ...props,
216
+ children: [
217
+ /* @__PURE__ */ jsx(
218
+ "canvas",
219
+ {
220
+ ref: canvasRef,
221
+ className: cn(
222
+ canvasVariants(),
223
+ // Scale up the low-res canvas to fill container
224
+ "scale-[2]",
225
+ // Inverse of 0.5 scale factor
226
+ "origin-center"
227
+ ),
228
+ style: {
229
+ // Additional CSS blur for smoother appearance
230
+ filter: `blur(${blurAmount * 0.3}px)`
231
+ }
232
+ }
233
+ ),
234
+ overlay && overlay !== "none" && /* @__PURE__ */ jsx(
235
+ "div",
236
+ {
237
+ className: gradientOverlayVariants(),
238
+ style: { background: OVERLAY_GRADIENTS[overlay] }
239
+ }
240
+ ),
241
+ showMetrics && /* @__PURE__ */ jsxs("div", { className: "absolute bottom-8 left-8 z-10 bg-black/80 text-white typography-caption px-8 py-4 rounded-4 font-mono", children: [
242
+ /* @__PURE__ */ jsxs("div", { children: [
243
+ "FPS: ",
244
+ metrics.fps
245
+ ] }),
246
+ /* @__PURE__ */ jsxs("div", { children: [
247
+ "Frame: ",
248
+ metrics.frameTime,
249
+ "ms"
250
+ ] }),
251
+ /* @__PURE__ */ jsxs("div", { children: [
252
+ "Scale: ",
253
+ scale,
254
+ "x"
255
+ ] })
256
+ ] })
257
+ ]
258
+ }
259
+ );
260
+ }
261
+ );
262
+ BlurredVideoBackdrop.displayName = "BlurredVideoBackdrop";
263
+
264
+ export { BLUR_AMOUNTS, BlurredVideoBackdrop, blurredVideoBackdropVariants, canvasVariants, gradientOverlayVariants, useCanvasBlur };
265
+ //# sourceMappingURL=index.js.map
266
+ //# sourceMappingURL=index.js.map