@mieweb/ui 0.1.0 → 0.1.1

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 (72) hide show
  1. package/LICENSE +39 -15
  2. package/README.md +9 -1
  3. package/dist/{chunk-CLNOI5J7.js → chunk-4SMSH4OY.js} +4 -4
  4. package/dist/chunk-4SMSH4OY.js.map +1 -0
  5. package/dist/chunk-5T3AWNHG.cjs +471 -0
  6. package/dist/chunk-5T3AWNHG.cjs.map +1 -0
  7. package/dist/chunk-74K3RRU7.cjs +4 -0
  8. package/dist/{chunk-ZO46CFVN.cjs.map → chunk-74K3RRU7.cjs.map} +1 -1
  9. package/dist/{chunk-VWXGUNBR.cjs → chunk-AKTUXJPI.cjs} +107 -18
  10. package/dist/chunk-AKTUXJPI.cjs.map +1 -0
  11. package/dist/{chunk-NH2JVQ6V.cjs → chunk-I7L6CQXR.cjs} +21 -9
  12. package/dist/chunk-I7L6CQXR.cjs.map +1 -0
  13. package/dist/{chunk-KJOFWJHV.js → chunk-MFB4FS7D.js} +120 -81
  14. package/dist/chunk-MFB4FS7D.js.map +1 -0
  15. package/dist/{chunk-LEE3NMNP.cjs → chunk-NL3CZNBH.cjs} +120 -81
  16. package/dist/chunk-NL3CZNBH.cjs.map +1 -0
  17. package/dist/{chunk-BR2XGATJ.cjs → chunk-NNEFAUHV.cjs} +4 -4
  18. package/dist/chunk-NNEFAUHV.cjs.map +1 -0
  19. package/dist/chunk-SCV7C55E.cjs +11 -0
  20. package/dist/chunk-SCV7C55E.cjs.map +1 -0
  21. package/dist/{chunk-D5IBXXF2.js → chunk-SD44QJIP.js} +20 -8
  22. package/dist/chunk-SD44QJIP.js.map +1 -0
  23. package/dist/{chunk-QBWVTJKF.js → chunk-UBRDKNLQ.js} +107 -18
  24. package/dist/chunk-UBRDKNLQ.js.map +1 -0
  25. package/dist/chunk-V2DF2GUE.js +3 -0
  26. package/dist/{chunk-ZQ4XMJH7.js.map → chunk-V2DF2GUE.js.map} +1 -1
  27. package/dist/chunk-VSQF22GL.js +9 -0
  28. package/dist/chunk-VSQF22GL.js.map +1 -0
  29. package/dist/chunk-XVZ4SLQB.js +447 -0
  30. package/dist/chunk-XVZ4SLQB.js.map +1 -0
  31. package/dist/components/AudioPlayer/index.cjs +6 -6
  32. package/dist/components/AudioPlayer/index.d.cts +5 -1
  33. package/dist/components/AudioPlayer/index.d.ts +5 -1
  34. package/dist/components/AudioPlayer/index.js +1 -1
  35. package/dist/components/Modal/index.cjs +11 -10
  36. package/dist/components/Modal/index.js +3 -2
  37. package/dist/components/RecordButton/index.cjs +4 -8
  38. package/dist/components/RecordButton/index.d.cts +57 -44
  39. package/dist/components/RecordButton/index.d.ts +57 -44
  40. package/dist/components/RecordButton/index.js +1 -1
  41. package/dist/components/Select/index.cjs +3 -4
  42. package/dist/components/Select/index.js +1 -2
  43. package/dist/components/Spinner/index.d.cts +1 -1
  44. package/dist/components/Spinner/index.d.ts +1 -1
  45. package/dist/hooks/index.cjs +3 -2
  46. package/dist/hooks/index.js +2 -1
  47. package/dist/index.cjs +880 -667
  48. package/dist/index.cjs.map +1 -1
  49. package/dist/index.d.cts +16 -11
  50. package/dist/index.d.ts +16 -11
  51. package/dist/index.js +801 -588
  52. package/dist/index.js.map +1 -1
  53. package/dist/styles.css +1 -1
  54. package/dist/utils/index.cjs +6 -1
  55. package/dist/utils/index.d.cts +14 -1
  56. package/dist/utils/index.d.ts +14 -1
  57. package/dist/utils/index.js +2 -1
  58. package/package.json +7 -7
  59. package/dist/chunk-BR2XGATJ.cjs.map +0 -1
  60. package/dist/chunk-CLNOI5J7.js.map +0 -1
  61. package/dist/chunk-D5IBXXF2.js.map +0 -1
  62. package/dist/chunk-FQ5G7J24.js +0 -297
  63. package/dist/chunk-FQ5G7J24.js.map +0 -1
  64. package/dist/chunk-HLW3XD5R.cjs +0 -322
  65. package/dist/chunk-HLW3XD5R.cjs.map +0 -1
  66. package/dist/chunk-KJOFWJHV.js.map +0 -1
  67. package/dist/chunk-LEE3NMNP.cjs.map +0 -1
  68. package/dist/chunk-NH2JVQ6V.cjs.map +0 -1
  69. package/dist/chunk-QBWVTJKF.js.map +0 -1
  70. package/dist/chunk-VWXGUNBR.cjs.map +0 -1
  71. package/dist/chunk-ZO46CFVN.cjs +0 -4
  72. package/dist/chunk-ZQ4XMJH7.js +0 -3
