@frequencyads/components 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.
package/dist/index.mjs ADDED
@@ -0,0 +1,1529 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
32
+
33
+ // src/AnimatedCounter/AnimatedCounter.tsx
34
+ import { useEffect, useRef, useState } from "react";
35
+ import { Text } from "@mantine/core";
36
+ import { jsxs } from "react/jsx-runtime";
37
+ function AnimatedCounter(_a) {
38
+ var _b = _a, {
39
+ value,
40
+ suffix = "",
41
+ prefix = "",
42
+ duration = 2e3,
43
+ threshold = 0.5,
44
+ abbreviate = true,
45
+ decimals
46
+ } = _b, textProps = __objRest(_b, [
47
+ "value",
48
+ "suffix",
49
+ "prefix",
50
+ "duration",
51
+ "threshold",
52
+ "abbreviate",
53
+ "decimals"
54
+ ]);
55
+ const [count, setCount] = useState(0);
56
+ const [hasTriggered, setHasTriggered] = useState(false);
57
+ const ref = useRef(null);
58
+ useEffect(() => {
59
+ const el = ref.current;
60
+ if (!el) return;
61
+ const observer = new IntersectionObserver(
62
+ ([entry]) => {
63
+ if (entry.isIntersecting && !hasTriggered) {
64
+ setHasTriggered(true);
65
+ }
66
+ },
67
+ { threshold }
68
+ );
69
+ observer.observe(el);
70
+ return () => observer.disconnect();
71
+ }, [hasTriggered, threshold]);
72
+ useEffect(() => {
73
+ if (!hasTriggered) return;
74
+ let startTime;
75
+ let raf;
76
+ const animate = (timestamp) => {
77
+ if (!startTime) startTime = timestamp;
78
+ const progress = Math.min((timestamp - startTime) / duration, 1);
79
+ const eased = 1 - Math.pow(1 - progress, 3);
80
+ setCount(eased * value);
81
+ if (progress < 1) {
82
+ raf = requestAnimationFrame(animate);
83
+ }
84
+ };
85
+ raf = requestAnimationFrame(animate);
86
+ return () => cancelAnimationFrame(raf);
87
+ }, [hasTriggered, value, duration]);
88
+ const formatValue = () => {
89
+ if (abbreviate && value >= 1e3) {
90
+ const kValue = count / 1e3;
91
+ return kValue % 1 === 0 ? `${Math.round(kValue)}K` : `${kValue.toFixed(1)}K`;
92
+ }
93
+ if (decimals !== void 0) {
94
+ return count.toFixed(decimals);
95
+ }
96
+ if (value !== Math.floor(value)) {
97
+ return count.toFixed(1);
98
+ }
99
+ return Math.round(count).toString();
100
+ };
101
+ return /* @__PURE__ */ jsxs(
102
+ Text,
103
+ __spreadProps(__spreadValues({
104
+ component: "span",
105
+ ref,
106
+ style: { fontVariantNumeric: "tabular-nums" }
107
+ }, textProps), {
108
+ children: [
109
+ prefix,
110
+ formatValue(),
111
+ suffix
112
+ ]
113
+ })
114
+ );
115
+ }
116
+
117
+ // src/AnimatedWaveform/AnimatedWaveform.tsx
118
+ import { useEffect as useEffect2, useState as useState2 } from "react";
119
+ import { motion } from "framer-motion";
120
+
121
+ // src/AnimatedWaveform/AnimatedWaveform.module.css
122
+ var AnimatedWaveform_default = {};
123
+
124
+ // src/AnimatedWaveform/AnimatedWaveform.tsx
125
+ import { jsx, jsxs as jsxs2 } from "react/jsx-runtime";
126
+ var BAR_COUNT = 140;
127
+ var BAR_WIDTH = 3;
128
+ var BAR_GAP = 10;
129
+ var VIEW_HEIGHT = 150;
130
+ var MIDLINE = VIEW_HEIGHT / 2;
131
+ function AnimatedWaveform({
132
+ barCount = BAR_COUNT,
133
+ duration = 3,
134
+ repeatDelay = 3
135
+ }) {
136
+ const [mounted, setMounted] = useState2(false);
137
+ useEffect2(() => {
138
+ setMounted(true);
139
+ }, []);
140
+ if (!mounted) return null;
141
+ const viewWidth = barCount * BAR_GAP;
142
+ return /* @__PURE__ */ jsx("div", { className: AnimatedWaveform_default.root, children: /* @__PURE__ */ jsxs2(
143
+ "svg",
144
+ {
145
+ className: AnimatedWaveform_default.svg,
146
+ viewBox: `0 0 ${viewWidth} ${VIEW_HEIGHT}`,
147
+ preserveAspectRatio: "none",
148
+ children: [
149
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs2("linearGradient", { id: "waveformBarGradient", x1: "0%", y1: "0%", x2: "100%", y2: "0%", children: [
150
+ /* @__PURE__ */ jsx("stop", { offset: "0%", stopColor: "white", stopOpacity: "0" }),
151
+ /* @__PURE__ */ jsx("stop", { offset: "15%", stopColor: "white", stopOpacity: "0.15" }),
152
+ /* @__PURE__ */ jsx("stop", { offset: "50%", stopColor: "white", stopOpacity: "0.25" }),
153
+ /* @__PURE__ */ jsx("stop", { offset: "85%", stopColor: "white", stopOpacity: "0.15" }),
154
+ /* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: "white", stopOpacity: "0" })
155
+ ] }) }),
156
+ [...Array(barCount)].map((_, i) => {
157
+ const x = i * BAR_GAP;
158
+ const baseHeight = 18 + Math.sin(i * 0.4) * 6 + Math.cos(i * 0.7) * 4;
159
+ const staggerDelay = Math.min(i, barCount - 1 - i) * 0.04;
160
+ return /* @__PURE__ */ jsxs2("g", { children: [
161
+ /* @__PURE__ */ jsx(
162
+ motion.rect,
163
+ {
164
+ x,
165
+ width: BAR_WIDTH,
166
+ rx: "1.5",
167
+ fill: "url(#waveformBarGradient)",
168
+ initial: { height: baseHeight / 2, y: MIDLINE - baseHeight / 4 },
169
+ animate: {
170
+ height: [baseHeight / 2, baseHeight * 2, baseHeight / 2, baseHeight * 1.2, baseHeight / 2],
171
+ y: [
172
+ MIDLINE - baseHeight / 4,
173
+ MIDLINE - baseHeight,
174
+ MIDLINE - baseHeight / 4,
175
+ MIDLINE - baseHeight * 0.6,
176
+ MIDLINE - baseHeight / 4
177
+ ]
178
+ },
179
+ transition: {
180
+ duration,
181
+ repeat: Infinity,
182
+ ease: "easeInOut",
183
+ delay: staggerDelay,
184
+ repeatDelay
185
+ }
186
+ }
187
+ ),
188
+ /* @__PURE__ */ jsx(
189
+ motion.rect,
190
+ {
191
+ x,
192
+ y: MIDLINE,
193
+ width: BAR_WIDTH,
194
+ rx: "1.5",
195
+ fill: "url(#waveformBarGradient)",
196
+ initial: { height: baseHeight / 2 },
197
+ animate: {
198
+ height: [baseHeight / 2, baseHeight * 2, baseHeight / 2, baseHeight * 1.2, baseHeight / 2]
199
+ },
200
+ transition: {
201
+ duration,
202
+ repeat: Infinity,
203
+ ease: "easeInOut",
204
+ delay: staggerDelay,
205
+ repeatDelay
206
+ }
207
+ }
208
+ )
209
+ ] }, i);
210
+ })
211
+ ]
212
+ }
213
+ ) });
214
+ }
215
+
216
+ // src/AudioPlayer/AudioPlayer.tsx
217
+ import { useRef as useRef3, useState as useState4, useEffect as useEffect4, useCallback as useCallback2 } from "react";
218
+ import { ActionIcon, Group, Text as Text2, Slider, Box as Box2 } from "@mantine/core";
219
+ import {
220
+ IconPlayerPlayFilled,
221
+ IconPlayerPauseFilled,
222
+ IconVolume,
223
+ IconVolumeOff,
224
+ IconDownload
225
+ } from "@tabler/icons-react";
226
+
227
+ // src/AudioWaveform/AudioWaveform.tsx
228
+ import { useRef as useRef2, useImperativeHandle, forwardRef, useEffect as useEffect3, useState as useState3, useCallback } from "react";
229
+ import { Box } from "@mantine/core";
230
+
231
+ // src/AudioWaveform/AudioWaveform.module.css
232
+ var AudioWaveform_default = {};
233
+
234
+ // src/AudioWaveform/AudioWaveform.tsx
235
+ import { jsx as jsx2, jsxs as jsxs3 } from "react/jsx-runtime";
236
+ function generateWaveformData(barCount = 100) {
237
+ const data = [];
238
+ for (let i = 0; i < barCount; i++) {
239
+ const progress = i / (barCount - 1);
240
+ const baseHeight = 20 + Math.sin(i * 0.1) * 15;
241
+ const noise = (Math.random() - 0.5) * 20;
242
+ const envelope = Math.sin(progress * Math.PI) * 30;
243
+ const midBoost = progress > 0.2 && progress < 0.8 ? Math.random() * 10 : 0;
244
+ const endTaper = progress < 0.05 || progress > 0.95 ? Math.min(progress / 0.05, (1 - progress) / 0.05) : 1;
245
+ data.push(Math.max(5, Math.min(90, (baseHeight + noise + envelope + midBoost) * endTaper)));
246
+ }
247
+ return data;
248
+ }
249
+ var AudioWaveform = forwardRef(
250
+ ({
251
+ audioRef,
252
+ currentTime = 0,
253
+ onSeek,
254
+ loading = false,
255
+ waveColor = "#CCCCCC",
256
+ progressColor = "#169bde",
257
+ height = 60,
258
+ barWidth = 2,
259
+ barGap = 1
260
+ }, ref) => {
261
+ const containerRef = useRef2(null);
262
+ const [waveformData] = useState3(() => generateWaveformData());
263
+ const [duration, setDuration] = useState3(0);
264
+ const [progress, setProgress] = useState3(0);
265
+ useImperativeHandle(ref, () => ({
266
+ seekTo: (time) => {
267
+ if (duration > 0) {
268
+ setProgress(Math.max(0, Math.min(100, time / duration * 100)));
269
+ }
270
+ },
271
+ getCurrentTime: () => progress / 100 * duration,
272
+ getDuration: () => duration
273
+ }));
274
+ useEffect3(() => {
275
+ const audio = audioRef.current;
276
+ if (!audio) return;
277
+ const handleMeta = () => {
278
+ if (audio.duration && !isNaN(audio.duration)) setDuration(audio.duration);
279
+ };
280
+ const handleTime = () => {
281
+ if (audio.duration > 0) setProgress(audio.currentTime / audio.duration * 100);
282
+ };
283
+ if (audio.duration && !isNaN(audio.duration)) setDuration(audio.duration);
284
+ audio.addEventListener("loadedmetadata", handleMeta);
285
+ audio.addEventListener("timeupdate", handleTime);
286
+ return () => {
287
+ audio.removeEventListener("loadedmetadata", handleMeta);
288
+ audio.removeEventListener("timeupdate", handleTime);
289
+ };
290
+ }, [audioRef]);
291
+ useEffect3(() => {
292
+ if (duration > 0 && typeof currentTime === "number") {
293
+ setProgress(currentTime / duration * 100);
294
+ }
295
+ }, [currentTime, duration]);
296
+ const handleClick = useCallback(
297
+ (e) => {
298
+ if (!containerRef.current || !onSeek || duration === 0) return;
299
+ const rect = containerRef.current.getBoundingClientRect();
300
+ const seekTime = (e.clientX - rect.left) / rect.width * duration;
301
+ onSeek(seekTime);
302
+ },
303
+ [onSeek, duration]
304
+ );
305
+ return /* @__PURE__ */ jsxs3(
306
+ Box,
307
+ {
308
+ ref: containerRef,
309
+ className: AudioWaveform_default.root,
310
+ style: { height },
311
+ onClick: handleClick,
312
+ children: [
313
+ /* @__PURE__ */ jsx2(
314
+ "div",
315
+ {
316
+ className: AudioWaveform_default.progressOverlay,
317
+ style: { width: `${progress}%`, backgroundColor: `${progressColor}15` }
318
+ }
319
+ ),
320
+ /* @__PURE__ */ jsx2("div", { className: AudioWaveform_default.bars, style: { gap: barGap }, children: waveformData.map((barHeight, i) => {
321
+ const isActive = i / waveformData.length * 100 <= progress;
322
+ return /* @__PURE__ */ jsx2(
323
+ "div",
324
+ {
325
+ className: AudioWaveform_default.bar,
326
+ style: {
327
+ width: barWidth,
328
+ height: `${barHeight}%`,
329
+ backgroundColor: isActive ? progressColor : waveColor
330
+ }
331
+ },
332
+ i
333
+ );
334
+ }) }),
335
+ loading && /* @__PURE__ */ jsx2("div", { className: AudioWaveform_default.loading, children: "Loading waveform..." })
336
+ ]
337
+ }
338
+ );
339
+ }
340
+ );
341
+ AudioWaveform.displayName = "AudioWaveform";
342
+
343
+ // src/AudioPlayer/AudioPlayer.module.css
344
+ var AudioPlayer_default = {};
345
+
346
+ // src/AudioPlayer/AudioPlayer.tsx
347
+ import { jsx as jsx3, jsxs as jsxs4 } from "react/jsx-runtime";
348
+ function formatTime(seconds) {
349
+ const m = Math.floor(seconds / 60);
350
+ const s = Math.floor(seconds % 60);
351
+ return `${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
352
+ }
353
+ function AudioPlayer({
354
+ src,
355
+ filename = "audio",
356
+ playButtonColor,
357
+ playButtonSize = 32,
358
+ waveColor = "#D0D0D0",
359
+ progressColor = "#a8a8a8",
360
+ waveHeight = 64,
361
+ barWidth = 3,
362
+ barGap = 2,
363
+ showVolume = true,
364
+ showDownload = true
365
+ }) {
366
+ const audioRef = useRef3(null);
367
+ const [isPlaying, setIsPlaying] = useState4(false);
368
+ const [currentTime, setCurrentTime] = useState4(0);
369
+ const [currentTimeFormatted, setCurrentTimeFormatted] = useState4("00:00");
370
+ const [totalDuration, setTotalDuration] = useState4("00:00");
371
+ const [volume, setVolume] = useState4(50);
372
+ const [prevVolume, setPrevVolume] = useState4(50);
373
+ const [isMuted, setIsMuted] = useState4(false);
374
+ useEffect4(() => {
375
+ const audio = audioRef.current;
376
+ if (!audio) return;
377
+ audio.volume = volume / 100;
378
+ const handleTimeUpdate = () => {
379
+ setCurrentTime(audio.currentTime);
380
+ setCurrentTimeFormatted(formatTime(audio.currentTime));
381
+ };
382
+ const handleMeta = () => setTotalDuration(formatTime(audio.duration));
383
+ const handleEnded = () => {
384
+ setTimeout(() => {
385
+ setCurrentTime(0);
386
+ setCurrentTimeFormatted("00:00");
387
+ setIsPlaying(false);
388
+ }, 500);
389
+ };
390
+ const handlePlay = () => setIsPlaying(true);
391
+ const handlePause = () => setIsPlaying(false);
392
+ audio.addEventListener("timeupdate", handleTimeUpdate);
393
+ audio.addEventListener("loadedmetadata", handleMeta);
394
+ audio.addEventListener("ended", handleEnded);
395
+ audio.addEventListener("play", handlePlay);
396
+ audio.addEventListener("pause", handlePause);
397
+ return () => {
398
+ audio.removeEventListener("timeupdate", handleTimeUpdate);
399
+ audio.removeEventListener("loadedmetadata", handleMeta);
400
+ audio.removeEventListener("ended", handleEnded);
401
+ audio.removeEventListener("play", handlePlay);
402
+ audio.removeEventListener("pause", handlePause);
403
+ };
404
+ }, [src]);
405
+ const togglePlay = useCallback2(() => {
406
+ const audio = audioRef.current;
407
+ if (!audio) return;
408
+ if (isPlaying) {
409
+ audio.pause();
410
+ } else {
411
+ audio.play().catch(() => {
412
+ });
413
+ }
414
+ }, [isPlaying]);
415
+ const handleSeek = useCallback2((time) => {
416
+ const audio = audioRef.current;
417
+ if (audio && !isNaN(time) && isFinite(time)) {
418
+ audio.currentTime = time;
419
+ setCurrentTime(time);
420
+ setCurrentTimeFormatted(formatTime(time));
421
+ }
422
+ }, []);
423
+ const handleVolumeChange = useCallback2(
424
+ (value) => {
425
+ const audio = audioRef.current;
426
+ if (!audio) return;
427
+ audio.volume = value / 100;
428
+ setVolume(value);
429
+ if (value > 0) {
430
+ setPrevVolume(value);
431
+ setIsMuted(false);
432
+ } else {
433
+ setIsMuted(true);
434
+ }
435
+ },
436
+ []
437
+ );
438
+ const toggleMute = useCallback2(() => {
439
+ const audio = audioRef.current;
440
+ if (!audio) return;
441
+ if (isMuted) {
442
+ const restore = prevVolume || 50;
443
+ audio.volume = restore / 100;
444
+ setVolume(restore);
445
+ setIsMuted(false);
446
+ } else {
447
+ setPrevVolume(volume);
448
+ audio.volume = 0;
449
+ setVolume(0);
450
+ setIsMuted(true);
451
+ }
452
+ }, [isMuted, volume, prevVolume]);
453
+ const handleDownload = useCallback2(() => {
454
+ fetch(src).then((r) => r.blob()).then((blob) => {
455
+ const url = URL.createObjectURL(blob);
456
+ const a = document.createElement("a");
457
+ a.href = url;
458
+ a.download = filename;
459
+ document.body.appendChild(a);
460
+ a.click();
461
+ document.body.removeChild(a);
462
+ URL.revokeObjectURL(url);
463
+ }).catch(() => window.open(src, "_blank"));
464
+ }, [src, filename]);
465
+ return /* @__PURE__ */ jsxs4(Group, { gap: "sm", wrap: "nowrap", className: AudioPlayer_default.root, children: [
466
+ /* @__PURE__ */ jsx3("audio", { ref: audioRef, src, preload: "metadata" }),
467
+ /* @__PURE__ */ jsx3(
468
+ ActionIcon,
469
+ {
470
+ variant: "filled",
471
+ radius: "xl",
472
+ size: playButtonSize,
473
+ color: playButtonColor,
474
+ onClick: togglePlay,
475
+ "aria-label": isPlaying ? "Pause" : "Play",
476
+ className: AudioPlayer_default.playButton,
477
+ children: isPlaying ? /* @__PURE__ */ jsx3(IconPlayerPauseFilled, { size: playButtonSize * 0.5 }) : /* @__PURE__ */ jsx3(IconPlayerPlayFilled, { size: playButtonSize * 0.5 })
478
+ }
479
+ ),
480
+ /* @__PURE__ */ jsx3(Text2, { size: "xs", ff: "monospace", c: "dimmed", className: AudioPlayer_default.time, children: currentTimeFormatted }),
481
+ /* @__PURE__ */ jsx3(Box2, { style: { flex: 1, minWidth: 0 }, children: /* @__PURE__ */ jsx3(
482
+ AudioWaveform,
483
+ {
484
+ audioRef,
485
+ currentTime,
486
+ onSeek: handleSeek,
487
+ waveColor,
488
+ progressColor,
489
+ height: waveHeight,
490
+ barWidth,
491
+ barGap
492
+ }
493
+ ) }),
494
+ /* @__PURE__ */ jsx3(Text2, { size: "xs", ff: "monospace", c: "dimmed", className: AudioPlayer_default.time, children: totalDuration }),
495
+ showVolume && /* @__PURE__ */ jsxs4(Group, { gap: 4, wrap: "nowrap", className: AudioPlayer_default.volumeGroup, children: [
496
+ /* @__PURE__ */ jsx3(
497
+ ActionIcon,
498
+ {
499
+ variant: "subtle",
500
+ size: "sm",
501
+ onClick: toggleMute,
502
+ "aria-label": isMuted ? "Unmute" : "Mute",
503
+ children: isMuted ? /* @__PURE__ */ jsx3(IconVolumeOff, { size: 16 }) : /* @__PURE__ */ jsx3(IconVolume, { size: 16 })
504
+ }
505
+ ),
506
+ /* @__PURE__ */ jsx3(
507
+ Slider,
508
+ {
509
+ value: volume,
510
+ onChange: handleVolumeChange,
511
+ size: "xs",
512
+ w: 80,
513
+ "aria-label": "Volume"
514
+ }
515
+ )
516
+ ] }),
517
+ showDownload && /* @__PURE__ */ jsx3(ActionIcon, { variant: "subtle", size: "sm", onClick: handleDownload, "aria-label": "Download", children: /* @__PURE__ */ jsx3(IconDownload, { size: 16 }) })
518
+ ] });
519
+ }
520
+
521
+ // src/CodeBlock/CodeBlock.tsx
522
+ import { useState as useState5, useCallback as useCallback3 } from "react";
523
+ import { Box as Box3, Button, Group as Group2, Text as Text3 } from "@mantine/core";
524
+
525
+ // src/CodeBlock/CodeBlock.module.css
526
+ var CodeBlock_default = {};
527
+
528
+ // src/CodeBlock/CodeBlock.tsx
529
+ import { jsx as jsx4, jsxs as jsxs5 } from "react/jsx-runtime";
530
+ function CodeBlock({ code, filename, height = 384 }) {
531
+ const [copied, setCopied] = useState5(false);
532
+ const handleCopy = useCallback3(async () => {
533
+ try {
534
+ await navigator.clipboard.writeText(code);
535
+ setCopied(true);
536
+ setTimeout(() => setCopied(false), 2e3);
537
+ } catch (e) {
538
+ }
539
+ }, [code]);
540
+ return /* @__PURE__ */ jsxs5(Box3, { className: CodeBlock_default.root, children: [
541
+ /* @__PURE__ */ jsxs5(Group2, { justify: "space-between", mb: "xs", children: [
542
+ filename && /* @__PURE__ */ jsx4(Text3, { size: "sm", fw: 500, c: "dimmed", children: filename }),
543
+ /* @__PURE__ */ jsx4(
544
+ Button,
545
+ {
546
+ size: "xs",
547
+ radius: "md",
548
+ color: copied ? "green" : "blue",
549
+ onClick: handleCopy,
550
+ children: copied ? "Copied!" : "Copy"
551
+ }
552
+ )
553
+ ] }),
554
+ /* @__PURE__ */ jsx4(
555
+ "textarea",
556
+ {
557
+ readOnly: true,
558
+ value: code,
559
+ className: CodeBlock_default.textarea,
560
+ style: { height }
561
+ }
562
+ )
563
+ ] });
564
+ }
565
+
566
+ // src/ColorPalette/ColorPalette.tsx
567
+ import { SimpleGrid, Text as Text4, Title } from "@mantine/core";
568
+
569
+ // src/Copyable/Copyable.tsx
570
+ import { useState as useState6, useCallback as useCallback4 } from "react";
571
+ import { Notification, Portal } from "@mantine/core";
572
+
573
+ // src/Copyable/Copyable.module.css
574
+ var Copyable_default = {};
575
+
576
+ // src/Copyable/Copyable.tsx
577
+ import { Fragment, jsx as jsx5, jsxs as jsxs6 } from "react/jsx-runtime";
578
+ function Copyable({ value, children }) {
579
+ const [toast, setToast] = useState6(null);
580
+ const handleCopy = useCallback4(() => {
581
+ navigator.clipboard.writeText(value).then(() => {
582
+ setToast(`Copied ${value}`);
583
+ setTimeout(() => setToast(null), 1800);
584
+ });
585
+ }, [value]);
586
+ return /* @__PURE__ */ jsxs6(Fragment, { children: [
587
+ /* @__PURE__ */ jsx5(
588
+ "span",
589
+ {
590
+ onClick: handleCopy,
591
+ className: Copyable_default.root,
592
+ title: `Click to copy ${value}`,
593
+ children
594
+ }
595
+ ),
596
+ toast && /* @__PURE__ */ jsx5(Portal, { children: /* @__PURE__ */ jsx5(
597
+ Notification,
598
+ {
599
+ withCloseButton: false,
600
+ className: Copyable_default.toast,
601
+ color: "blue",
602
+ children: toast
603
+ }
604
+ ) })
605
+ ] });
606
+ }
607
+
608
+ // src/ColorPalette/ColorPalette.module.css
609
+ var ColorPalette_default = {};
610
+
611
+ // src/ColorPalette/ColorPalette.tsx
612
+ import { jsx as jsx6, jsxs as jsxs7 } from "react/jsx-runtime";
613
+ function ColorPalette({ name, shades, mainIndex = 5 }) {
614
+ return /* @__PURE__ */ jsxs7("div", { className: ColorPalette_default.root, children: [
615
+ /* @__PURE__ */ jsx6(Title, { order: 4, size: "lg", tt: "capitalize", mb: "xs", children: name }),
616
+ /* @__PURE__ */ jsx6(SimpleGrid, { cols: 10, spacing: 4, children: shades.map((hex, i) => /* @__PURE__ */ jsx6(Copyable, { value: hex, children: /* @__PURE__ */ jsxs7("div", { className: ColorPalette_default.shade, children: [
617
+ /* @__PURE__ */ jsx6(
618
+ "div",
619
+ {
620
+ className: `${ColorPalette_default.color} ${i === mainIndex ? ColorPalette_default.main : ""}`,
621
+ style: { backgroundColor: hex }
622
+ }
623
+ ),
624
+ /* @__PURE__ */ jsx6(Text4, { size: "xs", c: "dimmed", ta: "center", mt: 4, children: i }),
625
+ /* @__PURE__ */ jsx6(Text4, { size: "xs", c: "dimmed", ta: "center", ff: "monospace", children: hex })
626
+ ] }) }, i)) })
627
+ ] });
628
+ }
629
+
630
+ // src/ColorSwatch/ColorSwatch.tsx
631
+ import { Paper, Text as Text5 } from "@mantine/core";
632
+
633
+ // src/ColorSwatch/ColorSwatch.module.css
634
+ var ColorSwatch_default = {};
635
+
636
+ // src/ColorSwatch/ColorSwatch.tsx
637
+ import { jsx as jsx7, jsxs as jsxs8 } from "react/jsx-runtime";
638
+ function ColorSwatch({ name, hex, label }) {
639
+ return /* @__PURE__ */ jsx7(Copyable, { value: hex, children: /* @__PURE__ */ jsxs8(Paper, { className: ColorSwatch_default.root, shadow: "lg", radius: "md", withBorder: false, children: [
640
+ /* @__PURE__ */ jsx7("div", { className: ColorSwatch_default.preview, style: { backgroundColor: hex } }),
641
+ /* @__PURE__ */ jsxs8("div", { className: ColorSwatch_default.info, children: [
642
+ /* @__PURE__ */ jsx7(Text5, { fw: 600, size: "sm", children: name }),
643
+ /* @__PURE__ */ jsx7(Text5, { size: "xs", c: "dimmed", ff: "monospace", children: hex }),
644
+ label && /* @__PURE__ */ jsx7(Text5, { size: "xs", c: "dimmed", children: label })
645
+ ] })
646
+ ] }) });
647
+ }
648
+
649
+ // src/DosDonts/DosDonts.tsx
650
+ import { SimpleGrid as SimpleGrid2, Paper as Paper2, Text as Text6, Group as Group3 } from "@mantine/core";
651
+ import { IconCheck, IconX } from "@tabler/icons-react";
652
+
653
+ // src/DosDonts/DosDonts.module.css
654
+ var DosDonts_default = {};
655
+
656
+ // src/DosDonts/DosDonts.tsx
657
+ import { jsx as jsx8, jsxs as jsxs9 } from "react/jsx-runtime";
658
+ function DosDonts({ items }) {
659
+ return /* @__PURE__ */ jsx8("div", { className: DosDonts_default.root, children: items.map((item, i) => /* @__PURE__ */ jsxs9(SimpleGrid2, { cols: { base: 1, sm: 2 }, spacing: "md", children: [
660
+ /* @__PURE__ */ jsxs9(Paper2, { className: DosDonts_default.dont, p: "md", radius: "md", children: [
661
+ /* @__PURE__ */ jsxs9(Group3, { gap: 6, mb: 6, children: [
662
+ /* @__PURE__ */ jsx8(IconX, { size: 16, className: DosDonts_default.dontIcon }),
663
+ /* @__PURE__ */ jsx8(Text6, { size: "sm", fw: 600, className: DosDonts_default.dontLabel, children: "Don't" })
664
+ ] }),
665
+ /* @__PURE__ */ jsx8(Text6, { size: "sm", children: item.dont })
666
+ ] }),
667
+ /* @__PURE__ */ jsxs9(Paper2, { className: DosDonts_default.do, p: "md", radius: "md", children: [
668
+ /* @__PURE__ */ jsxs9(Group3, { gap: 6, mb: 6, children: [
669
+ /* @__PURE__ */ jsx8(IconCheck, { size: 16, className: DosDonts_default.doIcon }),
670
+ /* @__PURE__ */ jsx8(Text6, { size: "sm", fw: 600, className: DosDonts_default.doLabel, children: "Do" })
671
+ ] }),
672
+ /* @__PURE__ */ jsx8(Text6, { size: "sm", children: item.do })
673
+ ] })
674
+ ] }, i)) });
675
+ }
676
+
677
+ // src/ExpandableCard/ExpandableCard.tsx
678
+ import { useEffect as useEffect5, useRef as useRef4, useState as useState7 } from "react";
679
+ import { Paper as Paper3, Group as Group4, Stack, Text as Text7, ThemeIcon } from "@mantine/core";
680
+ import { motion as motion2 } from "framer-motion";
681
+
682
+ // src/ExpandableCard/ExpandableCard.module.css
683
+ var ExpandableCard_default = {};
684
+
685
+ // src/ExpandableCard/ExpandableCard.tsx
686
+ import { jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
687
+ function ExpandableCard({
688
+ title,
689
+ description,
690
+ expandedContent,
691
+ icon: Icon,
692
+ color = "blue",
693
+ iconSize = "lg",
694
+ collapsedHeight = 120,
695
+ threshold = 0.5,
696
+ delay = 300,
697
+ expanded: controlledExpanded,
698
+ onExpandedChange
699
+ }) {
700
+ const ref = useRef4(null);
701
+ const [internalExpanded, setInternalExpanded] = useState7(false);
702
+ const isControlled = controlledExpanded !== void 0;
703
+ const isExpanded = isControlled ? controlledExpanded : internalExpanded;
704
+ useEffect5(() => {
705
+ if (isControlled) return;
706
+ const el = ref.current;
707
+ if (!el) return;
708
+ const observer = new IntersectionObserver(
709
+ ([entry]) => {
710
+ if (entry.isIntersecting) {
711
+ setTimeout(() => {
712
+ setInternalExpanded(true);
713
+ onExpandedChange == null ? void 0 : onExpandedChange(true);
714
+ }, delay);
715
+ }
716
+ },
717
+ { threshold }
718
+ );
719
+ observer.observe(el);
720
+ return () => observer.disconnect();
721
+ }, [isControlled, threshold, delay, onExpandedChange]);
722
+ return /* @__PURE__ */ jsx9(
723
+ Paper3,
724
+ __spreadProps(__spreadValues({
725
+ ref,
726
+ radius: 4,
727
+ className: ExpandableCard_default.root,
728
+ component: motion2.div
729
+ }, {
730
+ animate: { height: isExpanded ? "auto" : collapsedHeight },
731
+ transition: { duration: 0.5, ease: "easeOut" }
732
+ }), {
733
+ children: /* @__PURE__ */ jsx9("div", { className: ExpandableCard_default.inner, children: /* @__PURE__ */ jsxs10(Group4, { align: "flex-start", justify: "space-between", gap: "lg", wrap: "nowrap", children: [
734
+ /* @__PURE__ */ jsxs10(Stack, { gap: "xs", style: { flex: 1 }, children: [
735
+ /* @__PURE__ */ jsx9(Text7, { fw: 700, size: "xl", lh: 1.3, children: title }),
736
+ /* @__PURE__ */ jsx9(Text7, { size: "md", c: "dimmed", children: description }),
737
+ /* @__PURE__ */ jsx9(
738
+ motion2.div,
739
+ {
740
+ initial: { opacity: 0, height: 0 },
741
+ animate: {
742
+ opacity: isExpanded ? 1 : 0,
743
+ height: isExpanded ? "auto" : 0
744
+ },
745
+ transition: { duration: 0.4, delay: 0.2 },
746
+ style: { overflow: "hidden" },
747
+ children: typeof expandedContent === "string" ? /* @__PURE__ */ jsx9(Text7, { size: "sm", c: "dimmed", mt: "sm", children: expandedContent }) : expandedContent
748
+ }
749
+ )
750
+ ] }),
751
+ /* @__PURE__ */ jsx9(
752
+ motion2.div,
753
+ {
754
+ animate: { scale: isExpanded ? 1.1 : 1 },
755
+ transition: { duration: 0.3 },
756
+ children: /* @__PURE__ */ jsx9(ThemeIcon, { size: iconSize, radius: 4, color, variant: "filled", children: /* @__PURE__ */ jsx9(Icon, { size: 20, stroke: 1.5 }) })
757
+ }
758
+ )
759
+ ] }) })
760
+ })
761
+ );
762
+ }
763
+
764
+ // src/FadeInSection/FadeInSection.tsx
765
+ import { useEffect as useEffect6, useRef as useRef5, useState as useState8 } from "react";
766
+ import { Box as Box4 } from "@mantine/core";
767
+
768
+ // src/FadeInSection/FadeInSection.module.css
769
+ var FadeInSection_default = {};
770
+
771
+ // src/FadeInSection/FadeInSection.tsx
772
+ import { jsx as jsx10 } from "react/jsx-runtime";
773
+ function FadeInSection(_a) {
774
+ var _b = _a, {
775
+ children,
776
+ delay = 0,
777
+ threshold = 0.1,
778
+ className
779
+ } = _b, props = __objRest(_b, [
780
+ "children",
781
+ "delay",
782
+ "threshold",
783
+ "className"
784
+ ]);
785
+ const ref = useRef5(null);
786
+ const [isVisible, setIsVisible] = useState8(false);
787
+ useEffect6(() => {
788
+ const el = ref.current;
789
+ if (!el) return;
790
+ const observer = new IntersectionObserver(
791
+ ([entry]) => {
792
+ if (entry.isIntersecting) {
793
+ if (delay > 0) {
794
+ setTimeout(() => setIsVisible(true), delay);
795
+ } else {
796
+ setIsVisible(true);
797
+ }
798
+ }
799
+ },
800
+ { threshold }
801
+ );
802
+ observer.observe(el);
803
+ return () => observer.disconnect();
804
+ }, [delay, threshold]);
805
+ return /* @__PURE__ */ jsx10(
806
+ Box4,
807
+ __spreadProps(__spreadValues({
808
+ ref,
809
+ className: `${FadeInSection_default.root} ${isVisible ? FadeInSection_default.visible : ""} ${className != null ? className : ""}`
810
+ }, props), {
811
+ children
812
+ })
813
+ );
814
+ }
815
+
816
+ // src/FrequencyWave/FrequencyWave.tsx
817
+ import { useEffect as useEffect7, useRef as useRef6, useState as useState9, useCallback as useCallback5 } from "react";
818
+ import { Box as Box5, useMantineColorScheme } from "@mantine/core";
819
+ import { jsx as jsx11 } from "react/jsx-runtime";
820
+ function FrequencyWave({ isActive = false, height = 60 }) {
821
+ const canvasRef = useRef6(null);
822
+ const animationRef = useRef6(void 0);
823
+ const [isPulsing, setIsPulsing] = useState9(false);
824
+ const lastPulseRef = useRef6(null);
825
+ const randomSpikeRef = useRef6(null);
826
+ const { colorScheme } = useMantineColorScheme();
827
+ const isDark = colorScheme === "dark";
828
+ const colors = {
829
+ start: isDark ? "#7950F2" : "#9775FA",
830
+ mid: isDark ? "#BE4BDB" : "#DA77F2",
831
+ end: isDark ? "#15AABF" : "#22B8CF"
832
+ };
833
+ const drawWave = useCallback5(
834
+ (ctx, width, canvasHeight, time) => {
835
+ var _a;
836
+ ctx.clearRect(0, 0, width, canvasHeight);
837
+ const isAnimating = isActive || isPulsing;
838
+ const waveY = canvasHeight * 0.65;
839
+ const baseAmplitude = isActive ? 5 : isPulsing ? 7 : 1.5;
840
+ if (isAnimating) {
841
+ if (randomSpikeRef.current === null) {
842
+ randomSpikeRef.current = Math.random();
843
+ }
844
+ if (Math.floor(time / 500) !== Math.floor((time - 16) / 500)) {
845
+ randomSpikeRef.current = Math.random();
846
+ }
847
+ }
848
+ const gradient = ctx.createLinearGradient(0, 0, width, 0);
849
+ gradient.addColorStop(0, colors.start);
850
+ gradient.addColorStop(0.5, colors.mid);
851
+ gradient.addColorStop(1, colors.end);
852
+ ctx.strokeStyle = gradient;
853
+ ctx.lineWidth = isAnimating ? 2.5 : 1.5;
854
+ ctx.lineCap = "round";
855
+ ctx.lineJoin = "round";
856
+ if (isAnimating) {
857
+ ctx.shadowColor = colors.mid;
858
+ ctx.shadowBlur = isPulsing ? 12 : 8;
859
+ } else {
860
+ ctx.shadowBlur = 0;
861
+ }
862
+ ctx.beginPath();
863
+ const segments = 300;
864
+ const segmentWidth = width / segments;
865
+ const speed = isActive ? 0.02 : isPulsing ? 0.025 : 3e-3;
866
+ for (let i = 0; i <= segments; i++) {
867
+ const x = i * segmentWidth;
868
+ const normalizedX = x / width;
869
+ let y = waveY;
870
+ if (isAnimating) {
871
+ const wave1 = Math.sin(normalizedX * Math.PI * 6 + time * speed) * baseAmplitude;
872
+ const wave2 = Math.sin(normalizedX * Math.PI * 12 + time * speed * 1.3) * (baseAmplitude * 0.4);
873
+ const wave3 = Math.sin(normalizedX * Math.PI * 18 + time * speed * 0.8) * (baseAmplitude * 0.2);
874
+ const spikePosition = (_a = randomSpikeRef.current) != null ? _a : 0.5;
875
+ const distToSpike = Math.abs(normalizedX - spikePosition);
876
+ const spikeAmplitude = distToSpike < 0.15 ? (1 - distToSpike / 0.15) * baseAmplitude * 1 : 0;
877
+ const spikeWave = Math.sin(normalizedX * Math.PI * 20 + time * speed * 2) * spikeAmplitude;
878
+ let aggressiveWave = 0;
879
+ if (isPulsing) {
880
+ aggressiveWave = Math.sin(normalizedX * Math.PI * 30 + time * 0.03) * baseAmplitude * 0.4;
881
+ aggressiveWave += Math.sin(normalizedX * Math.PI * 8 + time * 0.015) * baseAmplitude * 0.5;
882
+ }
883
+ const combinedWave = wave1 + wave2 + wave3 + spikeWave + aggressiveWave;
884
+ const envelope = Math.sin(normalizedX * Math.PI);
885
+ y = waveY + combinedWave * envelope;
886
+ } else {
887
+ y += Math.sin(normalizedX * Math.PI * 2 + time * speed) * baseAmplitude;
888
+ }
889
+ if (i === 0) {
890
+ ctx.moveTo(x, y);
891
+ } else {
892
+ ctx.lineTo(x, y);
893
+ }
894
+ }
895
+ ctx.stroke();
896
+ if (isActive) {
897
+ const barCount = 80;
898
+ const barWidth = 2;
899
+ const barGap = width / barCount;
900
+ const maxBarHeight = 16;
901
+ ctx.shadowBlur = 3;
902
+ for (let i = 0; i < barCount; i++) {
903
+ const x = i * barGap + barGap / 2;
904
+ const normalizedX = x / width;
905
+ const baseBarHeight = Math.sin(normalizedX * Math.PI * 8 + time * 0.025) * 0.5 + Math.sin(normalizedX * Math.PI * 14 + time * 0.018) * 0.3 + Math.sin(normalizedX * Math.PI * 4 + time * 0.03) * 0.2;
906
+ const envelope = Math.sin(normalizedX * Math.PI);
907
+ const barHeight = Math.abs(baseBarHeight) * maxBarHeight * envelope;
908
+ const barGradient = ctx.createLinearGradient(
909
+ x,
910
+ waveY - barHeight / 2,
911
+ x,
912
+ waveY + barHeight / 2
913
+ );
914
+ barGradient.addColorStop(0, colors.start + "90");
915
+ barGradient.addColorStop(0.5, colors.mid + "70");
916
+ barGradient.addColorStop(1, colors.end + "50");
917
+ ctx.fillStyle = barGradient;
918
+ ctx.fillRect(x - barWidth / 2, waveY - barHeight / 2, barWidth, barHeight);
919
+ }
920
+ }
921
+ if (isPulsing) {
922
+ const particleCount = 15;
923
+ for (let i = 0; i < particleCount; i++) {
924
+ const px = (Math.sin(time * 1e-3 + i * 1.5) * 0.5 + 0.5) * width;
925
+ const py = waveY + Math.sin(time * 2e-3 + i) * 8;
926
+ const radius = 1.5 + Math.sin(time * 3e-3 + i * 2) * 0.5;
927
+ ctx.beginPath();
928
+ ctx.arc(px, py, radius, 0, Math.PI * 2);
929
+ ctx.fillStyle = i % 2 === 0 ? colors.start + "80" : colors.end + "80";
930
+ ctx.fill();
931
+ }
932
+ }
933
+ },
934
+ [isActive, isPulsing, colors.start, colors.mid, colors.end]
935
+ );
936
+ useEffect7(() => {
937
+ const canvas = canvasRef.current;
938
+ if (!canvas) return;
939
+ const ctx = canvas.getContext("2d");
940
+ if (!ctx) return;
941
+ const updateSize = () => {
942
+ const dpr = window.devicePixelRatio || 1;
943
+ const rect = canvas.getBoundingClientRect();
944
+ canvas.width = rect.width * dpr;
945
+ canvas.height = rect.height * dpr;
946
+ ctx.scale(dpr, dpr);
947
+ };
948
+ updateSize();
949
+ window.addEventListener("resize", updateSize);
950
+ const startTime = performance.now();
951
+ const animate = (currentTime) => {
952
+ const elapsed = currentTime - startTime;
953
+ const rect = canvas.getBoundingClientRect();
954
+ drawWave(ctx, rect.width, rect.height, elapsed);
955
+ animationRef.current = requestAnimationFrame(animate);
956
+ };
957
+ animationRef.current = requestAnimationFrame(animate);
958
+ return () => {
959
+ window.removeEventListener("resize", updateSize);
960
+ if (animationRef.current) {
961
+ cancelAnimationFrame(animationRef.current);
962
+ }
963
+ };
964
+ }, [drawWave]);
965
+ useEffect7(() => {
966
+ if (isActive) {
967
+ queueMicrotask(() => setIsPulsing(false));
968
+ lastPulseRef.current = Date.now();
969
+ return;
970
+ }
971
+ const checkForPulse = () => {
972
+ const now = Date.now();
973
+ if (lastPulseRef.current === null) {
974
+ lastPulseRef.current = now;
975
+ }
976
+ const timeSinceLastPulse = now - lastPulseRef.current;
977
+ const pulseInterval = 12e4 + Math.random() * 6e4;
978
+ if (timeSinceLastPulse >= pulseInterval && !isPulsing) {
979
+ setIsPulsing(true);
980
+ lastPulseRef.current = now;
981
+ setTimeout(() => setIsPulsing(false), 4e3);
982
+ }
983
+ };
984
+ const intervalId = setInterval(checkForPulse, 5e3);
985
+ return () => clearInterval(intervalId);
986
+ }, [isActive, isPulsing]);
987
+ return /* @__PURE__ */ jsx11(
988
+ Box5,
989
+ {
990
+ style: {
991
+ position: "relative",
992
+ width: "100%",
993
+ height,
994
+ overflow: "hidden",
995
+ pointerEvents: "none",
996
+ opacity: isDark ? 1 : 0.8
997
+ },
998
+ children: /* @__PURE__ */ jsx11(
999
+ "canvas",
1000
+ {
1001
+ ref: canvasRef,
1002
+ style: {
1003
+ width: "100%",
1004
+ height: "100%",
1005
+ display: "block"
1006
+ }
1007
+ }
1008
+ )
1009
+ }
1010
+ );
1011
+ }
1012
+
1013
+ // src/GradientSwatch/GradientSwatch.tsx
1014
+ import { Paper as Paper4, Text as Text8 } from "@mantine/core";
1015
+
1016
+ // src/GradientSwatch/GradientSwatch.module.css
1017
+ var GradientSwatch_default = {};
1018
+
1019
+ // src/GradientSwatch/GradientSwatch.tsx
1020
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1021
+ function GradientSwatch({ name, colors, description }) {
1022
+ const css = `linear-gradient(135deg, ${colors[0]} 0%, ${colors[1]} 100%)`;
1023
+ return /* @__PURE__ */ jsx12(Copyable, { value: css, children: /* @__PURE__ */ jsxs11(Paper4, { className: GradientSwatch_default.root, shadow: "lg", radius: "md", children: [
1024
+ /* @__PURE__ */ jsx12("div", { className: GradientSwatch_default.preview, style: { background: css } }),
1025
+ /* @__PURE__ */ jsxs11("div", { className: GradientSwatch_default.info, children: [
1026
+ /* @__PURE__ */ jsx12(Text8, { fw: 600, size: "sm", children: name }),
1027
+ description && /* @__PURE__ */ jsx12(Text8, { size: "xs", c: "dimmed", children: description }),
1028
+ /* @__PURE__ */ jsxs11(Text8, { size: "xs", c: "dimmed", ff: "monospace", children: [
1029
+ colors[0],
1030
+ " \u2192 ",
1031
+ colors[1]
1032
+ ] })
1033
+ ] })
1034
+ ] }) });
1035
+ }
1036
+
1037
+ // src/Hero/Hero.tsx
1038
+ import {
1039
+ Box as Box6,
1040
+ Button as Button2,
1041
+ Group as Group5,
1042
+ Image,
1043
+ Stack as Stack2,
1044
+ Text as Text9,
1045
+ Title as Title2
1046
+ } from "@mantine/core";
1047
+ import defaultLogoSrc from "@frequencyads/brand/assets/frequency-mark-white.svg";
1048
+ import { gradients } from "@frequencyads/brand/colors";
1049
+
1050
+ // src/VideoBackground/VideoBackground.module.css
1051
+ var VideoBackground_default = {};
1052
+
1053
+ // src/VideoBackground/VideoBackground.tsx
1054
+ import { jsx as jsx13 } from "react/jsx-runtime";
1055
+ function VideoBackground({ src, opacity = 0.3 }) {
1056
+ return /* @__PURE__ */ jsx13(
1057
+ "video",
1058
+ {
1059
+ autoPlay: true,
1060
+ muted: true,
1061
+ loop: true,
1062
+ playsInline: true,
1063
+ className: VideoBackground_default.root,
1064
+ style: { opacity },
1065
+ children: /* @__PURE__ */ jsx13("source", { src, type: "video/mp4" })
1066
+ }
1067
+ );
1068
+ }
1069
+
1070
+ // src/Hero/Hero.module.css
1071
+ var Hero_default = {};
1072
+
1073
+ // src/Hero/Hero.tsx
1074
+ import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
1075
+ function Hero({
1076
+ variant = "logo",
1077
+ heading,
1078
+ tagline,
1079
+ logoSrc = defaultLogoSrc,
1080
+ gradient: gradientName = "frequencyAlive",
1081
+ shimmer = true,
1082
+ primaryAction,
1083
+ secondaryAction,
1084
+ backgroundVideoSrc,
1085
+ showWaveform
1086
+ }) {
1087
+ const resolvedHeading = heading != null ? heading : variant === "text" ? "Frequency" : void 0;
1088
+ const hasActions = primaryAction || secondaryAction;
1089
+ const waveformVisible = showWaveform != null ? showWaveform : true;
1090
+ const grad = gradients[gradientName];
1091
+ return /* @__PURE__ */ jsxs12(Box6, { className: Hero_default.root, children: [
1092
+ backgroundVideoSrc && /* @__PURE__ */ jsx14(VideoBackground, { src: backgroundVideoSrc }),
1093
+ /* @__PURE__ */ jsxs12(Stack2, { className: Hero_default.content, align: "center", gap: "lg", children: [
1094
+ variant === "logo" && /* @__PURE__ */ jsxs12("div", { className: Hero_default.logoWrapper, children: [
1095
+ waveformVisible && /* @__PURE__ */ jsx14(AnimatedWaveform, {}),
1096
+ waveformVisible && /* @__PURE__ */ jsx14("div", { className: Hero_default.vignette }),
1097
+ /* @__PURE__ */ jsx14(
1098
+ Image,
1099
+ {
1100
+ src: logoSrc,
1101
+ alt: resolvedHeading != null ? resolvedHeading : "Frequency",
1102
+ className: Hero_default.logo,
1103
+ fit: "contain"
1104
+ }
1105
+ ),
1106
+ /* @__PURE__ */ jsx14("div", { className: Hero_default.glow })
1107
+ ] }),
1108
+ variant === "text" && resolvedHeading && /* @__PURE__ */ jsxs12("div", { className: Hero_default.textWrapper, children: [
1109
+ waveformVisible && /* @__PURE__ */ jsx14(AnimatedWaveform, {}),
1110
+ waveformVisible && /* @__PURE__ */ jsx14("div", { className: Hero_default.vignette }),
1111
+ /* @__PURE__ */ jsx14(
1112
+ Title2,
1113
+ {
1114
+ order: 1,
1115
+ className: `${Hero_default.heading} ${shimmer ? Hero_default.shimmer : ""}`,
1116
+ style: {
1117
+ backgroundImage: `linear-gradient(135deg, ${grad.from}, ${grad.to}, ${grad.from})`,
1118
+ backgroundSize: shimmer ? "200% 100%" : void 0
1119
+ },
1120
+ children: resolvedHeading
1121
+ }
1122
+ )
1123
+ ] }),
1124
+ tagline && /* @__PURE__ */ jsx14(Text9, { className: Hero_default.tagline, children: tagline }),
1125
+ hasActions && /* @__PURE__ */ jsxs12(Group5, { gap: "md", justify: "center", wrap: "wrap", children: [
1126
+ primaryAction && /* @__PURE__ */ jsx14(
1127
+ Button2,
1128
+ {
1129
+ component: "a",
1130
+ href: primaryAction.href,
1131
+ size: "lg",
1132
+ radius: 4,
1133
+ className: Hero_default.primaryButton,
1134
+ children: primaryAction.label
1135
+ }
1136
+ ),
1137
+ secondaryAction && /* @__PURE__ */ jsx14(
1138
+ Button2,
1139
+ {
1140
+ component: "a",
1141
+ href: secondaryAction.href,
1142
+ size: "lg",
1143
+ radius: 4,
1144
+ variant: "outline",
1145
+ className: Hero_default.secondaryButton,
1146
+ children: secondaryAction.label
1147
+ }
1148
+ )
1149
+ ] })
1150
+ ] })
1151
+ ] });
1152
+ }
1153
+
1154
+ // src/HintBadge/HintBadge.tsx
1155
+ import { Badge } from "@mantine/core";
1156
+ import { jsxs as jsxs13 } from "react/jsx-runtime";
1157
+ function HintBadge({ variant, children }) {
1158
+ const isDo = variant === "do";
1159
+ return /* @__PURE__ */ jsxs13(
1160
+ Badge,
1161
+ {
1162
+ variant: "light",
1163
+ color: isDo ? "green" : "red",
1164
+ size: "lg",
1165
+ radius: "sm",
1166
+ styles: {
1167
+ root: { textTransform: "none", fontWeight: 400 },
1168
+ label: { whiteSpace: "normal", lineHeight: 1.4 }
1169
+ },
1170
+ children: [
1171
+ /* @__PURE__ */ jsxs13("strong", { children: [
1172
+ isDo ? "Do" : "Don't",
1173
+ ":"
1174
+ ] }),
1175
+ " ",
1176
+ children
1177
+ ]
1178
+ }
1179
+ );
1180
+ }
1181
+
1182
+ // src/MiniAudioPlayer/MiniAudioPlayer.tsx
1183
+ import { useRef as useRef7, useState as useState10, useEffect as useEffect8, forwardRef as forwardRef2, useCallback as useCallback6 } from "react";
1184
+ import { ActionIcon as ActionIcon2, Group as Group6, Box as Box7 } from "@mantine/core";
1185
+ import { IconPlayerPlayFilled as IconPlayerPlayFilled2, IconPlayerPauseFilled as IconPlayerPauseFilled2 } from "@tabler/icons-react";
1186
+
1187
+ // src/MiniAudioPlayer/MiniAudioPlayer.module.css
1188
+ var MiniAudioPlayer_default = {};
1189
+
1190
+ // src/MiniAudioPlayer/MiniAudioPlayer.tsx
1191
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
1192
+ var SIZE_CONFIG = {
1193
+ mini: { height: 24, buttonSize: 20, iconSize: 14, waveHeight: 16, barWidth: 1, barGap: 0 },
1194
+ small: { height: 32, buttonSize: 28, iconSize: 16, waveHeight: 20, barWidth: 1, barGap: 0 },
1195
+ compact: { height: 40, buttonSize: 32, iconSize: 18, waveHeight: 24, barWidth: 2, barGap: 1 }
1196
+ };
1197
+ var MiniAudioPlayer = forwardRef2(
1198
+ ({
1199
+ audioUrl,
1200
+ size = "mini",
1201
+ waveColor = "#CCCCCC",
1202
+ progressColor = "#169bde",
1203
+ onPlay,
1204
+ onPause,
1205
+ className,
1206
+ style
1207
+ }, ref) => {
1208
+ const audioRef = useRef7(null);
1209
+ const [isPlaying, setIsPlaying] = useState10(false);
1210
+ const [currentTime, setCurrentTime] = useState10(0);
1211
+ const config = SIZE_CONFIG[size];
1212
+ useEffect8(() => {
1213
+ const audio = audioRef.current;
1214
+ if (!audio) return;
1215
+ const handleTimeUpdate = () => setCurrentTime(audio.currentTime);
1216
+ const handleEnded = () => {
1217
+ setIsPlaying(false);
1218
+ setCurrentTime(0);
1219
+ };
1220
+ const handlePause = () => setIsPlaying(false);
1221
+ const handlePlay = () => setIsPlaying(true);
1222
+ audio.addEventListener("timeupdate", handleTimeUpdate);
1223
+ audio.addEventListener("ended", handleEnded);
1224
+ audio.addEventListener("pause", handlePause);
1225
+ audio.addEventListener("play", handlePlay);
1226
+ return () => {
1227
+ audio.removeEventListener("timeupdate", handleTimeUpdate);
1228
+ audio.removeEventListener("ended", handleEnded);
1229
+ audio.removeEventListener("pause", handlePause);
1230
+ audio.removeEventListener("play", handlePlay);
1231
+ };
1232
+ }, [audioUrl]);
1233
+ const handlePlayPause = useCallback6(() => {
1234
+ const audio = audioRef.current;
1235
+ if (!audio) return;
1236
+ if (isPlaying) {
1237
+ audio.pause();
1238
+ onPause == null ? void 0 : onPause();
1239
+ } else {
1240
+ audio.play().catch(() => {
1241
+ });
1242
+ onPlay == null ? void 0 : onPlay();
1243
+ }
1244
+ }, [isPlaying, onPlay, onPause]);
1245
+ const handleSeek = useCallback6((time) => {
1246
+ const audio = audioRef.current;
1247
+ if (audio && !isNaN(time) && isFinite(time)) {
1248
+ audio.currentTime = time;
1249
+ setCurrentTime(time);
1250
+ }
1251
+ }, []);
1252
+ return /* @__PURE__ */ jsxs14(
1253
+ Group6,
1254
+ {
1255
+ ref,
1256
+ gap: size === "mini" ? 6 : size === "small" ? 8 : 10,
1257
+ wrap: "nowrap",
1258
+ className: `${MiniAudioPlayer_default.root} ${className != null ? className : ""}`,
1259
+ style: __spreadValues({ height: config.height }, style),
1260
+ children: [
1261
+ /* @__PURE__ */ jsx15("audio", { ref: audioRef, src: audioUrl, preload: "metadata" }),
1262
+ /* @__PURE__ */ jsx15(
1263
+ ActionIcon2,
1264
+ {
1265
+ variant: "filled",
1266
+ color: "blue",
1267
+ radius: "xl",
1268
+ size: config.buttonSize,
1269
+ onClick: handlePlayPause,
1270
+ "aria-label": isPlaying ? "Pause" : "Play",
1271
+ className: MiniAudioPlayer_default.playButton,
1272
+ children: isPlaying ? /* @__PURE__ */ jsx15(IconPlayerPauseFilled2, { size: config.iconSize }) : /* @__PURE__ */ jsx15(IconPlayerPlayFilled2, { size: config.iconSize })
1273
+ }
1274
+ ),
1275
+ /* @__PURE__ */ jsx15(Box7, { style: { flex: 1, minWidth: 80 }, children: /* @__PURE__ */ jsx15(
1276
+ AudioWaveform,
1277
+ {
1278
+ audioRef,
1279
+ currentTime,
1280
+ onSeek: handleSeek,
1281
+ waveColor,
1282
+ progressColor,
1283
+ height: config.waveHeight,
1284
+ barWidth: config.barWidth,
1285
+ barGap: config.barGap
1286
+ }
1287
+ ) })
1288
+ ]
1289
+ }
1290
+ );
1291
+ }
1292
+ );
1293
+ MiniAudioPlayer.displayName = "MiniAudioPlayer";
1294
+
1295
+ // src/PrincipleCard/PrincipleCard.tsx
1296
+ import { Paper as Paper5, Title as Title3, Text as Text10, Group as Group7 } from "@mantine/core";
1297
+
1298
+ // src/PrincipleCard/PrincipleCard.module.css
1299
+ var PrincipleCard_default = {};
1300
+
1301
+ // src/PrincipleCard/PrincipleCard.tsx
1302
+ import { jsx as jsx16, jsxs as jsxs15 } from "react/jsx-runtime";
1303
+ function PrincipleCard({
1304
+ accentColor,
1305
+ title,
1306
+ description,
1307
+ doHint,
1308
+ dontHint
1309
+ }) {
1310
+ return /* @__PURE__ */ jsxs15(
1311
+ Paper5,
1312
+ {
1313
+ className: PrincipleCard_default.root,
1314
+ p: "lg",
1315
+ radius: "md",
1316
+ style: { borderLeftColor: accentColor },
1317
+ children: [
1318
+ /* @__PURE__ */ jsx16(Title3, { order: 3, size: "h4", mb: "xs", children: title }),
1319
+ /* @__PURE__ */ jsx16(Text10, { c: "dimmed", children: description }),
1320
+ (doHint || dontHint) && /* @__PURE__ */ jsxs15(Group7, { gap: "sm", mt: "md", wrap: "wrap", children: [
1321
+ doHint && /* @__PURE__ */ jsx16(HintBadge, { variant: "do", children: doHint }),
1322
+ dontHint && /* @__PURE__ */ jsx16(HintBadge, { variant: "dont", children: dontHint })
1323
+ ] })
1324
+ ]
1325
+ }
1326
+ );
1327
+ }
1328
+
1329
+ // src/SpeedDial/SpeedDial.tsx
1330
+ import { useState as useState11, useCallback as useCallback7 } from "react";
1331
+ import { ActionIcon as ActionIcon3, Transition, Tooltip, Box as Box8 } from "@mantine/core";
1332
+ import { IconPlus } from "@tabler/icons-react";
1333
+
1334
+ // src/SpeedDial/SpeedDial.module.css
1335
+ var SpeedDial_default = {};
1336
+
1337
+ // src/SpeedDial/SpeedDial.tsx
1338
+ import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
1339
+ function SpeedDial({
1340
+ actions,
1341
+ icon,
1342
+ openIcon,
1343
+ direction = "up",
1344
+ color = "blue",
1345
+ size = 56,
1346
+ defaultOpen = false,
1347
+ open: controlledOpen,
1348
+ onOpenChange,
1349
+ style,
1350
+ className
1351
+ }) {
1352
+ var _a;
1353
+ const [uncontrolledOpen, setUncontrolledOpen] = useState11(defaultOpen);
1354
+ const isOpen = controlledOpen != null ? controlledOpen : uncontrolledOpen;
1355
+ const toggle = useCallback7(() => {
1356
+ const next = !isOpen;
1357
+ setUncontrolledOpen(next);
1358
+ onOpenChange == null ? void 0 : onOpenChange(next);
1359
+ }, [isOpen, onOpenChange]);
1360
+ const close = useCallback7(() => {
1361
+ setUncontrolledOpen(false);
1362
+ onOpenChange == null ? void 0 : onOpenChange(false);
1363
+ }, [onOpenChange]);
1364
+ const isVertical = direction === "up" || direction === "down";
1365
+ return /* @__PURE__ */ jsxs16(
1366
+ Box8,
1367
+ {
1368
+ className: `${SpeedDial_default.root} ${className != null ? className : ""}`,
1369
+ style,
1370
+ "data-direction": direction,
1371
+ children: [
1372
+ /* @__PURE__ */ jsx17("div", { className: SpeedDial_default.actions, "data-direction": direction, children: actions.map((action, i) => {
1373
+ const index = direction === "up" || direction === "left" ? actions.length - 1 - i : i;
1374
+ return /* @__PURE__ */ jsx17(
1375
+ Transition,
1376
+ {
1377
+ mounted: isOpen,
1378
+ transition: isVertical ? "slide-up" : "slide-right",
1379
+ duration: 200,
1380
+ timingFunction: "ease",
1381
+ enterDelay: index * 40,
1382
+ children: (transitionStyles) => /* @__PURE__ */ jsx17(Tooltip, { label: action.label, position: isVertical ? "left" : "top", children: /* @__PURE__ */ jsx17(
1383
+ ActionIcon3,
1384
+ {
1385
+ variant: "filled",
1386
+ color: "gray",
1387
+ radius: "xl",
1388
+ size: size * 0.7,
1389
+ style: transitionStyles,
1390
+ className: SpeedDial_default.actionButton,
1391
+ onClick: () => {
1392
+ action.onClick();
1393
+ close();
1394
+ },
1395
+ "aria-label": action.label,
1396
+ children: action.icon
1397
+ }
1398
+ ) })
1399
+ },
1400
+ action.label
1401
+ );
1402
+ }) }),
1403
+ /* @__PURE__ */ jsx17(
1404
+ ActionIcon3,
1405
+ {
1406
+ variant: "filled",
1407
+ color,
1408
+ radius: "xl",
1409
+ size,
1410
+ onClick: toggle,
1411
+ className: SpeedDial_default.fab,
1412
+ "data-open": isOpen || void 0,
1413
+ "aria-label": isOpen ? "Close actions" : "Open actions",
1414
+ children: isOpen ? (_a = openIcon != null ? openIcon : icon) != null ? _a : /* @__PURE__ */ jsx17(IconPlus, { size: size * 0.45 }) : icon != null ? icon : /* @__PURE__ */ jsx17(IconPlus, { size: size * 0.45 })
1415
+ }
1416
+ )
1417
+ ]
1418
+ }
1419
+ );
1420
+ }
1421
+
1422
+ // src/SplitSection/SplitSection.tsx
1423
+ import {
1424
+ Box as Box9,
1425
+ Badge as Badge2,
1426
+ Text as Text11,
1427
+ Title as Title4,
1428
+ Stack as Stack3
1429
+ } from "@mantine/core";
1430
+
1431
+ // src/SplitSection/SplitSection.module.css
1432
+ var SplitSection_default = {};
1433
+
1434
+ // src/SplitSection/SplitSection.tsx
1435
+ import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
1436
+ function SplitSection({
1437
+ badge,
1438
+ badgeColor = "violet",
1439
+ subtitle,
1440
+ title,
1441
+ titleColor = "blue",
1442
+ preTitle,
1443
+ description,
1444
+ actions,
1445
+ heading,
1446
+ children,
1447
+ stickyHeading = false,
1448
+ py,
1449
+ reversed = false,
1450
+ id,
1451
+ className
1452
+ }) {
1453
+ const headingContent = heading != null ? heading : /* @__PURE__ */ jsxs17(Stack3, { gap: "sm", children: [
1454
+ badge && /* @__PURE__ */ jsxs17(Box9, { children: [
1455
+ /* @__PURE__ */ jsx18(
1456
+ Badge2,
1457
+ {
1458
+ color: badgeColor,
1459
+ variant: "filled",
1460
+ size: "sm",
1461
+ radius: 4,
1462
+ tt: "uppercase",
1463
+ fw: 700,
1464
+ children: badge
1465
+ }
1466
+ ),
1467
+ subtitle && /* @__PURE__ */ jsx18(Text11, { size: "sm", c: "dimmed", mt: "xs", tt: "uppercase", style: { letterSpacing: "0.05em" }, children: subtitle })
1468
+ ] }),
1469
+ !badge && subtitle && /* @__PURE__ */ jsx18(Text11, { size: "sm", c: "dimmed", tt: "uppercase", style: { letterSpacing: "0.05em" }, children: subtitle }),
1470
+ (preTitle || title) && /* @__PURE__ */ jsxs17(Title4, { order: 2, className: SplitSection_default.title, children: [
1471
+ preTitle && /* @__PURE__ */ jsx18("span", { className: SplitSection_default.preTitle, children: preTitle }),
1472
+ preTitle && /* @__PURE__ */ jsx18("br", {}),
1473
+ title && /* @__PURE__ */ jsx18(
1474
+ Text11,
1475
+ {
1476
+ component: "span",
1477
+ inherit: true,
1478
+ className: SplitSection_default.titleHighlight,
1479
+ c: titleColor,
1480
+ children: title
1481
+ }
1482
+ )
1483
+ ] }),
1484
+ description && /* @__PURE__ */ jsx18(Text11, { size: "lg", c: "dimmed", lh: 1.7, className: SplitSection_default.description, children: description }),
1485
+ actions && /* @__PURE__ */ jsx18(Box9, { mt: "md", children: actions })
1486
+ ] });
1487
+ return /* @__PURE__ */ jsx18(
1488
+ Box9,
1489
+ {
1490
+ component: "section",
1491
+ py: py != null ? py : "calc(var(--mantine-spacing-xl) * 3)",
1492
+ pos: "relative",
1493
+ id,
1494
+ className,
1495
+ children: /* @__PURE__ */ jsx18(Box9, { className: SplitSection_default.container, children: /* @__PURE__ */ jsxs17(Box9, { className: `${SplitSection_default.layout} ${reversed ? SplitSection_default.reversed : ""}`, children: [
1496
+ /* @__PURE__ */ jsx18(
1497
+ Box9,
1498
+ {
1499
+ className: `${SplitSection_default.headingSide} ${stickyHeading ? SplitSection_default.sticky : ""}`,
1500
+ children: /* @__PURE__ */ jsx18(Box9, { className: stickyHeading ? SplitSection_default.stickyInner : void 0, children: headingContent })
1501
+ }
1502
+ ),
1503
+ /* @__PURE__ */ jsx18(Box9, { className: SplitSection_default.contentSide, children })
1504
+ ] }) })
1505
+ }
1506
+ );
1507
+ }
1508
+ export {
1509
+ AnimatedCounter,
1510
+ AnimatedWaveform,
1511
+ AudioPlayer,
1512
+ AudioWaveform,
1513
+ CodeBlock,
1514
+ ColorPalette,
1515
+ ColorSwatch,
1516
+ Copyable,
1517
+ DosDonts,
1518
+ ExpandableCard,
1519
+ FadeInSection,
1520
+ FrequencyWave,
1521
+ GradientSwatch,
1522
+ Hero,
1523
+ HintBadge,
1524
+ MiniAudioPlayer,
1525
+ PrincipleCard,
1526
+ SpeedDial,
1527
+ SplitSection,
1528
+ VideoBackground
1529
+ };