@nice2dev/ui-video 1.0.10

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,2046 @@
1
+ import { jsxs as a, jsx as e, Fragment as ae } from "react/jsx-runtime";
2
+ import { useState as p, useRef as T, useEffect as re, useCallback as le } from "react";
3
+ const ue = {
4
+ id: crypto.randomUUID(),
5
+ name: "Untitled Project",
6
+ resolution: { width: 1920, height: 1080, label: "1080p" },
7
+ frameRate: 30,
8
+ duration: 0,
9
+ tracks: [
10
+ {
11
+ id: "1",
12
+ type: "video",
13
+ name: "Video 1",
14
+ items: [],
15
+ muted: !1,
16
+ locked: !1,
17
+ visible: !0
18
+ },
19
+ {
20
+ id: "2",
21
+ type: "audio",
22
+ name: "Audio 1",
23
+ items: [],
24
+ muted: !1,
25
+ locked: !1,
26
+ visible: !0
27
+ }
28
+ ],
29
+ assets: [],
30
+ settings: {
31
+ backgroundColor: "#000000",
32
+ audio: { sampleRate: 48e3, channels: 2, bitrate: 320 },
33
+ video: { codec: "h264", bitrate: 8e3, profile: "high" }
34
+ }
35
+ }, me = [
36
+ { type: "blur", name: "Blur", icon: "🔵" },
37
+ { type: "brightness", name: "Brightness", icon: "☀️" },
38
+ { type: "contrast", name: "Contrast", icon: "◐" },
39
+ { type: "saturation", name: "Saturation", icon: "🎨" },
40
+ { type: "grayscale", name: "Grayscale", icon: "⬛" },
41
+ { type: "sepia", name: "Sepia", icon: "🟤" },
42
+ { type: "chromaKey", name: "Chroma Key", icon: "🟢" },
43
+ { type: "crop", name: "Crop", icon: "✂️" },
44
+ { type: "zoom", name: "Zoom", icon: "🔍" }
45
+ ], he = [
46
+ { type: "fade", name: "Fade" },
47
+ { type: "dissolve", name: "Dissolve" },
48
+ { type: "wipe", name: "Wipe" },
49
+ { type: "slide", name: "Slide" },
50
+ { type: "zoom", name: "Zoom" },
51
+ { type: "push", name: "Push" }
52
+ ], ge = ({
53
+ project: M,
54
+ onProjectChange: S,
55
+ onExport: D,
56
+ onAssetUpload: R,
57
+ className: F = ""
58
+ }) => {
59
+ const [c, J] = p(M || ue), [n, Q] = p(
60
+ "timeline"
61
+ ), [b, K] = p(null), [m, C] = p(null), [g, P] = p(0), [k, L] = p(!1), [x, U] = p(1), [q, V] = p(!0), [y, A] = p(null), X = T(null), ne = T(null), z = T(null);
62
+ re(() => {
63
+ M && J(M);
64
+ }, [M]), re(() => () => {
65
+ z.current && clearInterval(z.current);
66
+ }, []);
67
+ const f = le(
68
+ (s) => {
69
+ const r = { ...c, ...s };
70
+ J(r), S == null || S(r);
71
+ },
72
+ [c, S]
73
+ ), _ = async (s) => {
74
+ const r = [];
75
+ for (const u of Array.from(s)) {
76
+ const t = u.type.startsWith("video/") ? "video" : u.type.startsWith("audio/") ? "audio" : "image";
77
+ let i;
78
+ R ? i = await R(u) : i = {
79
+ id: crypto.randomUUID(),
80
+ type: t,
81
+ name: u.name,
82
+ url: URL.createObjectURL(u),
83
+ size: u.size
84
+ }, r.push(i);
85
+ }
86
+ f({ assets: [...c.assets, ...r] });
87
+ }, h = (s) => {
88
+ const r = {
89
+ id: crypto.randomUUID(),
90
+ type: s,
91
+ name: `${s.charAt(0).toUpperCase() + s.slice(1)} ${c.tracks.filter((u) => u.type === s).length + 1}`,
92
+ items: [],
93
+ muted: !1,
94
+ locked: !1,
95
+ visible: !0
96
+ };
97
+ f({ tracks: [...c.tracks, r] });
98
+ }, W = (s) => {
99
+ f({ tracks: c.tracks.filter((r) => r.id !== s) }), b === s && K(null);
100
+ }, G = (s) => {
101
+ f({
102
+ tracks: c.tracks.map((r) => r.id === s ? { ...r, muted: !r.muted } : r)
103
+ });
104
+ }, O = (s) => {
105
+ f({
106
+ tracks: c.tracks.map((r) => r.id === s ? { ...r, locked: !r.locked } : r)
107
+ });
108
+ }, ee = (s, r) => {
109
+ const u = c.tracks.find((d) => d.id === s);
110
+ if (!u || u.locked)
111
+ return;
112
+ const t = u.items[u.items.length - 1], i = t ? t.startTime + t.duration : 0, o = {
113
+ id: crypto.randomUUID(),
114
+ assetId: r.id,
115
+ type: r.type,
116
+ startTime: i,
117
+ duration: r.duration || 5,
118
+ offset: 0,
119
+ properties: {
120
+ x: 0,
121
+ y: 0,
122
+ opacity: 1,
123
+ scale: 1,
124
+ volume: 1
125
+ },
126
+ effects: [],
127
+ transitions: []
128
+ };
129
+ f({
130
+ tracks: c.tracks.map(
131
+ (d) => d.id === s ? { ...d, items: [...d.items, o] } : d
132
+ )
133
+ });
134
+ }, w = (s, r, u) => {
135
+ const t = {
136
+ id: crypto.randomUUID(),
137
+ type: u,
138
+ name: u.charAt(0).toUpperCase() + u.slice(1),
139
+ parameters: E(u)
140
+ };
141
+ f({
142
+ tracks: c.tracks.map(
143
+ (i) => i.id === s ? {
144
+ ...i,
145
+ items: i.items.map(
146
+ (o) => o.id === r ? { ...o, effects: [...o.effects, t] } : o
147
+ )
148
+ } : i
149
+ )
150
+ });
151
+ }, H = (s, r, u, t) => {
152
+ const i = {
153
+ id: crypto.randomUUID(),
154
+ type: u,
155
+ duration: 0.5,
156
+ position: t
157
+ };
158
+ f({
159
+ tracks: c.tracks.map(
160
+ (o) => o.id === s ? {
161
+ ...o,
162
+ items: o.items.map(
163
+ (d) => d.id === r ? { ...d, transitions: [...d.transitions, i] } : d
164
+ )
165
+ } : o
166
+ )
167
+ });
168
+ }, E = (s) => {
169
+ switch (s) {
170
+ case "blur":
171
+ return { radius: 5 };
172
+ case "brightness":
173
+ return { value: 100 };
174
+ case "contrast":
175
+ return { value: 100 };
176
+ case "saturation":
177
+ return { value: 100 };
178
+ case "grayscale":
179
+ return { amount: 100 };
180
+ case "sepia":
181
+ return { amount: 100 };
182
+ case "chromaKey":
183
+ return { color: "#00ff00", threshold: 40 };
184
+ case "crop":
185
+ return { top: 0, right: 0, bottom: 0, left: 0 };
186
+ case "zoom":
187
+ return { scale: 1, x: 0, y: 0 };
188
+ default:
189
+ return {};
190
+ }
191
+ }, ie = () => {
192
+ k ? (z.current && clearInterval(z.current), L(!1)) : (z.current = setInterval(() => {
193
+ P((s) => {
194
+ const r = Math.max(
195
+ ...c.tracks.flatMap((u) => u.items.map((t) => t.startTime + t.duration)),
196
+ 0
197
+ );
198
+ return s >= r ? (clearInterval(z.current), L(!1), 0) : s + 1 / c.frameRate;
199
+ });
200
+ }, 1e3 / c.frameRate), L(!0));
201
+ }, Y = (s) => {
202
+ P(Math.max(0, s));
203
+ }, te = async () => {
204
+ if (D) {
205
+ A(0);
206
+ try {
207
+ const s = setInterval(() => {
208
+ A((r) => r !== null && r < 90 ? r + Math.random() * 10 : r);
209
+ }, 500);
210
+ await D(c, c.settings.video.codec), clearInterval(s), A(100), setTimeout(() => A(null), 2e3);
211
+ } catch (s) {
212
+ A(null), console.error("Export failed:", s);
213
+ }
214
+ }
215
+ }, Z = (s) => {
216
+ const r = Math.floor(s / 60), u = Math.floor(s % 60), t = Math.floor(s % 1 * c.frameRate);
217
+ return `${r.toString().padStart(2, "0")}:${u.toString().padStart(2, "0")}:${t.toString().padStart(2, "0")}`;
218
+ }, j = () => {
219
+ for (const s of c.tracks) {
220
+ const r = s.items.find((u) => u.id === m);
221
+ if (r)
222
+ return { track: s, item: r };
223
+ }
224
+ return null;
225
+ };
226
+ return /* @__PURE__ */ a("div", { className: `nice-video-editor ${F}`, children: [
227
+ /* @__PURE__ */ a("header", { className: "video-editor__header", children: [
228
+ /* @__PURE__ */ a("div", { className: "header__project-info", children: [
229
+ /* @__PURE__ */ e(
230
+ "input",
231
+ {
232
+ type: "text",
233
+ value: c.name,
234
+ onChange: (s) => f({ name: s.target.value }),
235
+ className: "project-name-input"
236
+ }
237
+ ),
238
+ /* @__PURE__ */ a("span", { className: "project-settings", children: [
239
+ c.resolution.width,
240
+ "x",
241
+ c.resolution.height,
242
+ " • ",
243
+ c.frameRate,
244
+ "fps"
245
+ ] })
246
+ ] }),
247
+ /* @__PURE__ */ e("div", { className: "header__tabs", children: ["timeline", "effects", "transitions", "export"].map((s) => /* @__PURE__ */ e(
248
+ "button",
249
+ {
250
+ className: `tab-button ${n === s ? "tab-button--active" : ""}`,
251
+ onClick: () => Q(s),
252
+ children: s.charAt(0).toUpperCase() + s.slice(1)
253
+ },
254
+ s
255
+ )) }),
256
+ /* @__PURE__ */ e("div", { className: "header__actions", children: /* @__PURE__ */ e(
257
+ "button",
258
+ {
259
+ className: "action-button action-button--primary",
260
+ onClick: te,
261
+ disabled: y !== null,
262
+ children: y !== null ? `Exporting ${Math.round(y)}%` : "Export"
263
+ }
264
+ ) })
265
+ ] }),
266
+ /* @__PURE__ */ a("div", { className: "video-editor__main", children: [
267
+ q && /* @__PURE__ */ a("aside", { className: "video-editor__asset-library", children: [
268
+ /* @__PURE__ */ a("div", { className: "asset-library__header", children: [
269
+ /* @__PURE__ */ e("h3", { children: "Assets" }),
270
+ /* @__PURE__ */ e("button", { className: "close-button", onClick: () => V(!1), children: "×" })
271
+ ] }),
272
+ /* @__PURE__ */ e("div", { className: "asset-library__upload", children: /* @__PURE__ */ a("label", { className: "upload-zone", children: [
273
+ /* @__PURE__ */ e(
274
+ "input",
275
+ {
276
+ type: "file",
277
+ multiple: !0,
278
+ accept: "video/*,audio/*,image/*",
279
+ onChange: (s) => s.target.files && _(s.target.files),
280
+ hidden: !0
281
+ }
282
+ ),
283
+ /* @__PURE__ */ e("span", { className: "upload-icon", children: "+" }),
284
+ /* @__PURE__ */ e("span", { children: "Drop files or click to upload" })
285
+ ] }) }),
286
+ /* @__PURE__ */ e("div", { className: "asset-library__list", children: c.assets.map((s) => /* @__PURE__ */ a(
287
+ "div",
288
+ {
289
+ className: "asset-item",
290
+ draggable: !0,
291
+ onDragStart: (r) => r.dataTransfer.setData("assetId", s.id),
292
+ children: [
293
+ /* @__PURE__ */ e("div", { className: "asset-thumbnail", children: s.thumbnail ? /* @__PURE__ */ e("img", { src: s.thumbnail, alt: s.name }) : /* @__PURE__ */ e("span", { className: "asset-type-icon", children: s.type === "video" ? "🎬" : s.type === "audio" ? "🎵" : "🖼️" }) }),
294
+ /* @__PURE__ */ a("div", { className: "asset-info", children: [
295
+ /* @__PURE__ */ e("span", { className: "asset-name", children: s.name }),
296
+ /* @__PURE__ */ a("span", { className: "asset-meta", children: [
297
+ (s.size / 1024 / 1024).toFixed(1),
298
+ "MB"
299
+ ] })
300
+ ] })
301
+ ]
302
+ },
303
+ s.id
304
+ )) })
305
+ ] }),
306
+ /* @__PURE__ */ a("div", { className: "video-editor__preview-area", children: [
307
+ /* @__PURE__ */ a("div", { className: "preview-container", children: [
308
+ /* @__PURE__ */ a(
309
+ "div",
310
+ {
311
+ className: "preview-canvas",
312
+ style: { aspectRatio: `${c.resolution.width}/${c.resolution.height}` },
313
+ children: [
314
+ /* @__PURE__ */ e("video", { ref: ne, className: "preview-video" }),
315
+ /* @__PURE__ */ e("div", { className: "preview-overlay", children: !q && /* @__PURE__ */ e(
316
+ "button",
317
+ {
318
+ className: "toggle-library-button",
319
+ onClick: () => V(!0),
320
+ children: "📁"
321
+ }
322
+ ) })
323
+ ]
324
+ }
325
+ ),
326
+ /* @__PURE__ */ a("div", { className: "playback-controls", children: [
327
+ /* @__PURE__ */ e("button", { onClick: () => Y(0), children: "⏮️" }),
328
+ /* @__PURE__ */ e("button", { onClick: () => Y(g - 1 / c.frameRate), children: "⏪" }),
329
+ /* @__PURE__ */ e("button", { onClick: ie, className: "play-button", children: k ? "⏸️" : "▶️" }),
330
+ /* @__PURE__ */ e("button", { onClick: () => Y(g + 1 / c.frameRate), children: "⏩" }),
331
+ /* @__PURE__ */ e("span", { className: "time-display", children: Z(g) })
332
+ ] })
333
+ ] }),
334
+ m && n !== "export" && /* @__PURE__ */ e("div", { className: "item-inspector", children: (() => {
335
+ const s = j();
336
+ if (!s)
337
+ return null;
338
+ const { track: r, item: u } = s;
339
+ return /* @__PURE__ */ a(ae, { children: [
340
+ /* @__PURE__ */ e("h4", { children: "Item Properties" }),
341
+ /* @__PURE__ */ a("div", { className: "inspector-section", children: [
342
+ /* @__PURE__ */ a("label", { children: [
343
+ "Start Time",
344
+ /* @__PURE__ */ e(
345
+ "input",
346
+ {
347
+ type: "number",
348
+ step: "0.1",
349
+ value: u.startTime,
350
+ onChange: (t) => {
351
+ const i = parseFloat(t.target.value);
352
+ f({
353
+ tracks: c.tracks.map(
354
+ (o) => o.id === r.id ? {
355
+ ...o,
356
+ items: o.items.map(
357
+ (d) => d.id === u.id ? { ...d, startTime: i } : d
358
+ )
359
+ } : o
360
+ )
361
+ });
362
+ }
363
+ }
364
+ )
365
+ ] }),
366
+ /* @__PURE__ */ a("label", { children: [
367
+ "Duration",
368
+ /* @__PURE__ */ e(
369
+ "input",
370
+ {
371
+ type: "number",
372
+ step: "0.1",
373
+ value: u.duration,
374
+ onChange: (t) => {
375
+ const i = parseFloat(t.target.value);
376
+ f({
377
+ tracks: c.tracks.map(
378
+ (o) => o.id === r.id ? {
379
+ ...o,
380
+ items: o.items.map(
381
+ (d) => d.id === u.id ? { ...d, duration: i } : d
382
+ )
383
+ } : o
384
+ )
385
+ });
386
+ }
387
+ }
388
+ )
389
+ ] }),
390
+ /* @__PURE__ */ a("label", { children: [
391
+ "Opacity",
392
+ /* @__PURE__ */ e(
393
+ "input",
394
+ {
395
+ type: "range",
396
+ min: "0",
397
+ max: "1",
398
+ step: "0.1",
399
+ value: u.properties.opacity ?? 1,
400
+ onChange: (t) => {
401
+ const i = parseFloat(t.target.value);
402
+ f({
403
+ tracks: c.tracks.map(
404
+ (o) => o.id === r.id ? {
405
+ ...o,
406
+ items: o.items.map(
407
+ (d) => d.id === u.id ? {
408
+ ...d,
409
+ properties: { ...d.properties, opacity: i }
410
+ } : d
411
+ )
412
+ } : o
413
+ )
414
+ });
415
+ }
416
+ }
417
+ )
418
+ ] })
419
+ ] }),
420
+ /* @__PURE__ */ a("h4", { children: [
421
+ "Effects (",
422
+ u.effects.length,
423
+ ")"
424
+ ] }),
425
+ /* @__PURE__ */ e("div", { className: "effects-list", children: u.effects.map((t) => /* @__PURE__ */ e("div", { className: "effect-badge", children: t.name }, t.id)) })
426
+ ] });
427
+ })() })
428
+ ] })
429
+ ] }),
430
+ /* @__PURE__ */ a("div", { className: "video-editor__panel", children: [
431
+ n === "timeline" && /* @__PURE__ */ a("div", { className: "timeline-panel", children: [
432
+ /* @__PURE__ */ a("div", { className: "timeline-toolbar", children: [
433
+ /* @__PURE__ */ a("div", { className: "track-buttons", children: [
434
+ /* @__PURE__ */ e("button", { onClick: () => h("video"), children: "+ Video Track" }),
435
+ /* @__PURE__ */ e("button", { onClick: () => h("audio"), children: "+ Audio Track" }),
436
+ /* @__PURE__ */ e("button", { onClick: () => h("text"), children: "+ Text Track" })
437
+ ] }),
438
+ /* @__PURE__ */ a("div", { className: "zoom-controls", children: [
439
+ /* @__PURE__ */ e("button", { onClick: () => U(Math.max(0.25, x - 0.25)), children: "-" }),
440
+ /* @__PURE__ */ a("span", { children: [
441
+ Math.round(x * 100),
442
+ "%"
443
+ ] }),
444
+ /* @__PURE__ */ e("button", { onClick: () => U(Math.min(4, x + 0.25)), children: "+" })
445
+ ] })
446
+ ] }),
447
+ /* @__PURE__ */ a("div", { className: "timeline-container", ref: X, children: [
448
+ /* @__PURE__ */ e("div", { className: "timeline-ruler", children: Array.from({ length: Math.ceil(30 / x) }).map((s, r) => /* @__PURE__ */ e("div", { className: "ruler-mark", style: { left: `${r * 50 * x}px` }, children: Z(r) }, r)) }),
449
+ /* @__PURE__ */ e("div", { className: "timeline-playhead", style: { left: `${g * 50 * x}px` } }),
450
+ /* @__PURE__ */ e("div", { className: "timeline-tracks", children: c.tracks.map((s) => /* @__PURE__ */ a(
451
+ "div",
452
+ {
453
+ className: `timeline-track ${b === s.id ? "timeline-track--selected" : ""} ${s.locked ? "timeline-track--locked" : ""}`,
454
+ onClick: () => K(s.id),
455
+ onDrop: (r) => {
456
+ r.preventDefault();
457
+ const u = r.dataTransfer.getData("assetId"), t = c.assets.find((i) => i.id === u);
458
+ t && ee(s.id, t);
459
+ },
460
+ onDragOver: (r) => r.preventDefault(),
461
+ children: [
462
+ /* @__PURE__ */ a("div", { className: "track-header", children: [
463
+ /* @__PURE__ */ e("span", { className: "track-name", children: s.name }),
464
+ /* @__PURE__ */ a("div", { className: "track-controls", children: [
465
+ /* @__PURE__ */ e(
466
+ "button",
467
+ {
468
+ className: s.muted ? "active" : "",
469
+ onClick: (r) => {
470
+ r.stopPropagation(), G(s.id);
471
+ },
472
+ children: s.muted ? "🔇" : "🔊"
473
+ }
474
+ ),
475
+ /* @__PURE__ */ e(
476
+ "button",
477
+ {
478
+ className: s.locked ? "active" : "",
479
+ onClick: (r) => {
480
+ r.stopPropagation(), O(s.id);
481
+ },
482
+ children: s.locked ? "🔒" : "🔓"
483
+ }
484
+ ),
485
+ /* @__PURE__ */ e(
486
+ "button",
487
+ {
488
+ onClick: (r) => {
489
+ r.stopPropagation(), W(s.id);
490
+ },
491
+ children: "🗑️"
492
+ }
493
+ )
494
+ ] })
495
+ ] }),
496
+ /* @__PURE__ */ e("div", { className: "track-items", children: s.items.map((r) => {
497
+ const u = c.assets.find((t) => t.id === r.assetId);
498
+ return /* @__PURE__ */ a(
499
+ "div",
500
+ {
501
+ className: `track-item track-item--${r.type} ${m === r.id ? "track-item--selected" : ""}`,
502
+ style: {
503
+ left: `${r.startTime * 50 * x}px`,
504
+ width: `${r.duration * 50 * x}px`
505
+ },
506
+ onClick: (t) => {
507
+ t.stopPropagation(), C(r.id);
508
+ },
509
+ children: [
510
+ /* @__PURE__ */ e("span", { className: "item-name", children: (u == null ? void 0 : u.name) || "Untitled" }),
511
+ r.transitions.length > 0 && /* @__PURE__ */ e("span", { className: "item-transitions", children: "✨" }),
512
+ r.effects.length > 0 && /* @__PURE__ */ e("span", { className: "item-effects", children: "🎨" })
513
+ ]
514
+ },
515
+ r.id
516
+ );
517
+ }) })
518
+ ]
519
+ },
520
+ s.id
521
+ )) })
522
+ ] })
523
+ ] }),
524
+ n === "effects" && /* @__PURE__ */ a("div", { className: "effects-panel", children: [
525
+ /* @__PURE__ */ e("h3", { children: "Video Effects" }),
526
+ /* @__PURE__ */ e("p", { className: "panel-hint", children: "Select a clip to apply effects" }),
527
+ /* @__PURE__ */ e("div", { className: "effects-grid", children: me.map((s) => /* @__PURE__ */ a(
528
+ "button",
529
+ {
530
+ className: "effect-preset",
531
+ disabled: !m,
532
+ onClick: () => {
533
+ const r = j();
534
+ r && w(r.track.id, r.item.id, s.type);
535
+ },
536
+ children: [
537
+ /* @__PURE__ */ e("span", { className: "effect-icon", children: s.icon }),
538
+ /* @__PURE__ */ e("span", { className: "effect-name", children: s.name })
539
+ ]
540
+ },
541
+ s.type
542
+ )) })
543
+ ] }),
544
+ n === "transitions" && /* @__PURE__ */ a("div", { className: "transitions-panel", children: [
545
+ /* @__PURE__ */ e("h3", { children: "Transitions" }),
546
+ /* @__PURE__ */ e("p", { className: "panel-hint", children: "Select a clip and add transitions between clips" }),
547
+ /* @__PURE__ */ e("div", { className: "transitions-grid", children: he.map((s) => /* @__PURE__ */ a("div", { className: "transition-preset", children: [
548
+ /* @__PURE__ */ e("span", { className: "transition-name", children: s.name }),
549
+ /* @__PURE__ */ a("div", { className: "transition-buttons", children: [
550
+ /* @__PURE__ */ e(
551
+ "button",
552
+ {
553
+ disabled: !m,
554
+ onClick: () => {
555
+ const r = j();
556
+ r && H(
557
+ r.track.id,
558
+ r.item.id,
559
+ s.type,
560
+ "start"
561
+ );
562
+ },
563
+ children: "In"
564
+ }
565
+ ),
566
+ /* @__PURE__ */ e(
567
+ "button",
568
+ {
569
+ disabled: !m,
570
+ onClick: () => {
571
+ const r = j();
572
+ r && H(r.track.id, r.item.id, s.type, "end");
573
+ },
574
+ children: "Out"
575
+ }
576
+ )
577
+ ] })
578
+ ] }, s.type)) })
579
+ ] }),
580
+ n === "export" && /* @__PURE__ */ a("div", { className: "export-panel", children: [
581
+ /* @__PURE__ */ e("h3", { children: "Export Settings" }),
582
+ /* @__PURE__ */ a("div", { className: "export-settings", children: [
583
+ /* @__PURE__ */ a("div", { className: "setting-group", children: [
584
+ /* @__PURE__ */ e("label", { children: "Resolution" }),
585
+ /* @__PURE__ */ a(
586
+ "select",
587
+ {
588
+ value: `${c.resolution.width}x${c.resolution.height}`,
589
+ onChange: (s) => {
590
+ const [r, u] = s.target.value.split("x").map(Number);
591
+ f({ resolution: { width: r, height: u } });
592
+ },
593
+ children: [
594
+ /* @__PURE__ */ e("option", { value: "1920x1080", children: "1080p (1920x1080)" }),
595
+ /* @__PURE__ */ e("option", { value: "2560x1440", children: "1440p (2560x1440)" }),
596
+ /* @__PURE__ */ e("option", { value: "3840x2160", children: "4K (3840x2160)" }),
597
+ /* @__PURE__ */ e("option", { value: "1280x720", children: "720p (1280x720)" })
598
+ ]
599
+ }
600
+ )
601
+ ] }),
602
+ /* @__PURE__ */ a("div", { className: "setting-group", children: [
603
+ /* @__PURE__ */ e("label", { children: "Frame Rate" }),
604
+ /* @__PURE__ */ a(
605
+ "select",
606
+ {
607
+ value: c.frameRate,
608
+ onChange: (s) => f({ frameRate: parseInt(s.target.value) }),
609
+ children: [
610
+ /* @__PURE__ */ e("option", { value: "24", children: "24 fps" }),
611
+ /* @__PURE__ */ e("option", { value: "30", children: "30 fps" }),
612
+ /* @__PURE__ */ e("option", { value: "60", children: "60 fps" }),
613
+ /* @__PURE__ */ e("option", { value: "120", children: "120 fps" })
614
+ ]
615
+ }
616
+ )
617
+ ] }),
618
+ /* @__PURE__ */ a("div", { className: "setting-group", children: [
619
+ /* @__PURE__ */ e("label", { children: "Video Codec" }),
620
+ /* @__PURE__ */ a(
621
+ "select",
622
+ {
623
+ value: c.settings.video.codec,
624
+ onChange: (s) => f({
625
+ settings: {
626
+ ...c.settings,
627
+ video: {
628
+ ...c.settings.video,
629
+ codec: s.target.value
630
+ }
631
+ }
632
+ }),
633
+ children: [
634
+ /* @__PURE__ */ e("option", { value: "h264", children: "H.264 (Best Compatibility)" }),
635
+ /* @__PURE__ */ e("option", { value: "h265", children: "H.265/HEVC (Smaller Size)" }),
636
+ /* @__PURE__ */ e("option", { value: "vp9", children: "VP9 (Web Optimized)" }),
637
+ /* @__PURE__ */ e("option", { value: "av1", children: "AV1 (Future Standard)" })
638
+ ]
639
+ }
640
+ )
641
+ ] }),
642
+ /* @__PURE__ */ a("div", { className: "setting-group", children: [
643
+ /* @__PURE__ */ e("label", { children: "Video Bitrate (Mbps)" }),
644
+ /* @__PURE__ */ e(
645
+ "input",
646
+ {
647
+ type: "number",
648
+ value: c.settings.video.bitrate / 1e3,
649
+ onChange: (s) => f({
650
+ settings: {
651
+ ...c.settings,
652
+ video: {
653
+ ...c.settings.video,
654
+ bitrate: parseFloat(s.target.value) * 1e3
655
+ }
656
+ }
657
+ }),
658
+ min: "1",
659
+ max: "100"
660
+ }
661
+ )
662
+ ] })
663
+ ] }),
664
+ /* @__PURE__ */ e(
665
+ "button",
666
+ {
667
+ className: "export-button",
668
+ onClick: te,
669
+ disabled: y !== null,
670
+ children: y !== null ? `Exporting... ${Math.round(y)}%` : "Export Video"
671
+ }
672
+ ),
673
+ y !== null && /* @__PURE__ */ e("div", { className: "export-progress", children: /* @__PURE__ */ e("div", { className: "export-progress-bar", style: { width: `${y}%` } }) })
674
+ ] })
675
+ ] })
676
+ ] });
677
+ }, pe = {
678
+ video: {
679
+ source: "screen",
680
+ showCursor: !0,
681
+ frameRate: 30,
682
+ resolution: { width: 1920, height: 1080 }
683
+ },
684
+ audio: {
685
+ enabled: !0,
686
+ source: "both",
687
+ echoCancellation: !0,
688
+ noiseSuppression: !0
689
+ },
690
+ output: {
691
+ format: "webm",
692
+ quality: "high"
693
+ }
694
+ }, Ne = ({
695
+ options: M,
696
+ onRecordingStart: S,
697
+ onRecordingStop: D,
698
+ onRecordingPause: R,
699
+ onRecordingResume: F,
700
+ onError: c,
701
+ className: J = ""
702
+ }) => {
703
+ var d, I;
704
+ const [n, Q] = p({
705
+ ...pe,
706
+ ...M
707
+ }), [b, K] = p(null), [m, C] = p("idle"), [g, P] = p([]), [k, L] = p(null), [x, U] = p(null), [q, V] = p(!1), [y, A] = p(!1), [X, ne] = p(
708
+ "pen"
709
+ ), [z, f] = p("#ff0000"), _ = T(null), h = T([]), W = T(null), G = T(null), O = T(null), ee = T(0);
710
+ re(() => () => {
711
+ k && k.getTracks().forEach((l) => l.stop()), O.current && clearInterval(O.current);
712
+ }, [k]);
713
+ const w = (l) => {
714
+ Q((v) => ({
715
+ ...v,
716
+ ...l,
717
+ video: { ...v.video, ...l.video },
718
+ audio: { ...v.audio, ...l.audio },
719
+ output: { ...v.output, ...l.output }
720
+ }));
721
+ }, H = async () => {
722
+ try {
723
+ C("preparing");
724
+ const l = {
725
+ video: {
726
+ cursor: n.video.showCursor ? "always" : "never",
727
+ frameRate: n.video.frameRate
728
+ },
729
+ audio: n.audio.source === "system" || n.audio.source === "both"
730
+ }, v = await navigator.mediaDevices.getDisplayMedia(l);
731
+ if (n.audio.enabled && (n.audio.source === "microphone" || n.audio.source === "both"))
732
+ try {
733
+ (await navigator.mediaDevices.getUserMedia({
734
+ audio: {
735
+ echoCancellation: n.audio.echoCancellation,
736
+ noiseSuppression: n.audio.noiseSuppression
737
+ }
738
+ })).getAudioTracks().forEach(($) => v.addTrack($));
739
+ } catch (N) {
740
+ console.warn("Could not access microphone:", N);
741
+ }
742
+ L(v), W.current && (W.current.srcObject = v, W.current.play()), C("idle");
743
+ } catch (l) {
744
+ C("error"), c == null || c(l instanceof Error ? l : new Error("Failed to start preview"));
745
+ }
746
+ }, E = async () => {
747
+ k || await H();
748
+ for (let l = 3; l > 0; l--)
749
+ U(l), await new Promise((v) => setTimeout(v, 1e3));
750
+ U(null);
751
+ try {
752
+ const l = k || await ie();
753
+ if (!l)
754
+ throw new Error("No stream available");
755
+ const v = r(n.output.format), N = new MediaRecorder(l, {
756
+ mimeType: v,
757
+ videoBitsPerSecond: u(n.output.quality)
758
+ });
759
+ h.current = [], N.ondataavailable = (B) => {
760
+ B.data.size > 0 && h.current.push(B.data);
761
+ }, N.onstop = () => {
762
+ const B = new Blob(h.current, { type: v });
763
+ b && (D == null || D({ ...b, status: "stopped" }, B));
764
+ }, _.current = N, N.start(1e3), ee.current = Date.now();
765
+ const $ = {
766
+ id: crypto.randomUUID(),
767
+ status: "recording",
768
+ startTime: /* @__PURE__ */ new Date(),
769
+ duration: 0,
770
+ size: 0,
771
+ options: n,
772
+ chunks: []
773
+ };
774
+ K($), C("recording"), S == null || S($), O.current = setInterval(() => {
775
+ K(
776
+ (B) => B ? {
777
+ ...B,
778
+ duration: (Date.now() - ee.current) / 1e3,
779
+ size: h.current.reduce((ce, de) => ce + de.size, 0)
780
+ } : null
781
+ );
782
+ }, 100);
783
+ } catch (l) {
784
+ C("error"), c == null || c(l instanceof Error ? l : new Error("Failed to start recording"));
785
+ }
786
+ }, ie = async () => (await H(), k), Y = () => {
787
+ _.current && m === "recording" && (_.current.pause(), C("paused"), R == null || R());
788
+ }, te = () => {
789
+ _.current && m === "paused" && (_.current.resume(), C("recording"), F == null || F());
790
+ }, Z = () => {
791
+ O.current && clearInterval(O.current), _.current && (m === "recording" || m === "paused") && (_.current.stop(), C("stopped")), k && (k.getTracks().forEach((l) => l.stop()), L(null));
792
+ }, j = le(
793
+ (l) => {
794
+ if (m !== "recording")
795
+ return;
796
+ const v = {
797
+ id: crypto.randomUUID(),
798
+ time: (b == null ? void 0 : b.duration) || 0,
799
+ label: l || `Marker ${g.length + 1}`,
800
+ color: t()
801
+ };
802
+ P((N) => [...N, v]);
803
+ },
804
+ [m, b == null ? void 0 : b.duration, g.length]
805
+ ), s = (l) => {
806
+ P((v) => v.filter((N) => N.id !== l));
807
+ }, r = (l) => {
808
+ switch (l) {
809
+ case "mp4":
810
+ return "video/mp4";
811
+ case "mkv":
812
+ return "video/x-matroska";
813
+ default:
814
+ return "video/webm;codecs=vp9";
815
+ }
816
+ }, u = (l) => {
817
+ switch (l) {
818
+ case "low":
819
+ return 25e5;
820
+ case "medium":
821
+ return 5e6;
822
+ case "lossless":
823
+ return 2e7;
824
+ default:
825
+ return 8e6;
826
+ }
827
+ }, t = () => {
828
+ const l = ["#ff4444", "#44ff44", "#4444ff", "#ffff44", "#ff44ff", "#44ffff"];
829
+ return l[Math.floor(Math.random() * l.length)];
830
+ }, i = (l) => {
831
+ const v = Math.floor(l / 3600), N = Math.floor(l % 3600 / 60), $ = Math.floor(l % 60), B = Math.floor(l % 1 * 100);
832
+ return v > 0 ? `${v}:${N.toString().padStart(2, "0")}:${$.toString().padStart(2, "0")}` : `${N.toString().padStart(2, "0")}:${$.toString().padStart(2, "0")}.${B.toString().padStart(2, "0")}`;
833
+ }, o = (l) => l < 1024 ? `${l} B` : l < 1024 * 1024 ? `${(l / 1024).toFixed(1)} KB` : `${(l / 1024 / 1024).toFixed(1)} MB`;
834
+ return /* @__PURE__ */ a("div", { className: `nice-screen-recorder ${J}`, children: [
835
+ /* @__PURE__ */ a("div", { className: "recorder__preview", children: [
836
+ x !== null && /* @__PURE__ */ e("div", { className: "countdown-overlay", children: /* @__PURE__ */ e("span", { className: "countdown-number", children: x }) }),
837
+ /* @__PURE__ */ e("video", { ref: W, className: "preview-video", muted: !0, playsInline: !0 }),
838
+ y && /* @__PURE__ */ e("canvas", { ref: G, className: "annotation-canvas" }),
839
+ !k && m === "idle" && /* @__PURE__ */ e("div", { className: "preview-placeholder", children: /* @__PURE__ */ a("button", { className: "start-preview-button", onClick: H, children: [
840
+ /* @__PURE__ */ e("span", { className: "icon", children: "🖥️" }),
841
+ /* @__PURE__ */ e("span", { children: "Select Screen to Record" })
842
+ ] }) }),
843
+ m === "recording" && /* @__PURE__ */ a("div", { className: "recording-indicator", children: [
844
+ /* @__PURE__ */ e("span", { className: "recording-dot" }),
845
+ /* @__PURE__ */ e("span", { children: "REC" })
846
+ ] })
847
+ ] }),
848
+ /* @__PURE__ */ a("div", { className: "recorder__controls", children: [
849
+ /* @__PURE__ */ a("div", { className: "controls__main", children: [
850
+ m === "idle" && /* @__PURE__ */ a(
851
+ "button",
852
+ {
853
+ className: "control-button control-button--record",
854
+ onClick: E,
855
+ disabled: !!x,
856
+ children: [
857
+ /* @__PURE__ */ e("span", { className: "icon", children: "⏺️" }),
858
+ /* @__PURE__ */ e("span", { children: "Start Recording" })
859
+ ]
860
+ }
861
+ ),
862
+ m === "recording" && /* @__PURE__ */ a(ae, { children: [
863
+ /* @__PURE__ */ a("button", { className: "control-button control-button--pause", onClick: Y, children: [
864
+ /* @__PURE__ */ e("span", { className: "icon", children: "⏸️" }),
865
+ /* @__PURE__ */ e("span", { children: "Pause" })
866
+ ] }),
867
+ /* @__PURE__ */ a("button", { className: "control-button control-button--stop", onClick: Z, children: [
868
+ /* @__PURE__ */ e("span", { className: "icon", children: "⏹️" }),
869
+ /* @__PURE__ */ e("span", { children: "Stop" })
870
+ ] })
871
+ ] }),
872
+ m === "paused" && /* @__PURE__ */ a(ae, { children: [
873
+ /* @__PURE__ */ a("button", { className: "control-button control-button--resume", onClick: te, children: [
874
+ /* @__PURE__ */ e("span", { className: "icon", children: "▶️" }),
875
+ /* @__PURE__ */ e("span", { children: "Resume" })
876
+ ] }),
877
+ /* @__PURE__ */ a("button", { className: "control-button control-button--stop", onClick: Z, children: [
878
+ /* @__PURE__ */ e("span", { className: "icon", children: "⏹️" }),
879
+ /* @__PURE__ */ e("span", { children: "Stop" })
880
+ ] })
881
+ ] }),
882
+ m === "stopped" && /* @__PURE__ */ a(
883
+ "button",
884
+ {
885
+ className: "control-button control-button--new",
886
+ onClick: () => {
887
+ C("idle"), K(null), P([]);
888
+ },
889
+ children: [
890
+ /* @__PURE__ */ e("span", { className: "icon", children: "🔄" }),
891
+ /* @__PURE__ */ e("span", { children: "New Recording" })
892
+ ]
893
+ }
894
+ )
895
+ ] }),
896
+ /* @__PURE__ */ a("div", { className: "controls__secondary", children: [
897
+ (m === "recording" || m === "paused") && /* @__PURE__ */ a("button", { className: "control-button control-button--marker", onClick: () => j(), children: [
898
+ /* @__PURE__ */ e("span", { className: "icon", children: "🚩" }),
899
+ /* @__PURE__ */ e("span", { children: "Add Marker" })
900
+ ] }),
901
+ /* @__PURE__ */ a(
902
+ "button",
903
+ {
904
+ className: `control-button ${y ? "control-button--active" : ""}`,
905
+ onClick: () => A(!y),
906
+ disabled: m !== "recording",
907
+ children: [
908
+ /* @__PURE__ */ e("span", { className: "icon", children: "✏️" }),
909
+ /* @__PURE__ */ e("span", { children: "Annotate" })
910
+ ]
911
+ }
912
+ ),
913
+ /* @__PURE__ */ e(
914
+ "button",
915
+ {
916
+ className: "control-button control-button--settings",
917
+ onClick: () => V(!q),
918
+ disabled: m === "recording",
919
+ children: /* @__PURE__ */ e("span", { className: "icon", children: "⚙️" })
920
+ }
921
+ )
922
+ ] })
923
+ ] }),
924
+ /* @__PURE__ */ a("div", { className: "recorder__status", children: [
925
+ /* @__PURE__ */ a("div", { className: "status__info", children: [
926
+ /* @__PURE__ */ a("span", { className: "status-item", children: [
927
+ /* @__PURE__ */ e("strong", { children: "Duration:" }),
928
+ " ",
929
+ i((b == null ? void 0 : b.duration) || 0)
930
+ ] }),
931
+ /* @__PURE__ */ a("span", { className: "status-item", children: [
932
+ /* @__PURE__ */ e("strong", { children: "Size:" }),
933
+ " ",
934
+ o((b == null ? void 0 : b.size) || 0)
935
+ ] }),
936
+ /* @__PURE__ */ a("span", { className: "status-item", children: [
937
+ /* @__PURE__ */ e("strong", { children: "Markers:" }),
938
+ " ",
939
+ g.length
940
+ ] })
941
+ ] }),
942
+ /* @__PURE__ */ a("div", { className: "status__quality", children: [
943
+ n.video.resolution && /* @__PURE__ */ a("span", { children: [
944
+ n.video.resolution.width,
945
+ "x",
946
+ n.video.resolution.height
947
+ ] }),
948
+ /* @__PURE__ */ a("span", { children: [
949
+ n.video.frameRate,
950
+ "fps"
951
+ ] }),
952
+ /* @__PURE__ */ e("span", { className: n.audio.enabled ? "audio-on" : "audio-off", children: n.audio.enabled ? "🔊" : "🔇" })
953
+ ] })
954
+ ] }),
955
+ y && m === "recording" && /* @__PURE__ */ a("div", { className: "recorder__annotation-tools", children: [
956
+ /* @__PURE__ */ e("div", { className: "tool-group", children: ["pen", "arrow", "rectangle", "text"].map((l) => /* @__PURE__ */ a(
957
+ "button",
958
+ {
959
+ className: `tool-button ${X === l ? "tool-button--active" : ""}`,
960
+ onClick: () => ne(l),
961
+ children: [
962
+ l === "pen" && "✏️",
963
+ l === "arrow" && "➡️",
964
+ l === "rectangle" && "⬜",
965
+ l === "text" && "T"
966
+ ]
967
+ },
968
+ l
969
+ )) }),
970
+ /* @__PURE__ */ e("div", { className: "color-group", children: ["#ff0000", "#00ff00", "#0000ff", "#ffff00", "#ffffff", "#000000"].map((l) => /* @__PURE__ */ e(
971
+ "button",
972
+ {
973
+ className: `color-button ${z === l ? "color-button--active" : ""}`,
974
+ style: { backgroundColor: l },
975
+ onClick: () => f(l)
976
+ },
977
+ l
978
+ )) })
979
+ ] }),
980
+ g.length > 0 && /* @__PURE__ */ a("div", { className: "recorder__markers", children: [
981
+ /* @__PURE__ */ e("h4", { children: "Markers" }),
982
+ /* @__PURE__ */ e("div", { className: "markers-list", children: g.map((l) => /* @__PURE__ */ a(
983
+ "div",
984
+ {
985
+ className: "marker-item",
986
+ style: { borderLeftColor: l.color },
987
+ children: [
988
+ /* @__PURE__ */ e("span", { className: "marker-time", children: i(l.time) }),
989
+ /* @__PURE__ */ e(
990
+ "input",
991
+ {
992
+ type: "text",
993
+ value: l.label,
994
+ onChange: (v) => {
995
+ P(
996
+ (N) => N.map(($) => $.id === l.id ? { ...$, label: v.target.value } : $)
997
+ );
998
+ },
999
+ className: "marker-label"
1000
+ }
1001
+ ),
1002
+ /* @__PURE__ */ e("button", { className: "marker-remove", onClick: () => s(l.id), children: "×" })
1003
+ ]
1004
+ },
1005
+ l.id
1006
+ )) })
1007
+ ] }),
1008
+ q && /* @__PURE__ */ a("div", { className: "recorder__settings", children: [
1009
+ /* @__PURE__ */ a("div", { className: "settings-header", children: [
1010
+ /* @__PURE__ */ e("h3", { children: "Recording Settings" }),
1011
+ /* @__PURE__ */ e("button", { className: "close-button", onClick: () => V(!1), children: "×" })
1012
+ ] }),
1013
+ /* @__PURE__ */ a("div", { className: "settings-section", children: [
1014
+ /* @__PURE__ */ e("h4", { children: "Video" }),
1015
+ /* @__PURE__ */ a("label", { children: [
1016
+ "Source",
1017
+ /* @__PURE__ */ a(
1018
+ "select",
1019
+ {
1020
+ value: n.video.source,
1021
+ onChange: (l) => w({
1022
+ video: {
1023
+ ...n.video,
1024
+ source: l.target.value
1025
+ }
1026
+ }),
1027
+ children: [
1028
+ /* @__PURE__ */ e("option", { value: "screen", children: "Entire Screen" }),
1029
+ /* @__PURE__ */ e("option", { value: "window", children: "Application Window" }),
1030
+ /* @__PURE__ */ e("option", { value: "tab", children: "Browser Tab" }),
1031
+ /* @__PURE__ */ e("option", { value: "camera", children: "Camera" })
1032
+ ]
1033
+ }
1034
+ )
1035
+ ] }),
1036
+ /* @__PURE__ */ a("label", { children: [
1037
+ "Resolution",
1038
+ /* @__PURE__ */ a(
1039
+ "select",
1040
+ {
1041
+ value: `${(d = n.video.resolution) == null ? void 0 : d.width}x${(I = n.video.resolution) == null ? void 0 : I.height}`,
1042
+ onChange: (l) => {
1043
+ const [v, N] = l.target.value.split("x").map(Number);
1044
+ w({
1045
+ video: { ...n.video, resolution: { width: v, height: N } }
1046
+ });
1047
+ },
1048
+ children: [
1049
+ /* @__PURE__ */ e("option", { value: "1920x1080", children: "1080p (1920x1080)" }),
1050
+ /* @__PURE__ */ e("option", { value: "2560x1440", children: "1440p (2560x1440)" }),
1051
+ /* @__PURE__ */ e("option", { value: "3840x2160", children: "4K (3840x2160)" }),
1052
+ /* @__PURE__ */ e("option", { value: "1280x720", children: "720p (1280x720)" })
1053
+ ]
1054
+ }
1055
+ )
1056
+ ] }),
1057
+ /* @__PURE__ */ a("label", { children: [
1058
+ "Frame Rate",
1059
+ /* @__PURE__ */ a(
1060
+ "select",
1061
+ {
1062
+ value: n.video.frameRate,
1063
+ onChange: (l) => w({
1064
+ video: { ...n.video, frameRate: parseInt(l.target.value) }
1065
+ }),
1066
+ children: [
1067
+ /* @__PURE__ */ e("option", { value: "15", children: "15 fps" }),
1068
+ /* @__PURE__ */ e("option", { value: "24", children: "24 fps" }),
1069
+ /* @__PURE__ */ e("option", { value: "30", children: "30 fps" }),
1070
+ /* @__PURE__ */ e("option", { value: "60", children: "60 fps" })
1071
+ ]
1072
+ }
1073
+ )
1074
+ ] }),
1075
+ /* @__PURE__ */ a("label", { className: "checkbox-label", children: [
1076
+ /* @__PURE__ */ e(
1077
+ "input",
1078
+ {
1079
+ type: "checkbox",
1080
+ checked: n.video.showCursor,
1081
+ onChange: (l) => w({
1082
+ video: { ...n.video, showCursor: l.target.checked }
1083
+ })
1084
+ }
1085
+ ),
1086
+ "Show Cursor"
1087
+ ] })
1088
+ ] }),
1089
+ /* @__PURE__ */ a("div", { className: "settings-section", children: [
1090
+ /* @__PURE__ */ e("h4", { children: "Audio" }),
1091
+ /* @__PURE__ */ a("label", { className: "checkbox-label", children: [
1092
+ /* @__PURE__ */ e(
1093
+ "input",
1094
+ {
1095
+ type: "checkbox",
1096
+ checked: n.audio.enabled,
1097
+ onChange: (l) => w({
1098
+ audio: { ...n.audio, enabled: l.target.checked }
1099
+ })
1100
+ }
1101
+ ),
1102
+ "Enable Audio"
1103
+ ] }),
1104
+ n.audio.enabled && /* @__PURE__ */ a(ae, { children: [
1105
+ /* @__PURE__ */ a("label", { children: [
1106
+ "Source",
1107
+ /* @__PURE__ */ a(
1108
+ "select",
1109
+ {
1110
+ value: n.audio.source,
1111
+ onChange: (l) => w({
1112
+ audio: {
1113
+ ...n.audio,
1114
+ source: l.target.value
1115
+ }
1116
+ }),
1117
+ children: [
1118
+ /* @__PURE__ */ e("option", { value: "system", children: "System Audio" }),
1119
+ /* @__PURE__ */ e("option", { value: "microphone", children: "Microphone" }),
1120
+ /* @__PURE__ */ e("option", { value: "both", children: "Both" })
1121
+ ]
1122
+ }
1123
+ )
1124
+ ] }),
1125
+ /* @__PURE__ */ a("label", { className: "checkbox-label", children: [
1126
+ /* @__PURE__ */ e(
1127
+ "input",
1128
+ {
1129
+ type: "checkbox",
1130
+ checked: n.audio.echoCancellation,
1131
+ onChange: (l) => w({
1132
+ audio: { ...n.audio, echoCancellation: l.target.checked }
1133
+ })
1134
+ }
1135
+ ),
1136
+ "Echo Cancellation"
1137
+ ] }),
1138
+ /* @__PURE__ */ a("label", { className: "checkbox-label", children: [
1139
+ /* @__PURE__ */ e(
1140
+ "input",
1141
+ {
1142
+ type: "checkbox",
1143
+ checked: n.audio.noiseSuppression,
1144
+ onChange: (l) => w({
1145
+ audio: { ...n.audio, noiseSuppression: l.target.checked }
1146
+ })
1147
+ }
1148
+ ),
1149
+ "Noise Suppression"
1150
+ ] })
1151
+ ] })
1152
+ ] }),
1153
+ /* @__PURE__ */ a("div", { className: "settings-section", children: [
1154
+ /* @__PURE__ */ e("h4", { children: "Output" }),
1155
+ /* @__PURE__ */ a("label", { children: [
1156
+ "Format",
1157
+ /* @__PURE__ */ a(
1158
+ "select",
1159
+ {
1160
+ value: n.output.format,
1161
+ onChange: (l) => w({
1162
+ output: { ...n.output, format: l.target.value }
1163
+ }),
1164
+ children: [
1165
+ /* @__PURE__ */ e("option", { value: "webm", children: "WebM (Best Web)" }),
1166
+ /* @__PURE__ */ e("option", { value: "mp4", children: "MP4 (Most Compatible)" }),
1167
+ /* @__PURE__ */ e("option", { value: "mkv", children: "MKV (Lossless)" })
1168
+ ]
1169
+ }
1170
+ )
1171
+ ] }),
1172
+ /* @__PURE__ */ a("label", { children: [
1173
+ "Quality",
1174
+ /* @__PURE__ */ a(
1175
+ "select",
1176
+ {
1177
+ value: n.output.quality,
1178
+ onChange: (l) => w({
1179
+ output: {
1180
+ ...n.output,
1181
+ quality: l.target.value
1182
+ }
1183
+ }),
1184
+ children: [
1185
+ /* @__PURE__ */ e("option", { value: "low", children: "Low (Smaller file)" }),
1186
+ /* @__PURE__ */ e("option", { value: "medium", children: "Medium" }),
1187
+ /* @__PURE__ */ e("option", { value: "high", children: "High (Recommended)" }),
1188
+ /* @__PURE__ */ e("option", { value: "lossless", children: "Lossless (Largest file)" })
1189
+ ]
1190
+ }
1191
+ )
1192
+ ] })
1193
+ ] })
1194
+ ] })
1195
+ ] });
1196
+ }, ve = {
1197
+ id: crypto.randomUUID(),
1198
+ name: "My Stream",
1199
+ protocol: "rtmp",
1200
+ destinations: [],
1201
+ sources: [],
1202
+ layout: {
1203
+ name: "Default",
1204
+ canvas: { width: 1920, height: 1080, backgroundColor: "#000000" },
1205
+ layers: []
1206
+ },
1207
+ settings: {
1208
+ video: {
1209
+ resolution: { width: 1920, height: 1080 },
1210
+ frameRate: 30,
1211
+ codec: "h264",
1212
+ bitrate: 6e3,
1213
+ keyframe: 2,
1214
+ profile: "high"
1215
+ },
1216
+ audio: {
1217
+ sampleRate: 48e3,
1218
+ bitrate: 160,
1219
+ channels: 2,
1220
+ codec: "aac"
1221
+ }
1222
+ }
1223
+ }, oe = [
1224
+ {
1225
+ platform: "youtube",
1226
+ name: "YouTube",
1227
+ icon: "📺",
1228
+ defaultUrl: "rtmp://a.rtmp.youtube.com/live2"
1229
+ },
1230
+ { platform: "twitch", name: "Twitch", icon: "🎮", defaultUrl: "rtmp://live.twitch.tv/app" },
1231
+ {
1232
+ platform: "facebook",
1233
+ name: "Facebook",
1234
+ icon: "📘",
1235
+ defaultUrl: "rtmps://live-api-s.facebook.com:443/rtmp"
1236
+ },
1237
+ { platform: "custom-rtmp", name: "Custom RTMP", icon: "🔗", defaultUrl: "" },
1238
+ { platform: "custom-srt", name: "Custom SRT", icon: "🔒", defaultUrl: "" }
1239
+ ], se = [
1240
+ { type: "camera", name: "Camera", icon: "📷" },
1241
+ { type: "screen", name: "Screen Capture", icon: "🖥️" },
1242
+ { type: "window", name: "Window Capture", icon: "🪟" },
1243
+ { type: "browser", name: "Browser Source", icon: "🌐" },
1244
+ { type: "image", name: "Image", icon: "🖼️" },
1245
+ { type: "video", name: "Video", icon: "🎬" },
1246
+ { type: "microphone", name: "Microphone", icon: "🎤" },
1247
+ { type: "system-audio", name: "System Audio", icon: "🔊" }
1248
+ ], ye = ({
1249
+ config: M,
1250
+ onConfigChange: S,
1251
+ onStreamStart: D,
1252
+ onStreamStop: R,
1253
+ onStatsUpdate: F,
1254
+ onError: c,
1255
+ className: J = ""
1256
+ }) => {
1257
+ const [n, Q] = p(M || ve), [b, K] = p(
1258
+ "sources"
1259
+ ), [m, C] = p(!1), [g, P] = p({
1260
+ duration: 0,
1261
+ viewers: 0,
1262
+ peakViewers: 0,
1263
+ bitrate: 0,
1264
+ fps: 0,
1265
+ droppedFrames: 0,
1266
+ cpuUsage: 0,
1267
+ memoryUsage: 0
1268
+ }), [k, L] = p(null), [x, U] = p(!1), [q, V] = p(!1), [y, A] = p([n.layout]), [X, ne] = p(0), z = T(null), f = T(null), _ = T(0);
1269
+ re(() => {
1270
+ M && Q(M);
1271
+ }, [M]), re(() => () => {
1272
+ f.current && clearInterval(f.current);
1273
+ }, []);
1274
+ const h = le(
1275
+ (t) => {
1276
+ const i = { ...n, ...t };
1277
+ Q(i), S == null || S(i);
1278
+ },
1279
+ [n, S]
1280
+ ), W = (t) => {
1281
+ const i = oe.find((d) => d.platform === t), o = {
1282
+ id: crypto.randomUUID(),
1283
+ name: (i == null ? void 0 : i.name) || "Custom",
1284
+ platform: t,
1285
+ url: (i == null ? void 0 : i.defaultUrl) || "",
1286
+ streamKey: "",
1287
+ enabled: !0,
1288
+ status: "idle"
1289
+ };
1290
+ h({ destinations: [...n.destinations, o] }), V(!1);
1291
+ }, G = (t, i) => {
1292
+ h({
1293
+ destinations: n.destinations.map((o) => o.id === t ? { ...o, ...i } : o)
1294
+ });
1295
+ }, O = (t) => {
1296
+ h({ destinations: n.destinations.filter((i) => i.id !== t) });
1297
+ }, ee = async (t) => {
1298
+ const i = se.find((I) => I.type === t), o = {
1299
+ id: crypto.randomUUID(),
1300
+ type: t,
1301
+ name: `${(i == null ? void 0 : i.name) || t} ${n.sources.filter((I) => I.type === t).length + 1}`,
1302
+ settings: {},
1303
+ volume: 1,
1304
+ muted: !1
1305
+ };
1306
+ try {
1307
+ if (t === "camera" || t === "microphone") {
1308
+ const I = t === "camera" ? { video: !0 } : { audio: !0 }, v = (await navigator.mediaDevices.enumerateDevices()).filter(
1309
+ (N) => t === "camera" ? N.kind === "videoinput" : N.kind === "audioinput"
1310
+ );
1311
+ v.length > 0 && (o.settings.deviceId = v[0].deviceId);
1312
+ } else (t === "screen" || t === "window") && await navigator.mediaDevices.getDisplayMedia({ video: !0 });
1313
+ } catch (I) {
1314
+ console.warn(`Could not access ${t}:`, I);
1315
+ }
1316
+ h({ sources: [...n.sources, o] });
1317
+ const d = {
1318
+ id: crypto.randomUUID(),
1319
+ sourceId: o.id,
1320
+ position: { x: 0, y: 0 },
1321
+ size: { width: n.layout.canvas.width, height: n.layout.canvas.height },
1322
+ visible: !0,
1323
+ opacity: 1,
1324
+ zIndex: n.layout.layers.length
1325
+ };
1326
+ h({
1327
+ layout: {
1328
+ ...n.layout,
1329
+ layers: [...n.layout.layers, d]
1330
+ }
1331
+ }), U(!1);
1332
+ }, w = (t, i) => {
1333
+ h({
1334
+ sources: n.sources.map((o) => o.id === t ? { ...o, ...i } : o)
1335
+ });
1336
+ }, H = (t) => {
1337
+ h({
1338
+ sources: n.sources.filter((i) => i.id !== t),
1339
+ layout: {
1340
+ ...n.layout,
1341
+ layers: n.layout.layers.filter((i) => i.sourceId !== t)
1342
+ }
1343
+ });
1344
+ }, E = (t, i) => {
1345
+ h({
1346
+ layout: {
1347
+ ...n.layout,
1348
+ layers: n.layout.layers.map((o) => o.id === t ? { ...o, ...i } : o)
1349
+ }
1350
+ });
1351
+ }, ie = (t) => {
1352
+ const i = n.layout.layers.findIndex((o) => o.id === t);
1353
+ if (i < n.layout.layers.length - 1) {
1354
+ const o = [...n.layout.layers];
1355
+ [o[i], o[i + 1]] = [o[i + 1], o[i]], o.forEach((d, I) => {
1356
+ d.zIndex = I;
1357
+ }), h({ layout: { ...n.layout, layers: o } });
1358
+ }
1359
+ }, Y = (t) => {
1360
+ const i = n.layout.layers.findIndex((o) => o.id === t);
1361
+ if (i > 0) {
1362
+ const o = [...n.layout.layers];
1363
+ [o[i], o[i - 1]] = [o[i - 1], o[i]], o.forEach((d, I) => {
1364
+ d.zIndex = I;
1365
+ }), h({ layout: { ...n.layout, layers: o } });
1366
+ }
1367
+ }, te = () => {
1368
+ const t = {
1369
+ name: `Scene ${y.length + 1}`,
1370
+ canvas: { ...n.layout.canvas },
1371
+ layers: []
1372
+ };
1373
+ A([...y, t]);
1374
+ }, Z = (t) => {
1375
+ const i = [...y];
1376
+ i[X] = n.layout, A(i), ne(t), h({ layout: y[t] });
1377
+ }, j = async () => {
1378
+ try {
1379
+ h({
1380
+ destinations: n.destinations.map(
1381
+ (t) => t.enabled ? { ...t, status: "connecting" } : t
1382
+ )
1383
+ }), await new Promise((t) => setTimeout(t, 2e3)), h({
1384
+ destinations: n.destinations.map(
1385
+ (t) => t.enabled ? { ...t, status: "live" } : t
1386
+ )
1387
+ }), C(!0), _.current = Date.now(), D == null || D(), f.current = setInterval(() => {
1388
+ const t = {
1389
+ duration: (Date.now() - _.current) / 1e3,
1390
+ viewers: Math.floor(Math.random() * 100) + g.viewers,
1391
+ peakViewers: Math.max(g.peakViewers, g.viewers),
1392
+ bitrate: n.settings.video.bitrate + Math.floor(Math.random() * 500 - 250),
1393
+ fps: n.settings.video.frameRate - Math.random() * 2,
1394
+ droppedFrames: g.droppedFrames + (Math.random() > 0.95 ? 1 : 0),
1395
+ cpuUsage: 15 + Math.random() * 30,
1396
+ memoryUsage: 40 + Math.random() * 20
1397
+ };
1398
+ P(t), F == null || F(t);
1399
+ }, 1e3);
1400
+ } catch (t) {
1401
+ c == null || c(t instanceof Error ? t : new Error("Failed to start stream")), h({
1402
+ destinations: n.destinations.map((i) => ({
1403
+ ...i,
1404
+ status: "error"
1405
+ }))
1406
+ });
1407
+ }
1408
+ }, s = () => {
1409
+ f.current && clearInterval(f.current), h({
1410
+ destinations: n.destinations.map((t) => ({ ...t, status: "idle" }))
1411
+ }), C(!1), R == null || R();
1412
+ }, r = (t) => {
1413
+ const i = Math.floor(t / 3600), o = Math.floor(t % 3600 / 60), d = Math.floor(t % 60);
1414
+ return `${i.toString().padStart(2, "0")}:${o.toString().padStart(2, "0")}:${d.toString().padStart(2, "0")}`;
1415
+ }, u = (t) => {
1416
+ switch (t) {
1417
+ case "live":
1418
+ return "#00ff00";
1419
+ case "connecting":
1420
+ return "#ffff00";
1421
+ case "error":
1422
+ return "#ff0000";
1423
+ default:
1424
+ return "#888888";
1425
+ }
1426
+ };
1427
+ return /* @__PURE__ */ a("div", { className: `nice-live-streaming ${J}`, children: [
1428
+ /* @__PURE__ */ a("header", { className: "streaming__header", children: [
1429
+ /* @__PURE__ */ a("div", { className: "header__title", children: [
1430
+ /* @__PURE__ */ e(
1431
+ "input",
1432
+ {
1433
+ type: "text",
1434
+ value: n.name,
1435
+ onChange: (t) => h({ name: t.target.value }),
1436
+ className: "stream-name-input"
1437
+ }
1438
+ ),
1439
+ m && /* @__PURE__ */ a("span", { className: "live-badge", children: [
1440
+ /* @__PURE__ */ e("span", { className: "live-dot" }),
1441
+ " LIVE"
1442
+ ] })
1443
+ ] }),
1444
+ /* @__PURE__ */ e("div", { className: "header__stats", children: m && /* @__PURE__ */ a(ae, { children: [
1445
+ /* @__PURE__ */ a("span", { className: "stat-item", children: [
1446
+ "⏱️ ",
1447
+ r(g.duration)
1448
+ ] }),
1449
+ /* @__PURE__ */ a("span", { className: "stat-item", children: [
1450
+ "👥 ",
1451
+ g.viewers
1452
+ ] }),
1453
+ /* @__PURE__ */ a("span", { className: "stat-item", children: [
1454
+ "📊 ",
1455
+ Math.round(g.bitrate),
1456
+ " kbps"
1457
+ ] }),
1458
+ /* @__PURE__ */ a("span", { className: "stat-item", children: [
1459
+ "🎬 ",
1460
+ g.fps.toFixed(1),
1461
+ " fps"
1462
+ ] })
1463
+ ] }) }),
1464
+ /* @__PURE__ */ e("div", { className: "header__actions", children: m ? /* @__PURE__ */ e("button", { className: "action-button action-button--stop", onClick: s, children: "End Stream" }) : /* @__PURE__ */ e(
1465
+ "button",
1466
+ {
1467
+ className: "action-button action-button--go-live",
1468
+ onClick: j,
1469
+ disabled: n.destinations.filter((t) => t.enabled).length === 0,
1470
+ children: "Go Live"
1471
+ }
1472
+ ) })
1473
+ ] }),
1474
+ /* @__PURE__ */ a("div", { className: "streaming__main", children: [
1475
+ /* @__PURE__ */ a("div", { className: "streaming__preview", children: [
1476
+ /* @__PURE__ */ a("div", { className: "scenes-bar", children: [
1477
+ y.map((t, i) => /* @__PURE__ */ e(
1478
+ "button",
1479
+ {
1480
+ className: `scene-button ${X === i ? "scene-button--active" : ""}`,
1481
+ onClick: () => Z(i),
1482
+ children: t.name
1483
+ },
1484
+ i
1485
+ )),
1486
+ /* @__PURE__ */ e("button", { className: "scene-button scene-button--add", onClick: te, children: "+" })
1487
+ ] }),
1488
+ /* @__PURE__ */ e(
1489
+ "div",
1490
+ {
1491
+ ref: z,
1492
+ className: "preview-canvas",
1493
+ style: {
1494
+ aspectRatio: `${n.layout.canvas.width}/${n.layout.canvas.height}`,
1495
+ backgroundColor: n.layout.canvas.backgroundColor
1496
+ },
1497
+ children: n.layout.layers.sort((t, i) => t.zIndex - i.zIndex).map((t) => {
1498
+ var o;
1499
+ const i = n.sources.find((d) => d.id === t.sourceId);
1500
+ return !t.visible || !i ? null : /* @__PURE__ */ e(
1501
+ "div",
1502
+ {
1503
+ className: `canvas-layer ${k === t.id ? "canvas-layer--selected" : ""}`,
1504
+ style: {
1505
+ left: `${t.position.x / n.layout.canvas.width * 100}%`,
1506
+ top: `${t.position.y / n.layout.canvas.height * 100}%`,
1507
+ width: `${t.size.width / n.layout.canvas.width * 100}%`,
1508
+ height: `${t.size.height / n.layout.canvas.height * 100}%`,
1509
+ opacity: t.opacity,
1510
+ zIndex: t.zIndex
1511
+ },
1512
+ onClick: () => L(t.id),
1513
+ children: /* @__PURE__ */ a("div", { className: "layer-content", children: [
1514
+ /* @__PURE__ */ e("span", { className: "layer-icon", children: ((o = se.find((d) => d.type === i.type)) == null ? void 0 : o.icon) || "📦" }),
1515
+ /* @__PURE__ */ e("span", { className: "layer-name", children: i.name })
1516
+ ] })
1517
+ },
1518
+ t.id
1519
+ );
1520
+ })
1521
+ }
1522
+ )
1523
+ ] }),
1524
+ /* @__PURE__ */ a("aside", { className: "streaming__panel", children: [
1525
+ /* @__PURE__ */ e("div", { className: "panel-tabs", children: ["sources", "audio", "destinations", "settings"].map((t) => /* @__PURE__ */ e(
1526
+ "button",
1527
+ {
1528
+ className: `panel-tab ${b === t ? "panel-tab--active" : ""}`,
1529
+ onClick: () => K(t),
1530
+ children: t.charAt(0).toUpperCase() + t.slice(1)
1531
+ },
1532
+ t
1533
+ )) }),
1534
+ /* @__PURE__ */ a("div", { className: "panel-content", children: [
1535
+ b === "sources" && /* @__PURE__ */ a("div", { className: "sources-panel", children: [
1536
+ /* @__PURE__ */ a("div", { className: "panel-header", children: [
1537
+ /* @__PURE__ */ e("h3", { children: "Sources" }),
1538
+ /* @__PURE__ */ e(
1539
+ "button",
1540
+ {
1541
+ className: "add-button",
1542
+ onClick: () => U(!0),
1543
+ disabled: m,
1544
+ children: "+ Add"
1545
+ }
1546
+ )
1547
+ ] }),
1548
+ /* @__PURE__ */ e("div", { className: "sources-list", children: n.sources.filter((t) => t.type !== "microphone" && t.type !== "system-audio").map((t) => {
1549
+ var o;
1550
+ const i = n.layout.layers.find((d) => d.sourceId === t.id);
1551
+ return /* @__PURE__ */ a(
1552
+ "div",
1553
+ {
1554
+ className: `source-item ${k === (i == null ? void 0 : i.id) ? "source-item--selected" : ""}`,
1555
+ onClick: () => i && L(i.id),
1556
+ children: [
1557
+ /* @__PURE__ */ e("span", { className: "source-icon", children: (o = se.find((d) => d.type === t.type)) == null ? void 0 : o.icon }),
1558
+ /* @__PURE__ */ e("span", { className: "source-name", children: t.name }),
1559
+ /* @__PURE__ */ a("div", { className: "source-controls", children: [
1560
+ /* @__PURE__ */ e(
1561
+ "button",
1562
+ {
1563
+ className: i != null && i.visible ? "" : "inactive",
1564
+ onClick: (d) => {
1565
+ d.stopPropagation(), i && E(i.id, { visible: !i.visible });
1566
+ },
1567
+ children: i != null && i.visible ? "👁️" : "👁️‍🗨️"
1568
+ }
1569
+ ),
1570
+ /* @__PURE__ */ e(
1571
+ "button",
1572
+ {
1573
+ onClick: (d) => {
1574
+ d.stopPropagation(), i && ie(i.id);
1575
+ },
1576
+ children: "⬆️"
1577
+ }
1578
+ ),
1579
+ /* @__PURE__ */ e(
1580
+ "button",
1581
+ {
1582
+ onClick: (d) => {
1583
+ d.stopPropagation(), i && Y(i.id);
1584
+ },
1585
+ children: "⬇️"
1586
+ }
1587
+ ),
1588
+ /* @__PURE__ */ e(
1589
+ "button",
1590
+ {
1591
+ onClick: (d) => {
1592
+ d.stopPropagation(), H(t.id);
1593
+ },
1594
+ disabled: m,
1595
+ children: "🗑️"
1596
+ }
1597
+ )
1598
+ ] })
1599
+ ]
1600
+ },
1601
+ t.id
1602
+ );
1603
+ }) }),
1604
+ k && /* @__PURE__ */ a("div", { className: "layer-properties", children: [
1605
+ /* @__PURE__ */ e("h4", { children: "Properties" }),
1606
+ (() => {
1607
+ const t = n.layout.layers.find((i) => i.id === k);
1608
+ return t ? /* @__PURE__ */ a(ae, { children: [
1609
+ /* @__PURE__ */ a("label", { children: [
1610
+ "X Position",
1611
+ /* @__PURE__ */ e(
1612
+ "input",
1613
+ {
1614
+ type: "number",
1615
+ value: t.position.x,
1616
+ onChange: (i) => E(t.id, {
1617
+ position: { ...t.position, x: parseInt(i.target.value) || 0 }
1618
+ })
1619
+ }
1620
+ )
1621
+ ] }),
1622
+ /* @__PURE__ */ a("label", { children: [
1623
+ "Y Position",
1624
+ /* @__PURE__ */ e(
1625
+ "input",
1626
+ {
1627
+ type: "number",
1628
+ value: t.position.y,
1629
+ onChange: (i) => E(t.id, {
1630
+ position: { ...t.position, y: parseInt(i.target.value) || 0 }
1631
+ })
1632
+ }
1633
+ )
1634
+ ] }),
1635
+ /* @__PURE__ */ a("label", { children: [
1636
+ "Width",
1637
+ /* @__PURE__ */ e(
1638
+ "input",
1639
+ {
1640
+ type: "number",
1641
+ value: t.size.width,
1642
+ onChange: (i) => E(t.id, {
1643
+ size: { ...t.size, width: parseInt(i.target.value) || 100 }
1644
+ })
1645
+ }
1646
+ )
1647
+ ] }),
1648
+ /* @__PURE__ */ a("label", { children: [
1649
+ "Height",
1650
+ /* @__PURE__ */ e(
1651
+ "input",
1652
+ {
1653
+ type: "number",
1654
+ value: t.size.height,
1655
+ onChange: (i) => E(t.id, {
1656
+ size: { ...t.size, height: parseInt(i.target.value) || 100 }
1657
+ })
1658
+ }
1659
+ )
1660
+ ] }),
1661
+ /* @__PURE__ */ a("label", { children: [
1662
+ "Opacity",
1663
+ /* @__PURE__ */ e(
1664
+ "input",
1665
+ {
1666
+ type: "range",
1667
+ min: "0",
1668
+ max: "1",
1669
+ step: "0.1",
1670
+ value: t.opacity,
1671
+ onChange: (i) => E(t.id, {
1672
+ opacity: parseFloat(i.target.value)
1673
+ })
1674
+ }
1675
+ )
1676
+ ] })
1677
+ ] }) : null;
1678
+ })()
1679
+ ] })
1680
+ ] }),
1681
+ b === "audio" && /* @__PURE__ */ a("div", { className: "audio-panel", children: [
1682
+ /* @__PURE__ */ a("div", { className: "panel-header", children: [
1683
+ /* @__PURE__ */ e("h3", { children: "Audio Mixer" }),
1684
+ /* @__PURE__ */ e(
1685
+ "button",
1686
+ {
1687
+ className: "add-button",
1688
+ onClick: () => {
1689
+ U(!0);
1690
+ },
1691
+ disabled: m,
1692
+ children: "+ Add"
1693
+ }
1694
+ )
1695
+ ] }),
1696
+ /* @__PURE__ */ a("div", { className: "audio-sources", children: [
1697
+ n.sources.filter(
1698
+ (t) => t.type === "microphone" || t.type === "system-audio" || t.type === "video"
1699
+ ).map((t) => {
1700
+ var i;
1701
+ return /* @__PURE__ */ a("div", { className: "audio-source", children: [
1702
+ /* @__PURE__ */ a("div", { className: "audio-header", children: [
1703
+ /* @__PURE__ */ e("span", { className: "audio-icon", children: (i = se.find((o) => o.type === t.type)) == null ? void 0 : i.icon }),
1704
+ /* @__PURE__ */ e("span", { className: "audio-name", children: t.name }),
1705
+ /* @__PURE__ */ e(
1706
+ "button",
1707
+ {
1708
+ className: t.muted ? "muted" : "",
1709
+ onClick: () => w(t.id, { muted: !t.muted }),
1710
+ children: t.muted ? "🔇" : "🔊"
1711
+ }
1712
+ )
1713
+ ] }),
1714
+ /* @__PURE__ */ a("div", { className: "audio-slider", children: [
1715
+ /* @__PURE__ */ e(
1716
+ "input",
1717
+ {
1718
+ type: "range",
1719
+ min: "0",
1720
+ max: "1",
1721
+ step: "0.01",
1722
+ value: t.volume ?? 1,
1723
+ onChange: (o) => w(t.id, { volume: parseFloat(o.target.value) }),
1724
+ disabled: t.muted
1725
+ }
1726
+ ),
1727
+ /* @__PURE__ */ a("span", { className: "volume-value", children: [
1728
+ Math.round((t.volume ?? 1) * 100),
1729
+ "%"
1730
+ ] })
1731
+ ] }),
1732
+ /* @__PURE__ */ e("div", { className: "audio-meter", children: /* @__PURE__ */ e(
1733
+ "div",
1734
+ {
1735
+ className: "meter-fill",
1736
+ style: { width: `${(t.volume ?? 1) * 70 + Math.random() * 30}%` }
1737
+ }
1738
+ ) })
1739
+ ] }, t.id);
1740
+ }),
1741
+ n.sources.filter(
1742
+ (t) => t.type === "microphone" || t.type === "system-audio"
1743
+ ).length === 0 && /* @__PURE__ */ e("p", { className: "empty-message", children: "No audio sources added" })
1744
+ ] })
1745
+ ] }),
1746
+ b === "destinations" && /* @__PURE__ */ a("div", { className: "destinations-panel", children: [
1747
+ /* @__PURE__ */ a("div", { className: "panel-header", children: [
1748
+ /* @__PURE__ */ e("h3", { children: "Destinations" }),
1749
+ /* @__PURE__ */ e(
1750
+ "button",
1751
+ {
1752
+ className: "add-button",
1753
+ onClick: () => V(!0),
1754
+ disabled: m,
1755
+ children: "+ Add"
1756
+ }
1757
+ )
1758
+ ] }),
1759
+ /* @__PURE__ */ a("div", { className: "destinations-list", children: [
1760
+ n.destinations.map((t) => {
1761
+ var i;
1762
+ return /* @__PURE__ */ a("div", { className: "destination-item", children: [
1763
+ /* @__PURE__ */ a("div", { className: "destination-header", children: [
1764
+ /* @__PURE__ */ e(
1765
+ "span",
1766
+ {
1767
+ className: "status-indicator",
1768
+ style: { backgroundColor: u(t.status) }
1769
+ }
1770
+ ),
1771
+ /* @__PURE__ */ e("span", { className: "destination-icon", children: (i = oe.find((o) => o.platform === t.platform)) == null ? void 0 : i.icon }),
1772
+ /* @__PURE__ */ e("span", { className: "destination-name", children: t.name }),
1773
+ /* @__PURE__ */ a("label", { className: "toggle", children: [
1774
+ /* @__PURE__ */ e(
1775
+ "input",
1776
+ {
1777
+ type: "checkbox",
1778
+ checked: t.enabled,
1779
+ onChange: (o) => G(t.id, { enabled: o.target.checked }),
1780
+ disabled: m
1781
+ }
1782
+ ),
1783
+ /* @__PURE__ */ e("span", { className: "toggle-slider" })
1784
+ ] })
1785
+ ] }),
1786
+ /* @__PURE__ */ a("div", { className: "destination-config", children: [
1787
+ /* @__PURE__ */ a("label", { children: [
1788
+ "Server URL",
1789
+ /* @__PURE__ */ e(
1790
+ "input",
1791
+ {
1792
+ type: "text",
1793
+ value: t.url,
1794
+ onChange: (o) => G(t.id, { url: o.target.value }),
1795
+ placeholder: "rtmp://...",
1796
+ disabled: m
1797
+ }
1798
+ )
1799
+ ] }),
1800
+ /* @__PURE__ */ a("label", { children: [
1801
+ "Stream Key",
1802
+ /* @__PURE__ */ e(
1803
+ "input",
1804
+ {
1805
+ type: "password",
1806
+ value: t.streamKey || "",
1807
+ onChange: (o) => G(t.id, { streamKey: o.target.value }),
1808
+ placeholder: "Enter stream key",
1809
+ disabled: m
1810
+ }
1811
+ )
1812
+ ] })
1813
+ ] }),
1814
+ /* @__PURE__ */ e(
1815
+ "button",
1816
+ {
1817
+ className: "remove-button",
1818
+ onClick: () => O(t.id),
1819
+ disabled: m,
1820
+ children: "Remove"
1821
+ }
1822
+ )
1823
+ ] }, t.id);
1824
+ }),
1825
+ n.destinations.length === 0 && /* @__PURE__ */ e("p", { className: "empty-message", children: "No destinations configured" })
1826
+ ] })
1827
+ ] }),
1828
+ b === "settings" && /* @__PURE__ */ a("div", { className: "settings-panel", children: [
1829
+ /* @__PURE__ */ a("div", { className: "setting-section", children: [
1830
+ /* @__PURE__ */ e("h4", { children: "Video" }),
1831
+ /* @__PURE__ */ a("label", { children: [
1832
+ "Resolution",
1833
+ /* @__PURE__ */ a(
1834
+ "select",
1835
+ {
1836
+ value: `${n.settings.video.resolution.width}x${n.settings.video.resolution.height}`,
1837
+ onChange: (t) => {
1838
+ const [i, o] = t.target.value.split("x").map(Number);
1839
+ h({
1840
+ settings: {
1841
+ ...n.settings,
1842
+ video: { ...n.settings.video, resolution: { width: i, height: o } }
1843
+ },
1844
+ layout: {
1845
+ ...n.layout,
1846
+ canvas: { ...n.layout.canvas, width: i, height: o }
1847
+ }
1848
+ });
1849
+ },
1850
+ disabled: m,
1851
+ children: [
1852
+ /* @__PURE__ */ e("option", { value: "1920x1080", children: "1080p (1920x1080)" }),
1853
+ /* @__PURE__ */ e("option", { value: "1280x720", children: "720p (1280x720)" }),
1854
+ /* @__PURE__ */ e("option", { value: "2560x1440", children: "1440p (2560x1440)" })
1855
+ ]
1856
+ }
1857
+ )
1858
+ ] }),
1859
+ /* @__PURE__ */ a("label", { children: [
1860
+ "Frame Rate",
1861
+ /* @__PURE__ */ a(
1862
+ "select",
1863
+ {
1864
+ value: n.settings.video.frameRate,
1865
+ onChange: (t) => h({
1866
+ settings: {
1867
+ ...n.settings,
1868
+ video: {
1869
+ ...n.settings.video,
1870
+ frameRate: parseInt(t.target.value)
1871
+ }
1872
+ }
1873
+ }),
1874
+ disabled: m,
1875
+ children: [
1876
+ /* @__PURE__ */ e("option", { value: "24", children: "24 fps" }),
1877
+ /* @__PURE__ */ e("option", { value: "30", children: "30 fps" }),
1878
+ /* @__PURE__ */ e("option", { value: "60", children: "60 fps" })
1879
+ ]
1880
+ }
1881
+ )
1882
+ ] }),
1883
+ /* @__PURE__ */ a("label", { children: [
1884
+ "Bitrate (kbps)",
1885
+ /* @__PURE__ */ e(
1886
+ "input",
1887
+ {
1888
+ type: "number",
1889
+ value: n.settings.video.bitrate,
1890
+ onChange: (t) => h({
1891
+ settings: {
1892
+ ...n.settings,
1893
+ video: {
1894
+ ...n.settings.video,
1895
+ bitrate: parseInt(t.target.value) || 6e3
1896
+ }
1897
+ }
1898
+ }),
1899
+ min: "1000",
1900
+ max: "50000",
1901
+ disabled: m
1902
+ }
1903
+ )
1904
+ ] }),
1905
+ /* @__PURE__ */ a("label", { children: [
1906
+ "Keyframe Interval (sec)",
1907
+ /* @__PURE__ */ e(
1908
+ "input",
1909
+ {
1910
+ type: "number",
1911
+ value: n.settings.video.keyframe,
1912
+ onChange: (t) => h({
1913
+ settings: {
1914
+ ...n.settings,
1915
+ video: {
1916
+ ...n.settings.video,
1917
+ keyframe: parseInt(t.target.value) || 2
1918
+ }
1919
+ }
1920
+ }),
1921
+ min: "1",
1922
+ max: "10",
1923
+ disabled: m
1924
+ }
1925
+ )
1926
+ ] })
1927
+ ] }),
1928
+ /* @__PURE__ */ a("div", { className: "setting-section", children: [
1929
+ /* @__PURE__ */ e("h4", { children: "Audio" }),
1930
+ /* @__PURE__ */ a("label", { children: [
1931
+ "Sample Rate",
1932
+ /* @__PURE__ */ a(
1933
+ "select",
1934
+ {
1935
+ value: n.settings.audio.sampleRate,
1936
+ onChange: (t) => h({
1937
+ settings: {
1938
+ ...n.settings,
1939
+ audio: {
1940
+ ...n.settings.audio,
1941
+ sampleRate: parseInt(t.target.value)
1942
+ }
1943
+ }
1944
+ }),
1945
+ disabled: m,
1946
+ children: [
1947
+ /* @__PURE__ */ e("option", { value: "44100", children: "44.1 kHz" }),
1948
+ /* @__PURE__ */ e("option", { value: "48000", children: "48 kHz" })
1949
+ ]
1950
+ }
1951
+ )
1952
+ ] }),
1953
+ /* @__PURE__ */ a("label", { children: [
1954
+ "Audio Bitrate (kbps)",
1955
+ /* @__PURE__ */ a(
1956
+ "select",
1957
+ {
1958
+ value: n.settings.audio.bitrate,
1959
+ onChange: (t) => h({
1960
+ settings: {
1961
+ ...n.settings,
1962
+ audio: { ...n.settings.audio, bitrate: parseInt(t.target.value) }
1963
+ }
1964
+ }),
1965
+ disabled: m,
1966
+ children: [
1967
+ /* @__PURE__ */ e("option", { value: "96", children: "96 kbps" }),
1968
+ /* @__PURE__ */ e("option", { value: "128", children: "128 kbps" }),
1969
+ /* @__PURE__ */ e("option", { value: "160", children: "160 kbps" }),
1970
+ /* @__PURE__ */ e("option", { value: "320", children: "320 kbps" })
1971
+ ]
1972
+ }
1973
+ )
1974
+ ] })
1975
+ ] })
1976
+ ] })
1977
+ ] })
1978
+ ] })
1979
+ ] }),
1980
+ m && /* @__PURE__ */ e("footer", { className: "streaming__footer", children: /* @__PURE__ */ a("div", { className: "footer-stats", children: [
1981
+ /* @__PURE__ */ a("span", { className: "stat", children: [
1982
+ /* @__PURE__ */ e("label", { children: "CPU" }),
1983
+ /* @__PURE__ */ a("span", { className: "value", children: [
1984
+ g.cpuUsage.toFixed(1),
1985
+ "%"
1986
+ ] })
1987
+ ] }),
1988
+ /* @__PURE__ */ a("span", { className: "stat", children: [
1989
+ /* @__PURE__ */ e("label", { children: "Memory" }),
1990
+ /* @__PURE__ */ a("span", { className: "value", children: [
1991
+ g.memoryUsage.toFixed(1),
1992
+ "%"
1993
+ ] })
1994
+ ] }),
1995
+ /* @__PURE__ */ a("span", { className: "stat", children: [
1996
+ /* @__PURE__ */ e("label", { children: "Dropped" }),
1997
+ /* @__PURE__ */ e("span", { className: "value", children: g.droppedFrames })
1998
+ ] }),
1999
+ /* @__PURE__ */ a("span", { className: "stat", children: [
2000
+ /* @__PURE__ */ e("label", { children: "Peak Viewers" }),
2001
+ /* @__PURE__ */ e("span", { className: "value", children: g.peakViewers })
2002
+ ] })
2003
+ ] }) }),
2004
+ x && /* @__PURE__ */ e("div", { className: "modal-overlay", children: /* @__PURE__ */ a("div", { className: "modal", children: [
2005
+ /* @__PURE__ */ a("div", { className: "modal-header", children: [
2006
+ /* @__PURE__ */ e("h3", { children: "Add Source" }),
2007
+ /* @__PURE__ */ e("button", { className: "close-button", onClick: () => U(!1), children: "×" })
2008
+ ] }),
2009
+ /* @__PURE__ */ e("div", { className: "modal-content", children: /* @__PURE__ */ e("div", { className: "source-type-grid", children: se.map((t) => /* @__PURE__ */ a(
2010
+ "button",
2011
+ {
2012
+ className: "source-type-button",
2013
+ onClick: () => ee(t.type),
2014
+ children: [
2015
+ /* @__PURE__ */ e("span", { className: "icon", children: t.icon }),
2016
+ /* @__PURE__ */ e("span", { className: "name", children: t.name })
2017
+ ]
2018
+ },
2019
+ t.type
2020
+ )) }) })
2021
+ ] }) }),
2022
+ q && /* @__PURE__ */ e("div", { className: "modal-overlay", children: /* @__PURE__ */ a("div", { className: "modal", children: [
2023
+ /* @__PURE__ */ a("div", { className: "modal-header", children: [
2024
+ /* @__PURE__ */ e("h3", { children: "Add Destination" }),
2025
+ /* @__PURE__ */ e("button", { className: "close-button", onClick: () => V(!1), children: "×" })
2026
+ ] }),
2027
+ /* @__PURE__ */ e("div", { className: "modal-content", children: /* @__PURE__ */ e("div", { className: "platform-grid", children: oe.map((t) => /* @__PURE__ */ a(
2028
+ "button",
2029
+ {
2030
+ className: "platform-button",
2031
+ onClick: () => W(t.platform),
2032
+ children: [
2033
+ /* @__PURE__ */ e("span", { className: "icon", children: t.icon }),
2034
+ /* @__PURE__ */ e("span", { className: "name", children: t.name })
2035
+ ]
2036
+ },
2037
+ t.platform
2038
+ )) }) })
2039
+ ] }) })
2040
+ ] });
2041
+ };
2042
+ export {
2043
+ ye as NiceLiveStreaming,
2044
+ Ne as NiceScreenRecorder,
2045
+ ge as NiceVideoEditor
2046
+ };