@@ -0,0 +1,447 @@
1
+ import { cn } from './chunk-F3SOEIN2.js';
2
+ import * as React from 'react';
3
+ import { cva } from 'class-variance-authority';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+
6
+ function MicIcon({ className }) {
7
+ return /* @__PURE__ */ jsxs(
8
+ "svg",
9
+ {
10
+ xmlns: "http://www.w3.org/2000/svg",
11
+ viewBox: "0 0 24 24",
12
+ fill: "none",
13
+ stroke: "currentColor",
14
+ strokeWidth: "2",
15
+ strokeLinecap: "round",
16
+ strokeLinejoin: "round",
17
+ className,
18
+ "aria-hidden": "true",
19
+ children: [
20
+ /* @__PURE__ */ jsx("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
21
+ /* @__PURE__ */ jsx("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
22
+ /* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
23
+ ]
24
+ }
25
+ );
26
+ }
27
+ function MicOffIcon({ className }) {
28
+ return /* @__PURE__ */ jsxs(
29
+ "svg",
30
+ {
31
+ xmlns: "http://www.w3.org/2000/svg",
32
+ viewBox: "0 0 24 24",
33
+ fill: "none",
34
+ stroke: "currentColor",
35
+ strokeWidth: "2",
36
+ strokeLinecap: "round",
37
+ strokeLinejoin: "round",
38
+ className,
39
+ "aria-hidden": "true",
40
+ children: [
41
+ /* @__PURE__ */ jsx("line", { x1: "2", x2: "22", y1: "2", y2: "22" }),
42
+ /* @__PURE__ */ jsx("path", { d: "M18.89 13.23A7.12 7.12 0 0 0 19 12v-2" }),
43
+ /* @__PURE__ */ jsx("path", { d: "M5 10v2a7 7 0 0 0 12 5" }),
44
+ /* @__PURE__ */ jsx("path", { d: "M15 9.34V5a3 3 0 0 0-5.68-1.33" }),
45
+ /* @__PURE__ */ jsx("path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12" }),
46
+ /* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
47
+ ]
48
+ }
49
+ );
50
+ }
51
+ function StopIcon({ className }) {
52
+ return /* @__PURE__ */ jsx(
53
+ "svg",
54
+ {
55
+ xmlns: "http://www.w3.org/2000/svg",
56
+ viewBox: "0 0 24 24",
57
+ fill: "currentColor",
58
+ className,
59
+ "aria-hidden": "true",
60
+ children: /* @__PURE__ */ jsx("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" })
61
+ }
62
+ );
63
+ }
64
+ function CheckIcon({ className }) {
65
+ return /* @__PURE__ */ jsx(
66
+ "svg",
67
+ {
68
+ xmlns: "http://www.w3.org/2000/svg",
69
+ viewBox: "0 0 24 24",
70
+ fill: "none",
71
+ stroke: "currentColor",
72
+ strokeWidth: "2.5",
73
+ strokeLinecap: "round",
74
+ strokeLinejoin: "round",
75
+ className,
76
+ "aria-hidden": "true",
77
+ children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
78
+ }
79
+ );
80
+ }
81
+ function LoadingSpinner({ className }) {
82
+ return /* @__PURE__ */ jsx(
83
+ "svg",
84
+ {
85
+ xmlns: "http://www.w3.org/2000/svg",
86
+ viewBox: "0 0 24 24",
87
+ fill: "none",
88
+ stroke: "currentColor",
89
+ strokeWidth: "2",
90
+ strokeLinecap: "round",
91
+ strokeLinejoin: "round",
92
+ className: cn("animate-spin", className),
93
+ "aria-hidden": "true",
94
+ children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" })
95
+ }
96
+ );
97
+ }
98
+ function PulseRings({ variant }) {
99
+ const ringColor = variant === "minimal" ? "bg-red-500/30" : "bg-red-400/40";
100
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
101
+ /* @__PURE__ */ jsx(
102
+ "span",
103
+ {
104
+ className: cn("absolute inset-0 animate-ping rounded-full", ringColor),
105
+ style: { animationDuration: "1.5s" }
106
+ }
107
+ ),
108
+ /* @__PURE__ */ jsx(
109
+ "span",
110
+ {
111
+ className: cn("absolute inset-0 animate-ping rounded-full", ringColor),
112
+ style: { animationDuration: "1.5s", animationDelay: "0.5s" }
113
+ }
114
+ )
115
+ ] });
116
+ }
117
+ function WaveformBars({ size }) {
118
+ const barHeight = size === "sm" ? "h-2" : size === "md" ? "h-3" : "h-4";
119
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0.5", children: [0, 1, 2, 3, 4].map((i) => /* @__PURE__ */ jsx(
120
+ "span",
121
+ {
122
+ className: cn(
123
+ "animate-waveform w-0.5 rounded-full bg-current",
124
+ barHeight
125
+ ),
126
+ style: {
127
+ animationDelay: `${i * 0.1}s`
128
+ }
129
+ },
130
+ i
131
+ )) });
132
+ }
133
+ var recordButtonVariants = cva(
134
+ [
135
+ "relative inline-flex items-center justify-center rounded-full",
136
+ "transition-all duration-200",
137
+ "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background"
138
+ ],
139
+ {
140
+ variants: {
141
+ variant: {
142
+ default: "",
143
+ outline: "border-2",
144
+ ghost: "",
145
+ minimal: ""
146
+ },
147
+ size: {
148
+ sm: "size-10",
149
+ md: "size-12",
150
+ lg: "size-14"
151
+ }
152
+ },
153
+ defaultVariants: {
154
+ variant: "default",
155
+ size: "md"
156
+ }
157
+ }
158
+ );
159
+ var iconSizes = {
160
+ sm: "size-4",
161
+ md: "size-5",
162
+ lg: "size-6"
163
+ };
164
+ function getStateStyles(state, variant) {
165
+ const styles = {
166
+ default: {
167
+ idle: "bg-primary/10 text-primary hover:bg-primary/20",
168
+ recording: "bg-red-500/10 text-red-500 hover:bg-red-500/20",
169
+ processing: "bg-primary/10 text-primary cursor-wait",
170
+ disabled: "bg-muted text-muted-foreground cursor-not-allowed opacity-50",
171
+ error: "bg-destructive/10 text-destructive",
172
+ success: "bg-success/10 text-success"
173
+ },
174
+ outline: {
175
+ idle: "border-primary/50 text-primary bg-transparent hover:bg-primary/10 hover:border-primary",
176
+ recording: "border-red-500/50 text-red-500 bg-transparent hover:bg-red-500/10 hover:border-red-500",
177
+ processing: "border-primary/50 text-primary bg-transparent cursor-wait",
178
+ disabled: "border-muted text-muted-foreground bg-transparent cursor-not-allowed opacity-50",
179
+ error: "border-destructive/50 text-destructive bg-transparent",
180
+ success: "border-success/50 text-success bg-transparent"
181
+ },
182
+ ghost: {
183
+ idle: "text-primary hover:bg-primary/10",
184
+ recording: "text-red-500 hover:bg-red-500/10",
185
+ processing: "text-primary bg-primary/5 cursor-wait",
186
+ disabled: "text-muted-foreground cursor-not-allowed opacity-50",
187
+ error: "text-destructive",
188
+ success: "text-success"
189
+ },
190
+ minimal: {
191
+ idle: "text-primary hover:text-primary/80",
192
+ recording: "text-red-500 hover:text-red-500/80",
193
+ processing: "text-primary cursor-wait",
194
+ disabled: "text-muted-foreground/40 cursor-not-allowed",
195
+ error: "text-destructive",
196
+ success: "text-success"
197
+ }
198
+ };
199
+ return styles[variant][state];
200
+ }
201
+ function formatDuration(seconds) {
202
+ const mins = Math.floor(seconds / 60);
203
+ const secs = Math.floor(seconds % 60);
204
+ return `${mins}:${secs.toString().padStart(2, "0")}`;
205
+ }
206
+ var RecordButton = React.forwardRef(
207
+ ({
208
+ className,
209
+ variant = "default",
210
+ size = "md",
211
+ state: controlledState,
212
+ showWaveform = false,
213
+ showPulse = true,
214
+ disabled,
215
+ showDuration = false,
216
+ idleIcon,
217
+ recordingIcon,
218
+ transcriptionState,
219
+ showTranscriptionState = false,
220
+ onRecordingComplete,
221
+ onRecordingStart,
222
+ onRecordingError,
223
+ maxDuration = 0,
224
+ mimeType = "audio/webm",
225
+ onClick,
226
+ ...props
227
+ }, ref) => {
228
+ const [internalState, setInternalState] = React.useState("idle");
229
+ const [duration, setDuration] = React.useState(0);
230
+ const mediaRecorderRef = React.useRef(null);
231
+ const streamRef = React.useRef(null);
232
+ const chunksRef = React.useRef([]);
233
+ const timerRef = React.useRef(void 0);
234
+ const startTimeRef = React.useRef(0);
235
+ const timeoutsRef = React.useRef([]);
236
+ const addTimeout = (callback, delay) => {
237
+ const id = setTimeout(() => {
238
+ callback();
239
+ timeoutsRef.current = timeoutsRef.current.filter((t) => t !== id);
240
+ }, delay);
241
+ timeoutsRef.current.push(id);
242
+ return id;
243
+ };
244
+ const clearAllTimeouts = () => {
245
+ timeoutsRef.current.forEach(clearTimeout);
246
+ timeoutsRef.current = [];
247
+ };
248
+ const isControlled = controlledState !== void 0;
249
+ const currentState = isControlled ? controlledState : internalState;
250
+ const effectiveState = disabled ? "disabled" : transcriptionState === "error" ? "error" : transcriptionState === "transcribing" || transcriptionState === "streaming" ? "processing" : transcriptionState === "complete" ? "success" : currentState;
251
+ React.useEffect(() => {
252
+ if (typeof window === "undefined") return;
253
+ if (disabled && (controlledState && controlledState !== "disabled" || transcriptionState)) {
254
+ console.warn(
255
+ "[RecordButton]: `disabled` prop takes precedence over both `state` and `transcriptionState`. When `disabled` is true, the button will always appear disabled."
256
+ );
257
+ }
258
+ if (controlledState !== void 0 && transcriptionState !== void 0) {
259
+ const mappedTranscriptionState = transcriptionState === "error" ? "error" : transcriptionState === "transcribing" || transcriptionState === "streaming" ? "processing" : transcriptionState === "complete" ? "success" : void 0;
260
+ if (mappedTranscriptionState !== void 0 && mappedTranscriptionState !== controlledState) {
261
+ console.warn(
262
+ `[RecordButton]: \`transcriptionState\` takes precedence over \`state\`. Received state="${controlledState}" and transcriptionState="${transcriptionState}". This may lead to unexpected visual states.`
263
+ );
264
+ }
265
+ }
266
+ }, [disabled, controlledState, transcriptionState]);
267
+ const iconSize = iconSizes[size];
268
+ const isRecording = effectiveState === "recording";
269
+ const isDisabled = effectiveState === "disabled" || effectiveState === "processing";
270
+ React.useEffect(() => {
271
+ return () => {
272
+ if (timerRef.current) {
273
+ clearInterval(timerRef.current);
274
+ }
275
+ clearAllTimeouts();
276
+ if (streamRef.current) {
277
+ streamRef.current.getTracks().forEach((track) => track.stop());
278
+ }
279
+ };
280
+ }, []);
281
+ const stopRecording = React.useCallback(() => {
282
+ if (timerRef.current) {
283
+ clearInterval(timerRef.current);
284
+ }
285
+ if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") {
286
+ mediaRecorderRef.current.stop();
287
+ }
288
+ if (streamRef.current) {
289
+ streamRef.current.getTracks().forEach((track) => track.stop());
290
+ }
291
+ }, []);
292
+ const startRecording = React.useCallback(async () => {
293
+ if (disabled || effectiveState === "recording" || effectiveState === "processing")
294
+ return;
295
+ try {
296
+ const stream = await navigator.mediaDevices.getUserMedia({
297
+ audio: true
298
+ });
299
+ streamRef.current = stream;
300
+ const options = { mimeType };
301
+ if (!MediaRecorder.isTypeSupported(mimeType)) {
302
+ mediaRecorderRef.current = new MediaRecorder(stream);
303
+ } else {
304
+ mediaRecorderRef.current = new MediaRecorder(stream, options);
305
+ }
306
+ chunksRef.current = [];
307
+ mediaRecorderRef.current.ondataavailable = (e) => {
308
+ if (e.data.size > 0) {
309
+ chunksRef.current.push(e.data);
310
+ }
311
+ };
312
+ mediaRecorderRef.current.onstop = () => {
313
+ if (!isControlled) {
314
+ setInternalState("processing");
315
+ }
316
+ const blob = new Blob(chunksRef.current, { type: mimeType });
317
+ const finalDuration = duration;
318
+ addTimeout(() => {
319
+ onRecordingComplete?.(blob, finalDuration);
320
+ if (!isControlled) {
321
+ setInternalState("success");
322
+ addTimeout(() => {
323
+ setInternalState("idle");
324
+ }, 1500);
325
+ }
326
+ setDuration(0);
327
+ }, 200);
328
+ };
329
+ mediaRecorderRef.current.start(100);
330
+ startTimeRef.current = Date.now();
331
+ if (!isControlled) {
332
+ setInternalState("recording");
333
+ }
334
+ onRecordingStart?.();
335
+ timerRef.current = window.setInterval(() => {
336
+ const elapsed = (Date.now() - startTimeRef.current) / 1e3;
337
+ setDuration(elapsed);
338
+ if (maxDuration > 0 && elapsed >= maxDuration) {
339
+ stopRecording();
340
+ }
341
+ }, 100);
342
+ } catch (error) {
343
+ onRecordingError?.(error);
344
+ if (!isControlled) {
345
+ setInternalState("error");
346
+ addTimeout(() => {
347
+ setInternalState("idle");
348
+ }, 2e3);
349
+ }
350
+ }
351
+ }, [
352
+ disabled,
353
+ effectiveState,
354
+ isControlled,
355
+ mimeType,
356
+ maxDuration,
357
+ duration,
358
+ onRecordingComplete,
359
+ onRecordingStart,
360
+ onRecordingError,
361
+ stopRecording
362
+ ]);
363
+ const handleClick = React.useCallback(
364
+ (e) => {
365
+ onClick?.(e);
366
+ if (!isControlled) {
367
+ if (effectiveState === "recording") {
368
+ stopRecording();
369
+ } else if (effectiveState === "idle") {
370
+ startRecording();
371
+ }
372
+ }
373
+ },
374
+ [onClick, isControlled, effectiveState, startRecording, stopRecording]
375
+ );
376
+ const renderIcon = () => {
377
+ switch (effectiveState) {
378
+ case "recording":
379
+ if (showWaveform) {
380
+ return /* @__PURE__ */ jsx(WaveformBars, { size });
381
+ }
382
+ return recordingIcon || /* @__PURE__ */ jsx(StopIcon, { className: iconSize });
383
+ case "processing":
384
+ return /* @__PURE__ */ jsx(LoadingSpinner, { className: iconSize });
385
+ case "disabled":
386
+ case "error":
387
+ return /* @__PURE__ */ jsx(MicOffIcon, { className: iconSize });
388
+ case "success":
389
+ return /* @__PURE__ */ jsx(CheckIcon, { className: iconSize });
390
+ default:
391
+ return idleIcon || /* @__PURE__ */ jsx(MicIcon, { className: iconSize });
392
+ }
393
+ };
394
+ const getAriaLabel = () => {
395
+ switch (effectiveState) {
396
+ case "recording":
397
+ return "Stop recording";
398
+ case "processing":
399
+ return "Processing recording";
400
+ case "disabled":
401
+ return "Recording unavailable";
402
+ case "error":
403
+ return "Recording failed";
404
+ case "success":
405
+ return "Recording complete";
406
+ default:
407
+ return "Start recording";
408
+ }
409
+ };
410
+ const getTranscriptionLabel = () => {
411
+ if (transcriptionState === "streaming") return "Listening...";
412
+ if (transcriptionState === "transcribing") return "Transcribing...";
413
+ return null;
414
+ };
415
+ return /* @__PURE__ */ jsxs("div", { className: "relative inline-flex items-center gap-2", children: [
416
+ /* @__PURE__ */ jsxs(
417
+ "button",
418
+ {
419
+ ref,
420
+ type: "button",
421
+ disabled: isDisabled,
422
+ onClick: handleClick,
423
+ ...props,
424
+ className: cn(
425
+ recordButtonVariants({ variant, size }),
426
+ getStateStyles(effectiveState, variant),
427
+ className
428
+ ),
429
+ "aria-label": getAriaLabel(),
430
+ "aria-pressed": effectiveState === "recording" ? true : void 0,
431
+ "aria-busy": effectiveState === "processing" ? true : void 0,
432
+ children: [
433
+ effectiveState === "recording" && showPulse && /* @__PURE__ */ jsx(PulseRings, { variant }),
434
+ /* @__PURE__ */ jsx("span", { className: "relative z-10", children: renderIcon() })
435
+ ]
436
+ }
437
+ ),
438
+ showDuration && isRecording && /* @__PURE__ */ jsx("span", { className: "text-destructive font-mono text-xs tabular-nums", children: formatDuration(duration) }),
439
+ showTranscriptionState && getTranscriptionLabel() && /* @__PURE__ */ jsx("span", { className: "text-primary text-xs font-medium", children: getTranscriptionLabel() })
440
+ ] });
441
+ }
442
+ );
443
+ RecordButton.displayName = "RecordButton";
444
+
445
+ export { RecordButton, formatDuration, recordButtonVariants };
446
+ //# sourceMappingURL=chunk-XVZ4SLQB.js.map
447
+ //# sourceMappingURL=chunk-XVZ4SLQB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/RecordButton/RecordButton.tsx"],"names":[],"mappings":"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","file":"chunk-XVZ4SLQB.js","sourcesContent":["import * as React from 'react';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type RecordButtonState =\n | 'idle'\n | 'recording'\n | 'processing'\n | 'disabled'\n | 'error'\n | 'success';\n\nexport type RecordButtonVariant = 'default' | 'outline' | 'ghost' | 'minimal';\nexport type RecordButtonSize = 'sm' | 'md' | 'lg';\n\n/** Transcription state for integration with transcription services */\nexport type TranscriptionState =\n | 'idle'\n | 'recording'\n | 'transcribing'\n | 'streaming'\n | 'complete'\n | 'error';\n\nexport interface TranscriptionResult {\n /** The transcribed text */\n text: string;\n /** Whether this is a partial (streaming) or final result */\n isFinal: boolean;\n /** Confidence score (0-1) if available */\n confidence?: number;\n}\n\nexport interface RecordButtonProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'children'\n> {\n /** Current state of the button */\n state?: RecordButtonState;\n /** Size of the button */\n size?: RecordButtonSize;\n /** Visual style variant */\n variant?: RecordButtonVariant;\n /** Show waveform bars when recording (instead of stop icon) */\n showWaveform?: boolean;\n /** Show pulse rings when recording */\n showPulse?: boolean;\n /** Show recording duration while recording */\n showDuration?: boolean;\n /** Custom idle icon */\n idleIcon?: React.ReactNode;\n /** Custom recording icon */\n recordingIcon?: React.ReactNode;\n /** Current transcription state (for external control) */\n transcriptionState?: TranscriptionState;\n /** Show transcription state indicator */\n showTranscriptionState?: boolean;\n\n // Recording callbacks (for uncontrolled usage)\n /** Callback when recording is complete with the audio blob */\n onRecordingComplete?: (blob: Blob, duration: number) => void;\n /** Callback when recording starts */\n onRecordingStart?: () => void;\n /** Callback when a recording error occurs */\n onRecordingError?: (error: Error) => void;\n /** Maximum recording duration in seconds (0 for unlimited) */\n maxDuration?: number;\n /** Audio MIME type */\n mimeType?: string;\n}\n\n// ============================================================================\n// Icons\n// ============================================================================\n\nfunction MicIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n );\n}\n\nfunction MicOffIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\" />\n <path d=\"M18.89 13.23A7.12 7.12 0 0 0 19 12v-2\" />\n <path d=\"M5 10v2a7 7 0 0 0 12 5\" />\n <path d=\"M15 9.34V5a3 3 0 0 0-5.68-1.33\" />\n <path d=\"M9 9v3a3 3 0 0 0 5.12 2.12\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n );\n}\n\nfunction StopIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\nfunction CheckIcon({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\nfunction LoadingSpinner({ className }: { className?: string }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('animate-spin', className)}\n aria-hidden=\"true\"\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\n// ============================================================================\n// Pulse Ring Animation (for recording state)\n// ============================================================================\n\nfunction PulseRings({ variant }: { variant: RecordButtonVariant }) {\n const ringColor = variant === 'minimal' ? 'bg-red-500/30' : 'bg-red-400/40';\n\n return (\n <>\n <span\n className={cn('absolute inset-0 animate-ping rounded-full', ringColor)}\n style={{ animationDuration: '1.5s' }}\n />\n <span\n className={cn('absolute inset-0 animate-ping rounded-full', ringColor)}\n style={{ animationDuration: '1.5s', animationDelay: '0.5s' }}\n />\n </>\n );\n}\n\n// ============================================================================\n// Waveform Animation (for recording state)\n// ============================================================================\n\nfunction WaveformBars({ size }: { size: RecordButtonSize }) {\n const barHeight = size === 'sm' ? 'h-2' : size === 'md' ? 'h-3' : 'h-4';\n\n return (\n <div className=\"flex items-center gap-0.5\">\n {[0, 1, 2, 3, 4].map((i) => (\n <span\n key={i}\n className={cn(\n 'animate-waveform w-0.5 rounded-full bg-current',\n barHeight\n )}\n style={{\n animationDelay: `${i * 0.1}s`,\n }}\n />\n ))}\n </div>\n );\n}\n\n// ============================================================================\n// Style Variants\n// ============================================================================\n\nconst recordButtonVariants = cva(\n [\n 'relative inline-flex items-center justify-center rounded-full',\n 'transition-all duration-200',\n 'outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',\n ],\n {\n variants: {\n variant: {\n default: '',\n outline: 'border-2',\n ghost: '',\n minimal: '',\n },\n size: {\n sm: 'size-10',\n md: 'size-12',\n lg: 'size-14',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n },\n }\n);\n\nconst iconSizes: Record<RecordButtonSize, string> = {\n sm: 'size-4',\n md: 'size-5',\n lg: 'size-6',\n};\n\n// ============================================================================\n// State Styles\n// ============================================================================\n\nfunction getStateStyles(\n state: RecordButtonState,\n variant: RecordButtonVariant\n): string {\n const styles: Record<\n RecordButtonVariant,\n Record<RecordButtonState, string>\n > = {\n default: {\n idle: 'bg-primary/10 text-primary hover:bg-primary/20',\n recording: 'bg-red-500/10 text-red-500 hover:bg-red-500/20',\n processing: 'bg-primary/10 text-primary cursor-wait',\n disabled: 'bg-muted text-muted-foreground cursor-not-allowed opacity-50',\n error: 'bg-destructive/10 text-destructive',\n success: 'bg-success/10 text-success',\n },\n outline: {\n idle: 'border-primary/50 text-primary bg-transparent hover:bg-primary/10 hover:border-primary',\n recording:\n 'border-red-500/50 text-red-500 bg-transparent hover:bg-red-500/10 hover:border-red-500',\n processing: 'border-primary/50 text-primary bg-transparent cursor-wait',\n disabled:\n 'border-muted text-muted-foreground bg-transparent cursor-not-allowed opacity-50',\n error: 'border-destructive/50 text-destructive bg-transparent',\n success: 'border-success/50 text-success bg-transparent',\n },\n ghost: {\n idle: 'text-primary hover:bg-primary/10',\n recording: 'text-red-500 hover:bg-red-500/10',\n processing: 'text-primary bg-primary/5 cursor-wait',\n disabled: 'text-muted-foreground cursor-not-allowed opacity-50',\n error: 'text-destructive',\n success: 'text-success',\n },\n minimal: {\n idle: 'text-primary hover:text-primary/80',\n recording: 'text-red-500 hover:text-red-500/80',\n processing: 'text-primary cursor-wait',\n disabled: 'text-muted-foreground/40 cursor-not-allowed',\n error: 'text-destructive',\n success: 'text-success',\n },\n };\n\n return styles[variant][state];\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nfunction formatDuration(seconds: number): string {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * A voice recording button with 6 states and 4 visual variants.\n * Supports pulse animations, waveform visualization, and transcription integration.\n *\n * ## Controlled vs Uncontrolled Mode\n *\n * **Uncontrolled mode** (default): The component manages its own recording state.\n * Use `onRecordingComplete`, `onRecordingStart`, and `onRecordingError` callbacks.\n *\n * **Controlled mode**: When the `state` prop is provided, the component becomes\n * controlled and you must manage state changes externally. Note: In controlled mode,\n * the internal MediaRecorder functionality is disabled - you must implement your own\n * recording logic.\n *\n * ## State Precedence\n *\n * When multiple state-controlling props are provided, they follow this precedence:\n * 1. `disabled` prop (highest priority)\n * 2. `transcriptionState` prop\n * 3. `state` prop\n * 4. Internal state (uncontrolled)\n *\n * @example\n * ```tsx\n * // Uncontrolled with recording callbacks\n * <RecordButton\n * onRecordingComplete={(blob, duration) => console.log('Recorded:', blob)}\n * onRecordingError={(error) => console.error('Recording failed:', error)}\n * />\n *\n * // Controlled state (requires external recording implementation)\n * <RecordButton state=\"idle\" onClick={handleClick} />\n *\n * // Different variants\n * <RecordButton variant=\"outline\" size=\"lg\" />\n *\n * // With waveform animation\n * <RecordButton state=\"recording\" showWaveform showPulse />\n * ```\n */\nconst RecordButton = React.forwardRef<HTMLButtonElement, RecordButtonProps>(\n (\n {\n className,\n variant = 'default',\n size = 'md',\n state: controlledState,\n showWaveform = false,\n showPulse = true,\n disabled,\n showDuration = false,\n idleIcon,\n recordingIcon,\n transcriptionState,\n showTranscriptionState = false,\n onRecordingComplete,\n onRecordingStart,\n onRecordingError,\n maxDuration = 0,\n mimeType = 'audio/webm',\n onClick,\n ...props\n },\n ref\n ) => {\n // Internal state for uncontrolled usage\n const [internalState, setInternalState] =\n React.useState<RecordButtonState>('idle');\n const [duration, setDuration] = React.useState(0);\n\n const mediaRecorderRef = React.useRef<MediaRecorder | null>(null);\n const streamRef = React.useRef<MediaStream | null>(null);\n const chunksRef = React.useRef<Blob[]>([]);\n const timerRef = React.useRef<number | undefined>(undefined);\n const startTimeRef = React.useRef<number>(0);\n const timeoutsRef = React.useRef<NodeJS.Timeout[]>([]);\n\n // Helper to track and manage timeouts\n const addTimeout = (callback: () => void, delay: number) => {\n const id = setTimeout(() => {\n callback();\n // Remove from tracking after execution\n timeoutsRef.current = timeoutsRef.current.filter((t) => t !== id);\n }, delay);\n timeoutsRef.current.push(id);\n return id;\n };\n\n const clearAllTimeouts = () => {\n timeoutsRef.current.forEach(clearTimeout);\n timeoutsRef.current = [];\n };\n\n // Use controlled state if provided, otherwise internal state\n const isControlled = controlledState !== undefined;\n const currentState = isControlled ? controlledState : internalState;\n\n // Map transcription state to button state if provided\n // Precedence: disabled prop → transcriptionState → state prop → internal state\n const effectiveState: RecordButtonState = disabled\n ? 'disabled'\n : transcriptionState === 'error'\n ? 'error'\n : transcriptionState === 'transcribing' ||\n transcriptionState === 'streaming'\n ? 'processing'\n : transcriptionState === 'complete'\n ? 'success'\n : currentState;\n\n // Dev mode warnings for conflicting states\n React.useEffect(() => {\n // Only warn in development\n if (typeof window === 'undefined') return;\n\n // Warn when disabled is true but other state props suggest a different visual state\n if (\n disabled &&\n ((controlledState && controlledState !== 'disabled') ||\n transcriptionState)\n ) {\n console.warn(\n '[RecordButton]: `disabled` prop takes precedence over both `state` and `transcriptionState`. ' +\n 'When `disabled` is true, the button will always appear disabled.'\n );\n }\n\n // Warn when both controlled state and transcriptionState are provided and conflict\n if (controlledState !== undefined && transcriptionState !== undefined) {\n const mappedTranscriptionState: RecordButtonState | undefined =\n transcriptionState === 'error'\n ? 'error'\n : transcriptionState === 'transcribing' ||\n transcriptionState === 'streaming'\n ? 'processing'\n : transcriptionState === 'complete'\n ? 'success'\n : undefined;\n\n if (\n mappedTranscriptionState !== undefined &&\n mappedTranscriptionState !== controlledState\n ) {\n console.warn(\n '[RecordButton]: `transcriptionState` takes precedence over `state`. ' +\n `Received state=\"${controlledState}\" and transcriptionState=\"${transcriptionState}\". ` +\n 'This may lead to unexpected visual states.'\n );\n }\n }\n }, [disabled, controlledState, transcriptionState]);\n\n const iconSize = iconSizes[size];\n const isRecording = effectiveState === 'recording';\n const isDisabled =\n effectiveState === 'disabled' || effectiveState === 'processing';\n\n // Cleanup on unmount\n React.useEffect(() => {\n return () => {\n if (timerRef.current) {\n clearInterval(timerRef.current);\n }\n clearAllTimeouts();\n if (streamRef.current) {\n streamRef.current.getTracks().forEach((track) => track.stop());\n }\n };\n }, []);\n\n const stopRecording = React.useCallback(() => {\n if (timerRef.current) {\n clearInterval(timerRef.current);\n }\n\n if (\n mediaRecorderRef.current &&\n mediaRecorderRef.current.state !== 'inactive'\n ) {\n mediaRecorderRef.current.stop();\n }\n\n if (streamRef.current) {\n streamRef.current.getTracks().forEach((track) => track.stop());\n }\n }, []);\n\n const startRecording = React.useCallback(async () => {\n // Guard: don't start if disabled, already recording, or processing\n if (\n disabled ||\n effectiveState === 'recording' ||\n effectiveState === 'processing'\n )\n return;\n\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n });\n streamRef.current = stream;\n\n const options = { mimeType };\n if (!MediaRecorder.isTypeSupported(mimeType)) {\n mediaRecorderRef.current = new MediaRecorder(stream);\n } else {\n mediaRecorderRef.current = new MediaRecorder(stream, options);\n }\n\n chunksRef.current = [];\n\n mediaRecorderRef.current.ondataavailable = (e) => {\n if (e.data.size > 0) {\n chunksRef.current.push(e.data);\n }\n };\n\n mediaRecorderRef.current.onstop = () => {\n if (!isControlled) {\n setInternalState('processing');\n }\n\n const blob = new Blob(chunksRef.current, { type: mimeType });\n const finalDuration = duration;\n\n // Small delay to show processing state\n addTimeout(() => {\n onRecordingComplete?.(blob, finalDuration);\n if (!isControlled) {\n setInternalState('success');\n // Reset to idle after showing success\n addTimeout(() => {\n setInternalState('idle');\n }, 1500);\n }\n setDuration(0);\n }, 200);\n };\n\n mediaRecorderRef.current.start(100);\n startTimeRef.current = Date.now();\n\n if (!isControlled) {\n setInternalState('recording');\n }\n onRecordingStart?.();\n\n timerRef.current = window.setInterval(() => {\n const elapsed = (Date.now() - startTimeRef.current) / 1000;\n setDuration(elapsed);\n\n if (maxDuration > 0 && elapsed >= maxDuration) {\n stopRecording();\n }\n }, 100);\n } catch (error) {\n onRecordingError?.(error as Error);\n if (!isControlled) {\n setInternalState('error');\n // Reset to idle after showing error\n addTimeout(() => {\n setInternalState('idle');\n }, 2000);\n }\n }\n }, [\n disabled,\n effectiveState,\n isControlled,\n mimeType,\n maxDuration,\n duration,\n onRecordingComplete,\n onRecordingStart,\n onRecordingError,\n stopRecording,\n ]);\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n // Call external onClick if provided\n onClick?.(e);\n\n // Handle internal recording logic only if not fully controlled\n if (!isControlled) {\n if (effectiveState === 'recording') {\n stopRecording();\n } else if (effectiveState === 'idle') {\n startRecording();\n }\n }\n },\n [onClick, isControlled, effectiveState, startRecording, stopRecording]\n );\n\n // Determine which icon to show\n const renderIcon = () => {\n switch (effectiveState) {\n case 'recording':\n if (showWaveform) {\n return <WaveformBars size={size} />;\n }\n return recordingIcon || <StopIcon className={iconSize} />;\n case 'processing':\n return <LoadingSpinner className={iconSize} />;\n case 'disabled':\n case 'error':\n return <MicOffIcon className={iconSize} />;\n case 'success':\n return <CheckIcon className={iconSize} />;\n default:\n return idleIcon || <MicIcon className={iconSize} />;\n }\n };\n\n const getAriaLabel = () => {\n switch (effectiveState) {\n case 'recording':\n return 'Stop recording';\n case 'processing':\n return 'Processing recording';\n case 'disabled':\n return 'Recording unavailable';\n case 'error':\n return 'Recording failed';\n case 'success':\n return 'Recording complete';\n default:\n return 'Start recording';\n }\n };\n\n const getTranscriptionLabel = () => {\n if (transcriptionState === 'streaming') return 'Listening...';\n if (transcriptionState === 'transcribing') return 'Transcribing...';\n return null;\n };\n\n return (\n <div className=\"relative inline-flex items-center gap-2\">\n <button\n ref={ref}\n type=\"button\"\n disabled={isDisabled}\n onClick={handleClick}\n {...props}\n className={cn(\n recordButtonVariants({ variant, size }),\n getStateStyles(effectiveState, variant),\n className\n )}\n aria-label={getAriaLabel()}\n aria-pressed={effectiveState === 'recording' ? true : undefined}\n aria-busy={effectiveState === 'processing' ? true : undefined}\n >\n {/* Pulse animation for recording state */}\n {effectiveState === 'recording' && showPulse && (\n <PulseRings variant={variant} />\n )}\n\n {/* Icon */}\n <span className=\"relative z-10\">{renderIcon()}</span>\n </button>\n\n {/* Duration display */}\n {showDuration && isRecording && (\n <span className=\"text-destructive font-mono text-xs tabular-nums\">\n {formatDuration(duration)}\n </span>\n )}\n\n {/* Transcription state label */}\n {showTranscriptionState && getTranscriptionLabel() && (\n <span className=\"text-primary text-xs font-medium\">\n {getTranscriptionLabel()}\n </span>\n )}\n </div>\n );\n }\n);\n\nRecordButton.displayName = 'RecordButton';\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { RecordButton, recordButtonVariants, formatDuration };\n"]}
@@ -1,29 +1,29 @@
1
1
  'use strict';
