@djangocfg/ui-nextjs 2.1.65 → 2.1.67

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 (92) hide show
  1. package/package.json +13 -8
  2. package/src/blocks/SplitHero/SplitHeroMedia.tsx +2 -1
  3. package/src/stores/index.ts +8 -0
  4. package/src/stores/mediaCache.ts +464 -0
  5. package/src/tools/AudioPlayer/@refactoring/00-PLAN.md +148 -0
  6. package/src/tools/AudioPlayer/@refactoring/01-TYPES.md +301 -0
  7. package/src/tools/AudioPlayer/@refactoring/02-HOOKS.md +281 -0
  8. package/src/tools/AudioPlayer/@refactoring/03-CONTEXT.md +328 -0
  9. package/src/tools/AudioPlayer/@refactoring/04-COMPONENTS.md +251 -0
  10. package/src/tools/AudioPlayer/@refactoring/05-EFFECTS.md +427 -0
  11. package/src/tools/AudioPlayer/@refactoring/06-UTILS-AND-INDEX.md +193 -0
  12. package/src/tools/AudioPlayer/@refactoring/07-EXECUTION-CHECKLIST.md +146 -0
  13. package/src/tools/AudioPlayer/README.md +325 -0
  14. package/src/tools/AudioPlayer/components/AudioEqualizer.tsx +200 -0
  15. package/src/tools/AudioPlayer/components/AudioPlayer.tsx +231 -0
  16. package/src/tools/AudioPlayer/components/AudioShortcutsPopover.tsx +99 -0
  17. package/src/tools/AudioPlayer/components/ReactiveCover/AudioReactiveCover.tsx +147 -0
  18. package/src/tools/AudioPlayer/components/ReactiveCover/effects/GlowEffect.tsx +110 -0
  19. package/src/tools/AudioPlayer/components/ReactiveCover/effects/MeshEffect.tsx +58 -0
  20. package/src/tools/AudioPlayer/components/ReactiveCover/effects/OrbsEffect.tsx +45 -0
  21. package/src/tools/AudioPlayer/components/ReactiveCover/effects/SpotlightEffect.tsx +82 -0
  22. package/src/tools/AudioPlayer/components/ReactiveCover/effects/index.ts +8 -0
  23. package/src/tools/AudioPlayer/components/ReactiveCover/index.ts +6 -0
  24. package/src/tools/AudioPlayer/components/SimpleAudioPlayer.tsx +280 -0
  25. package/src/tools/AudioPlayer/components/VisualizationToggle.tsx +64 -0
  26. package/src/tools/AudioPlayer/components/index.ts +21 -0
  27. package/src/tools/AudioPlayer/context/AudioProvider.tsx +292 -0
  28. package/src/tools/AudioPlayer/context/index.ts +11 -0
  29. package/src/tools/AudioPlayer/context/selectors.ts +96 -0
  30. package/src/tools/AudioPlayer/effects/index.ts +412 -0
  31. package/src/tools/AudioPlayer/hooks/index.ts +29 -0
  32. package/src/tools/AudioPlayer/hooks/useAudioAnalysis.ts +110 -0
  33. package/src/tools/AudioPlayer/hooks/useAudioHotkeys.ts +149 -0
  34. package/src/tools/AudioPlayer/hooks/useSharedWebAudio.ts +106 -0
  35. package/src/tools/AudioPlayer/hooks/useVisualization.tsx +201 -0
  36. package/src/tools/AudioPlayer/index.ts +139 -0
  37. package/src/tools/AudioPlayer/types/audio.ts +107 -0
  38. package/src/tools/AudioPlayer/types/components.ts +98 -0
  39. package/src/tools/AudioPlayer/types/effects.ts +73 -0
  40. package/src/tools/AudioPlayer/types/index.ts +35 -0
  41. package/src/tools/AudioPlayer/utils/formatTime.ts +10 -0
  42. package/src/tools/AudioPlayer/utils/index.ts +5 -0
  43. package/src/tools/ImageViewer/@refactoring/00-PLAN.md +71 -0
  44. package/src/tools/ImageViewer/@refactoring/01-TYPES.md +121 -0
  45. package/src/tools/ImageViewer/@refactoring/02-UTILS.md +143 -0
  46. package/src/tools/ImageViewer/@refactoring/03-HOOKS.md +261 -0
  47. package/src/tools/ImageViewer/@refactoring/04-COMPONENTS.md +427 -0
  48. package/src/tools/ImageViewer/@refactoring/05-EXECUTION-CHECKLIST.md +126 -0
  49. package/src/tools/ImageViewer/README.md +174 -0
  50. package/src/tools/ImageViewer/components/ImageInfo.tsx +44 -0
  51. package/src/tools/ImageViewer/components/ImageToolbar.tsx +150 -0
  52. package/src/tools/ImageViewer/components/ImageViewer.tsx +235 -0
  53. package/src/tools/ImageViewer/components/index.ts +7 -0
  54. package/src/tools/ImageViewer/hooks/index.ts +9 -0
  55. package/src/tools/ImageViewer/hooks/useImageLoading.ts +153 -0
  56. package/src/tools/ImageViewer/hooks/useImageTransform.ts +101 -0
  57. package/src/tools/ImageViewer/index.ts +60 -0
  58. package/src/tools/ImageViewer/types.ts +75 -0
  59. package/src/tools/ImageViewer/utils/constants.ts +59 -0
  60. package/src/tools/ImageViewer/utils/index.ts +16 -0
  61. package/src/tools/ImageViewer/utils/lqip.ts +47 -0
  62. package/src/tools/VideoPlayer/@refactoring/00-PLAN.md +91 -0
  63. package/src/tools/VideoPlayer/@refactoring/01-TYPES.md +284 -0
  64. package/src/tools/VideoPlayer/@refactoring/02-UTILS.md +141 -0
  65. package/src/tools/VideoPlayer/@refactoring/03-HOOKS.md +178 -0
  66. package/src/tools/VideoPlayer/@refactoring/04-COMPONENTS.md +95 -0
  67. package/src/tools/VideoPlayer/@refactoring/05-EXECUTION-CHECKLIST.md +139 -0
  68. package/src/tools/VideoPlayer/README.md +212 -187
  69. package/src/tools/VideoPlayer/{VideoControls.tsx → components/VideoControls.tsx} +8 -9
  70. package/src/tools/VideoPlayer/components/VideoErrorFallback.tsx +174 -0
  71. package/src/tools/VideoPlayer/components/VideoPlayer.tsx +201 -0
  72. package/src/tools/VideoPlayer/components/index.ts +14 -0
  73. package/src/tools/VideoPlayer/context/VideoPlayerContext.tsx +52 -0
  74. package/src/tools/VideoPlayer/context/index.ts +8 -0
  75. package/src/tools/VideoPlayer/hooks/index.ts +9 -0
  76. package/src/tools/VideoPlayer/hooks/useVideoPositionCache.ts +109 -0
  77. package/src/tools/VideoPlayer/index.ts +70 -9
  78. package/src/tools/VideoPlayer/providers/NativeProvider.tsx +206 -0
  79. package/src/tools/VideoPlayer/providers/StreamProvider.tsx +401 -0
  80. package/src/tools/VideoPlayer/providers/VidstackProvider.tsx +332 -0
  81. package/src/tools/VideoPlayer/providers/index.ts +8 -0
  82. package/src/tools/VideoPlayer/types/index.ts +38 -0
  83. package/src/tools/VideoPlayer/types/player.ts +116 -0
  84. package/src/tools/VideoPlayer/types/provider.ts +93 -0
  85. package/src/tools/VideoPlayer/types/sources.ts +97 -0
  86. package/src/tools/VideoPlayer/utils/fileSource.ts +78 -0
  87. package/src/tools/VideoPlayer/utils/index.ts +11 -0
  88. package/src/tools/VideoPlayer/utils/resolvers.ts +75 -0
  89. package/src/tools/index.ts +92 -4
  90. package/src/tools/VideoPlayer/NativePlayer.tsx +0 -141
  91. package/src/tools/VideoPlayer/VideoPlayer.tsx +0 -231
  92. package/src/tools/VideoPlayer/types.ts +0 -118