2
2
 
3
- var chunkVWXGUNBR_cjs = require('../../chunk-VWXGUNBR.cjs');
3
+ var chunkAKTUXJPI_cjs = require('../../chunk-AKTUXJPI.cjs');
4
4
  require('../../chunk-OR5DRJCW.cjs');
5
5
 
6
6
 
7
7
 
8
8
  Object.defineProperty(exports, "AudioPlayer", {
9
9
  enumerable: true,
10
- get: function () { return chunkVWXGUNBR_cjs.AudioPlayer; }
10
+ get: function () { return chunkAKTUXJPI_cjs.AudioPlayer; }
11
11
  });
12
12
  Object.defineProperty(exports, "ProgressBar", {
13
13
  enumerable: true,
14
- get: function () { return chunkVWXGUNBR_cjs.ProgressBar; }
14
+ get: function () { return chunkAKTUXJPI_cjs.ProgressBar; }
15
15
  });
16
16
  Object.defineProperty(exports, "audioPlayerVariants", {
17
17
  enumerable: true,
18
- get: function () { return chunkVWXGUNBR_cjs.audioPlayerVariants; }
18
+ get: function () { return chunkAKTUXJPI_cjs.audioPlayerVariants; }
19
19
  });
20
20
  Object.defineProperty(exports, "formatAudioTime", {
21
21
  enumerable: true,
22
- get: function () { return chunkVWXGUNBR_cjs.formatTime; }
22
+ get: function () { return chunkAKTUXJPI_cjs.formatTime; }
23
23
  });
24
24
  Object.defineProperty(exports, "playButtonVariants", {
25
25
  enumerable: true,
26
- get: function () { return chunkVWXGUNBR_cjs.playButtonVariants; }
26
+ get: function () { return chunkAKTUXJPI_cjs.playButtonVariants; }
27
27
  });
28
28
  //# sourceMappingURL=index.cjs.map
29
29
  //# sourceMappingURL=index.cjs.map
@@ -26,6 +26,10 @@ interface AudioPlayerProps extends VariantProps<typeof audioPlayerVariants> {
26
26
  progressColor?: string;
27
27
  /** Height of the waveform (for waveform variant) */
28
28
  waveformHeight?: number;
29
+ /** Whether to show hover cursor on waveform for click-to-seek preview (for waveform variant) */
30
+ showWaveformHoverCursor?: boolean;
31
+ /** Color of the hover cursor line (for waveform variant) */
32
+ waveformCursorColor?: string;
29
33
  /** Whether the player is disabled */
30
34
  disabled?: boolean;
31
35
  /** Additional class name */
@@ -68,7 +72,7 @@ declare function ProgressBar({ currentTime, duration, onSeek, disabled, }: Progr
68
72
  * <AudioPlayer src="/audio.mp3" variant="waveform" showTime />
69
73
  * ```
70
74
  */
71
- declare function AudioPlayer({ src, title, variant, size, onStateChange, onEnded, onError, onTimeUpdate, showTime, showDuration, waveColor, progressColor, waveformHeight, disabled, className, 'aria-label': ariaLabel, playbackRates, showPlaybackRate,
75
+ declare function AudioPlayer({ src, title, variant, size, onStateChange, onEnded, onError, onTimeUpdate, showTime, showDuration, waveColor, progressColor, waveformHeight, showWaveformHoverCursor, waveformCursorColor, disabled, className, 'aria-label': ariaLabel, playbackRates, showPlaybackRate,
72
76
  /** Whether to preload audio (set to false for lists with many items) */
73
77
  preload,
74
78
  /** Fallback duration in seconds to display before audio is loaded */
@@ -26,6 +26,10 @@ interface AudioPlayerProps extends VariantProps<typeof audioPlayerVariants> {
26
26
  progressColor?: string;
27
27
  /** Height of the waveform (for waveform variant) */
28
28
  waveformHeight?: number;
29
+ /** Whether to show hover cursor on waveform for click-to-seek preview (for waveform variant) */
30
+ showWaveformHoverCursor?: boolean;
31
+ /** Color of the hover cursor line (for waveform variant) */
32
+ waveformCursorColor?: string;
29
33
  /** Whether the player is disabled */
30
34
  disabled?: boolean;
31
35
  /** Additional class name */
@@ -68,7 +72,7 @@ declare function ProgressBar({ currentTime, duration, onSeek, disabled, }: Progr
68
72
  * <AudioPlayer src="/audio.mp3" variant="waveform" showTime />
69
73
  * ```
70
74
  */
71
- declare function AudioPlayer({ src, title, variant, size, onStateChange, onEnded, onError, onTimeUpdate, showTime, showDuration, waveColor, progressColor, waveformHeight, disabled, className, 'aria-label': ariaLabel, playbackRates, showPlaybackRate,
75
+ declare function AudioPlayer({ src, title, variant, size, onStateChange, onEnded, onError, onTimeUpdate, showTime, showDuration, waveColor, progressColor, waveformHeight, showWaveformHoverCursor, waveformCursorColor, disabled, className, 'aria-label': ariaLabel, playbackRates, showPlaybackRate,
72
76
  /** Whether to preload audio (set to false for lists with many items) */
73
77
  preload,
74
78
  /** Fallback duration in seconds to display before audio is loaded */
@@ -1,4 +1,4 @@
1
- export { AudioPlayer, ProgressBar, audioPlayerVariants, formatTime as formatAudioTime, playButtonVariants } from '../../chunk-QBWVTJKF.js';
1
+ export { AudioPlayer, ProgressBar, audioPlayerVariants, formatTime as formatAudioTime, playButtonVariants } from '../../chunk-UBRDKNLQ.js';
2
2
  import '../../chunk-F3SOEIN2.js';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map