@@ -0,0 +1,82 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * SpotlightEffect - Rotating spotlight with conic gradients
5
+ */
6
+
7
+ import { cn } from '@djangocfg/ui-nextjs';
8
+ import type { calculateSpotlight } from '../../../effects';
9
+
10
+ // =============================================================================
11
+ // TYPES
12
+ // =============================================================================
13
+
14
+ interface SpotlightEffectProps {
15
+ data: ReturnType<typeof calculateSpotlight>;
16
+ colors: string[];
17
+ blur: string;
18
+ isPlaying: boolean;
19
+ }
20
+
21
+ // =============================================================================
22
+ // COMPONENT
23
+ // =============================================================================
24
+
25
+ export function SpotlightEffect({ data, colors, blur, isPlaying }: SpotlightEffectProps) {
26
+ const inset = 'inset' in data ? data.inset : 12;
27
+ const pulseInset = 'pulseInset' in data ? data.pulseInset : 24;
28
+ const ringOpacity = 'ringOpacity' in data ? data.ringOpacity : 0.3;
29
+ const ringScale = 'ringScale' in data ? data.ringScale : 1;
30
+
31
+ return (
32
+ <>
33
+ {/* Rotating conic gradient - reactive size */}
34
+ <div
35
+ className={cn('absolute rounded-xl -z-10', blur)}
36
+ style={{
37
+ inset: `-${inset}px`,
38
+ background: `conic-gradient(
39
+ from ${data.rotation}deg,
40
+ hsl(${colors[0]} / ${data.colors[0]?.opacity || 0.5}),
41
+ hsl(${colors[1] || colors[0]} / ${data.colors[1]?.opacity || 0.7}),
42
+ hsl(${colors[2] || colors[0]} / ${data.colors[2]?.opacity || 0.5}),
43
+ hsl(${colors[0]} / ${data.colors[1]?.opacity || 0.7}),
44
+ hsl(${colors[0]} / ${data.colors[0]?.opacity || 0.5})
45
+ )`,
46
+ opacity: isPlaying ? 1 : 0,
47
+ transition: 'all 0.08s ease-out',
48
+ }}
49
+ />
50
+
51
+ {/* Inner border */}
52
+ <div
53
+ className="absolute -inset-1 rounded-lg bg-background -z-10"
54
+ style={{ opacity: isPlaying ? 1 : 0, transition: 'opacity 0.1s' }}
55
+ />
56
+
57
+ {/* Bass pulse glow - reactive size */}
58
+ <div
59
+ className={cn('absolute rounded-2xl -z-10', blur)}
60
+ style={{
61
+ inset: `-${pulseInset}px`,
62
+ background: `radial-gradient(circle, hsl(${colors[0]} / 0.7) 0%, hsl(${colors[0]} / 0.3) 50%, transparent 70%)`,
63
+ opacity: isPlaying ? data.pulseOpacity : 0,
64
+ transform: `scale(${data.pulseScale})`,
65
+ transition: 'all 0.08s ease-out',
66
+ }}
67
+ />
68
+
69
+ {/* Outer ring glow */}
70
+ <div
71
+ className="absolute rounded-3xl -z-10 blur-2xl"
72
+ style={{
73
+ inset: `-${pulseInset + 30}px`,
74
+ background: `radial-gradient(circle, hsl(${colors[1] || colors[0]} / 0.4) 0%, transparent 60%)`,
75
+ opacity: isPlaying ? ringOpacity : 0,
76
+ transform: `scale(${ringScale})`,
77
+ transition: 'all 0.08s ease-out',
78
+ }}
79
+ />
80
+ </>
81
+ );
82
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * ReactiveCover effects - Audio-reactive visual effects
3
+ */
4
+
5
+ export { GlowEffect, type GlowEffectData } from './GlowEffect';
6
+ export { OrbsEffect } from './OrbsEffect';
7
+ export { SpotlightEffect } from './SpotlightEffect';
8
+ export { MeshEffect } from './MeshEffect';
@@ -0,0 +1,6 @@
1
+ /**
2
+ * ReactiveCover - Audio-reactive cover art component
3
+ */
4
+
5
+ export { AudioReactiveCover, type AudioReactiveCoverProps } from './AudioReactiveCover';
6
+ export { GlowEffect, OrbsEffect, SpotlightEffect, MeshEffect, type GlowEffectData } from './effects';
@@ -0,0 +1,280 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * SimpleAudioPlayer - Easy-to-use audio player wrapper
5
+ *
6
+ * Combines AudioProvider + AudioPlayer + optional reactive cover
7
+ * in a single component with sensible defaults.
8
+ *
9
+ * @example
10
+ * // Minimal usage
11
+ * <SimpleAudioPlayer src="https://example.com/audio.mp3" />
12
+ *
13
+ * @example
14
+ * // With cover art
15
+ * <SimpleAudioPlayer
16
+ * src={audioUrl}
17
+ * title="Track Title"
18
+ * artist="Artist Name"
19
+ * coverArt="/path/to/cover.jpg"
20
+ * />
21
+ *
22
+ * @example
23
+ * // Full customization
24
+ * <SimpleAudioPlayer
25
+ * src={audioUrl}
26
+ * title="Track Title"
27
+ * coverArt={coverUrl}
28
+ * showWaveform
29
+ * showEqualizer={false}
30
+ * reactiveCover
31
+ * variant="spotlight"
32
+ * autoPlay={false}
33
+ * />
34
+ */
35
+
36
+ import { useRef, type ReactNode } from 'react';
37
+ import { Music } from 'lucide-react';
38
+ import { cn } from '@djangocfg/ui-core';
39
+
40
+ import { AudioProvider } from '../context';
41
+ import { AudioPlayer } from './AudioPlayer';
42
+ import { AudioReactiveCover } from './ReactiveCover';
43
+ import { VisualizationProvider, useVisualization } from '../hooks';
44
+ import type { WaveformOptions, EqualizerOptions } from '../types';
45
+ import type { EffectIntensity, EffectColorScheme } from '../effects';
46
+ import type { VisualizationVariant } from '../hooks';
47
+
48
+ // =============================================================================
49
+ // TYPES
50
+ // =============================================================================
51
+
52
+ export interface SimpleAudioPlayerProps {
53
+ /** Audio source URL */
54
+ src: string;
55
+
56
+ /** Track title */
57
+ title?: string;
58
+
59
+ /** Artist name */
60
+ artist?: string;
61
+
62
+ /** Cover art URL or ReactNode */
63
+ coverArt?: string | ReactNode;
64
+
65
+ /** Cover art size */
66
+ coverSize?: 'sm' | 'md' | 'lg';
67
+
68
+ /** Show waveform visualization */
69
+ showWaveform?: boolean;
70
+
71
+ /** Show equalizer bars */
72
+ showEqualizer?: boolean;
73
+
74
+ /** Show timer */
75
+ showTimer?: boolean;
76
+
77
+ /** Show volume control */
78
+ showVolume?: boolean;
79
+
80
+ /** Show loop/repeat button */
81
+ showLoop?: boolean;
82
+
83
+ /** Enable audio-reactive cover effects */
84
+ reactiveCover?: boolean;
85
+
86
+ /** Reactive effect variant */
87
+ variant?: VisualizationVariant;
88
+
89
+ /** Reactive effect intensity */
90
+ intensity?: EffectIntensity;
91
+
92
+ /** Reactive effect color scheme */
93
+ colorScheme?: EffectColorScheme;
94
+
95
+ /** Auto-play on load */
96
+ autoPlay?: boolean;
97
+
98
+ /** Waveform customization */
99
+ waveformOptions?: WaveformOptions;
100
+
101
+ /** Equalizer customization */
102
+ equalizerOptions?: EqualizerOptions;
103
+
104
+ /** Layout direction */
105
+ layout?: 'vertical' | 'horizontal';
106
+
107
+ /** Additional class name */
108
+ className?: string;
109
+ }
110
+
111
+ // =============================================================================
112
+ // CONSTANTS
113
+ // =============================================================================
114
+
115
+ const COVER_SIZES = {
116
+ sm: 'w-24 h-24',
117
+ md: 'w-32 h-32',
118
+ lg: 'w-48 h-48',
119
+ };
120
+
121
+ // =============================================================================
122
+ // COMPONENT
123
+ // =============================================================================
124
+
125
+ export function SimpleAudioPlayer(props: SimpleAudioPlayerProps) {
126
+ return (
127
+ <VisualizationProvider>
128
+ <SimpleAudioPlayerContent {...props} />
129
+ </VisualizationProvider>
130
+ );
131
+ }
132
+
133
+ function SimpleAudioPlayerContent({
134
+ src,
135
+ title,
136
+ artist,
137
+ coverArt,
138
+ coverSize = 'md',
139
+ showWaveform = true,
140
+ showEqualizer = false,
141
+ showTimer = true,
142
+ showVolume = true,
143
+ showLoop = true,
144
+ reactiveCover = true,
145
+ variant,
146
+ intensity,
147
+ colorScheme,
148
+ autoPlay = false,
149
+ waveformOptions,
150
+ equalizerOptions,
151
+ layout = 'vertical',
152
+ className,
153
+ }: SimpleAudioPlayerProps) {
154
+ const containerRef = useRef<HTMLDivElement>(null);
155
+ const { settings: vizSettings, nextVariant } = useVisualization();
156
+
157
+ // Determine effective variant (from props or localStorage settings)
158
+ const effectiveVariant = variant ?? (vizSettings.variant !== 'none' ? vizSettings.variant : 'spotlight');
159
+ const effectiveIntensity = intensity ?? vizSettings.intensity;
160
+ const effectiveColorScheme = colorScheme ?? vizSettings.colorScheme;
161
+
162
+ // Show reactive cover if enabled and variant is not 'none'
163
+ const showReactiveCover = reactiveCover && effectiveVariant !== 'none';
164
+
165
+ // Render cover art content
166
+ const renderCoverContent = () => {
167
+ if (typeof coverArt === 'string') {
168
+ return (
169
+ <img
170
+ src={coverArt}
171
+ alt={title || 'Album cover'}
172
+ className="w-full h-full object-cover"
173
+ />
174
+ );
175
+ }
176
+
177
+ if (coverArt) {
178
+ return coverArt;
179
+ }
180
+
181
+ // Default placeholder
182
+ return (
183
+ <div className="w-full h-full bg-muted/30 flex items-center justify-center">
184
+ <Music className="w-1/3 h-1/3 text-muted-foreground/50" />
185
+ </div>
186
+ );
187
+ };
188
+
189
+ const isHorizontal = layout === 'horizontal';
190
+
191
+ return (
192
+ <AudioProvider
193
+ source={{ uri: src }}
194
+ containerRef={containerRef}
195
+ autoPlay={autoPlay}
196
+ waveformOptions={waveformOptions}
197
+ >
198
+ <div
199
+ className={cn(
200
+ 'flex gap-4',
201
+ isHorizontal ? 'flex-row items-center' : 'flex-col items-center',
202
+ className
203
+ )}
204
+ >
205
+ {/* Cover Art */}
206
+ {(coverArt || reactiveCover) && (
207
+ <div className="flex flex-col items-center gap-2 shrink-0">
208
+ {showReactiveCover ? (
209
+ <AudioReactiveCover
210
+ size={coverSize}
211
+ variant={effectiveVariant as 'glow' | 'orbs' | 'spotlight' | 'mesh'}
212
+ intensity={effectiveIntensity}
213
+ colorScheme={effectiveColorScheme}
214
+ onClick={nextVariant}
215
+ >
216
+ <div className={cn('rounded-lg overflow-hidden', COVER_SIZES[coverSize])}>
217
+ {renderCoverContent()}
218
+ </div>
219
+ </AudioReactiveCover>
220
+ ) : (
221
+ <div
222
+ className={cn(
223
+ 'rounded-lg overflow-hidden shadow-lg cursor-pointer',
224
+ COVER_SIZES[coverSize]
225
+ )}
226
+ onClick={nextVariant}
227
+ role="button"
228
+ tabIndex={0}
229
+ onKeyDown={(e) => e.key === 'Enter' && nextVariant()}
230
+ >
231
+ {renderCoverContent()}
232
+ </div>
233
+ )}
234
+
235
+ {/* Effect indicator */}
236
+ {reactiveCover && (
237
+ <span className="text-[10px] uppercase tracking-wider text-muted-foreground/50 select-none">
238
+ {vizSettings.variant === 'none' ? 'off' : vizSettings.variant}
239
+ </span>
240
+ )}
241
+ </div>
242
+ )}
243
+
244
+ {/* Track Info + Player */}
245
+ <div className={cn('flex flex-col gap-3', isHorizontal ? 'flex-1 min-w-0' : 'w-full max-w-md')}>
246
+ {/* Track Info */}
247
+ {(title || artist) && (
248
+ <div className={cn('text-center', isHorizontal && 'text-left')}>
249
+ {title && (
250
+ <h3 className="text-base font-medium text-foreground truncate">
251
+ {title}
252
+ </h3>
253
+ )}
254
+ {artist && (
255
+ <p className="text-sm text-muted-foreground truncate">
256
+ {artist}
257
+ </p>
258
+ )}
259
+ </div>
260
+ )}
261
+
262
+ {/* Audio Player */}
263
+ <AudioPlayer
264
+ ref={containerRef}
265
+ showControls
266
+ showWaveform={showWaveform}
267
+ showEqualizer={showEqualizer}
268
+ showTimer={showTimer}
269
+ showVolume={showVolume}
270
+ showLoop={showLoop}
271
+ equalizerOptions={equalizerOptions}
272
+ className="border-0 bg-transparent"
273
+ />
274
+ </div>
275
+ </div>
276
+ </AudioProvider>
277
+ );
278
+ }
279
+
280
+ export default SimpleAudioPlayer;
@@ -0,0 +1,64 @@
1
+ 'use client';
2
+
3
+ /**
4
+ * VisualizationToggle - Simple toggle for audio visualization settings
5
+ *
6
+ * Click: cycle through variants
7
+ * Long press / right click: opens menu (future)
8
+ */
9
+
10
+ import { Sparkles } from 'lucide-react';
11
+ import { Button, cn } from '@djangocfg/ui-nextjs';
12
+ import { useVisualization, VARIANT_INFO } from '../hooks';
13
+
14
+ // =============================================================================
15
+ // TYPES
16
+ // =============================================================================
17
+
18
+ export interface VisualizationToggleProps {
19
+ /** Compact mode (icon only) */
20
+ compact?: boolean;
21
+ /** Additional class name */
22
+ className?: string;
23
+ }
24
+
25
+ // =============================================================================
26
+ // COMPONENT
27
+ // =============================================================================
28
+
29
+ export function VisualizationToggle({
30
+ compact = false,
31
+ className,
32
+ }: VisualizationToggleProps) {
33
+ const { settings, nextVariant } = useVisualization();
34
+
35
+ const currentInfo = VARIANT_INFO[settings.variant];
36
+ const isEnabled = settings.variant !== 'none';
37
+
38
+ return (
39
+ <Button
40
+ variant={isEnabled ? 'secondary' : 'ghost'}
41
+ size={compact ? 'icon' : 'sm'}
42
+ className={cn(
43
+ 'transition-all',
44
+ isEnabled && 'bg-primary/10 text-primary hover:bg-primary/20',
45
+ className
46
+ )}
47
+ onClick={nextVariant}
48
+ title={`Visualization: ${currentInfo.label} (click to change)`}
49
+ >
50
+ <Sparkles
51
+ className={cn(
52
+ 'h-4 w-4',
53
+ isEnabled && 'text-primary',
54
+ !compact && 'mr-1.5'
55
+ )}
56
+ />
57
+ {!compact && (
58
+ <span className="text-xs">{currentInfo.label}</span>
59
+ )}
60
+ </Button>
61
+ );
62
+ }
63
+
64
+ export default VisualizationToggle;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * AudioPlayer components - Public API
3
+ */
4
+
5
+ // Main components
6
+ export { AudioPlayer } from './AudioPlayer';
7
+ export { SimpleAudioPlayer, type SimpleAudioPlayerProps } from './SimpleAudioPlayer';
8
+ export { AudioEqualizer } from './AudioEqualizer';
9
+ export { AudioShortcutsPopover } from './AudioShortcutsPopover';
10
+ export { VisualizationToggle, type VisualizationToggleProps } from './VisualizationToggle';
11
+
12
+ // ReactiveCover
13
+ export {
14
+ AudioReactiveCover,
15
+ type AudioReactiveCoverProps,
16
+ GlowEffect,
17
+ OrbsEffect,
18
+ SpotlightEffect,
19
+ MeshEffect,
20
+ type GlowEffectData,
21
+ } from './ReactiveCover';