@norskvideo/norsk-studio-built-ins 1.12.0-2025-02-03-6cdc30e8 → 1.12.0-2025-02-07-e66173eb

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 (46) hide show
  1. package/client/info.js +238 -157
  2. package/client/style.css +22 -0
  3. package/lib/input.rtmp/info.js +8 -8
  4. package/lib/input.rtmp/info.js.map +1 -1
  5. package/lib/input.silence/info.js +7 -7
  6. package/lib/input.silence/info.js.map +1 -1
  7. package/lib/input.srt-caller/info.js +8 -8
  8. package/lib/input.srt-caller/info.js.map +1 -1
  9. package/lib/input.srt-listener/info.js +7 -7
  10. package/lib/input.srt-listener/info.js.map +1 -1
  11. package/lib/input.udp-ts/info.js +2 -2
  12. package/lib/input.udp-ts/info.js.map +1 -1
  13. package/lib/input.videoTestCard/info.js +4 -7
  14. package/lib/input.videoTestCard/info.js.map +1 -1
  15. package/lib/output.autoCmaf/info.js +9 -7
  16. package/lib/output.autoCmaf/info.js.map +1 -1
  17. package/lib/output.autoCmaf/runtime.d.ts +5 -8
  18. package/lib/output.autoCmaf/runtime.js +18 -31
  19. package/lib/output.autoCmaf/runtime.js.map +1 -1
  20. package/lib/output.autoCmaf/summary-view.d.ts +4 -0
  21. package/lib/output.autoCmaf/summary-view.js +24 -0
  22. package/lib/output.autoCmaf/summary-view.js.map +1 -0
  23. package/lib/output.preview/info.js +5 -8
  24. package/lib/output.preview/info.js.map +1 -1
  25. package/lib/output.rtmp/info.js +5 -2
  26. package/lib/output.rtmp/info.js.map +1 -1
  27. package/lib/output.srt/info.js +5 -2
  28. package/lib/output.srt/info.js.map +1 -1
  29. package/lib/output.udpTs/info.js +4 -1
  30. package/lib/output.udpTs/info.js.map +1 -1
  31. package/lib/output.whep/info.d.ts +2 -2
  32. package/lib/output.whep/info.js +15 -4
  33. package/lib/output.whep/info.js.map +1 -1
  34. package/lib/output.whep/inline-view.d.ts +2 -2
  35. package/lib/output.whep/inline-view.js.map +1 -1
  36. package/lib/output.whep/runtime.d.ts +24 -10
  37. package/lib/output.whep/runtime.js +122 -10
  38. package/lib/output.whep/runtime.js.map +1 -1
  39. package/lib/output.whep/summary-view.d.ts +4 -0
  40. package/lib/output.whep/summary-view.js +24 -0
  41. package/lib/output.whep/summary-view.js.map +1 -0
  42. package/lib/test/auto-cmaf.js +138 -1
  43. package/lib/test/auto-cmaf.js.map +1 -1
  44. package/lib/test/whep-output.js +184 -3
  45. package/lib/test/whep-output.js.map +1 -1
  46. package/package.json +3 -3
package/client/info.js CHANGED
@@ -493,6 +493,39 @@ var require_config = __commonJS({
493
493
  }
494
494
  });
495
495
 
496
+ // build/output.autoCmaf/summary-view.js
497
+ var summary_view_exports3 = {};
498
+ __export(summary_view_exports3, {
499
+ default: () => summary_view_default3
500
+ });
501
+ function SummaryView5({ state, sendCommand }) {
502
+ const handleEnableOutput = () => {
503
+ void enableOutput();
504
+ };
505
+ const enableOutput = async () => {
506
+ sendCommand({
507
+ type: "enable-output"
508
+ });
509
+ };
510
+ const handleDisableOutput = () => {
511
+ void disableOutput();
512
+ };
513
+ const disableOutput = async () => {
514
+ sendCommand({
515
+ type: "disable-output"
516
+ });
517
+ };
518
+ return (0, import_jsx_runtime6.jsx)("div", { className: "mb-5", children: (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [(0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center space-x-2", children: [(0, import_jsx_runtime6.jsx)("span", { className: `inline-block w-2 h-2 rounded-full ${state.enabled ? "bg-blue-500" : "bg-red-500"}` }), (0, import_jsx_runtime6.jsxs)("span", { className: "text-sm", children: ["Status: ", state.enabled ? "Enabled" : "Disabled"] })] }), (0, import_jsx_runtime6.jsx)("div", { children: state.enabled ? (0, import_jsx_runtime6.jsx)("button", { onClick: handleDisableOutput, className: "px-3 py-1 text-sm bg-red-600 hover:bg-red-700 text-white rounded", children: "Disable Output" }) : (0, import_jsx_runtime6.jsx)("button", { onClick: handleEnableOutput, className: "px-3 py-1 text-sm bg-blue-600 hover:bg-blue-700 text-white rounded", children: "Enable Output" }) })] }) });
519
+ }
520
+ var import_jsx_runtime6, summary_view_default3;
521
+ var init_summary_view3 = __esm({
522
+ "build/output.autoCmaf/summary-view.js"() {
523
+ "use strict";
524
+ import_jsx_runtime6 = __toESM(require_jsx_runtime());
525
+ summary_view_default3 = SummaryView5;
526
+ }
527
+ });
528
+
496
529
  // external-global-plugin:hls.js
497
530
  var require_hls = __commonJS({
498
531
  "external-global-plugin:hls.js"(exports, module) {
@@ -521,16 +554,16 @@ function FullscreenView({ state, config }) {
521
554
  }
522
555
  }, [state.url]);
523
556
  if (!url)
524
- return (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: "..." });
557
+ return (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: "..." });
525
558
  {
526
559
  }
527
- return (0, import_jsx_runtime6.jsx)("div", { children: (0, import_jsx_runtime6.jsx)("video", { controls: true, autoPlay: true, muted: true, id: `${id}-video` }) });
560
+ return (0, import_jsx_runtime7.jsx)("div", { children: (0, import_jsx_runtime7.jsx)("video", { controls: true, autoPlay: true, muted: true, id: `${id}-video` }) });
528
561
  }
529
- var import_jsx_runtime6, import_react4, import_hls, fullscreen_default;
562
+ var import_jsx_runtime7, import_react4, import_hls, fullscreen_default;
530
563
  var init_fullscreen = __esm({
531
564
  "build/output.autoCmaf/fullscreen.js"() {
532
565
  "use strict";
533
- import_jsx_runtime6 = __toESM(require_jsx_runtime());
566
+ import_jsx_runtime7 = __toESM(require_jsx_runtime());
534
567
  import_react4 = __toESM(require_react());
535
568
  import_hls = __toESM(require_hls());
536
569
  fullscreen_default = FullscreenView;
@@ -544,16 +577,16 @@ __export(form_views_exports, {
544
577
  SegmentConfiguration: () => SegmentConfiguration
545
578
  });
546
579
  function S3Destination(destination) {
547
- return (0, import_jsx_runtime7.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-3 text-sm", children: [(0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Host" }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-2", children: destination.host }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Path" }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-2", children: destination.prefix }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Include Ads" }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-2", children: destination.includeAdInsertions ? "yes" : "no" })] });
580
+ return (0, import_jsx_runtime8.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-3 text-sm", children: [(0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Host" }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2", children: destination.host }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Path" }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2", children: destination.prefix }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Include Ads" }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2", children: destination.includeAdInsertions ? "yes" : "no" })] });
548
581
  }
549
582
  function SegmentConfiguration(cfg) {
550
- return (0, import_jsx_runtime7.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-3 text-sm", children: [(0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Segments" }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-2", children: cfg.defaultSegmentCount == 0 ? "all" : cfg.defaultSegmentCount }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Segment Target" }), (0, import_jsx_runtime7.jsxs)("div", { className: "col-span-2", children: [cfg.targetSegmentDuration, "s"] }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Part Target" }), (0, import_jsx_runtime7.jsxs)("div", { className: "col-span-2", children: [cfg.targetPartDuration, "s"] }), (0, import_jsx_runtime7.jsx)("div", { className: "col-span-1", children: "Retention" }), (0, import_jsx_runtime7.jsxs)("div", { className: "col-span-2", children: [cfg.retentionPeriod, "s"] })] });
583
+ return (0, import_jsx_runtime8.jsxs)("div", { className: "grid grid-flow-row-dense grid-cols-3 text-sm", children: [(0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Segments" }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-2", children: cfg.defaultSegmentCount == 0 ? "all" : cfg.defaultSegmentCount }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Segment Target" }), (0, import_jsx_runtime8.jsxs)("div", { className: "col-span-2", children: [cfg.targetSegmentDuration, "s"] }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Part Target" }), (0, import_jsx_runtime8.jsxs)("div", { className: "col-span-2", children: [cfg.targetPartDuration, "s"] }), (0, import_jsx_runtime8.jsx)("div", { className: "col-span-1", children: "Retention" }), (0, import_jsx_runtime8.jsxs)("div", { className: "col-span-2", children: [cfg.retentionPeriod, "s"] })] });
551
584
  }
552
- var import_jsx_runtime7;
585
+ var import_jsx_runtime8;
553
586
  var init_form_views = __esm({
554
587
  "build/output.autoCmaf/form-views.js"() {
555
588
  "use strict";
556
- import_jsx_runtime7 = __toESM(require_jsx_runtime());
589
+ import_jsx_runtime8 = __toESM(require_jsx_runtime());
557
590
  }
558
591
  });
559
592
 
@@ -611,7 +644,7 @@ function InlineView5({ state, config, raise }) {
611
644
  }, [config.showPreview]);
612
645
  raise && (0, import_react6.useEffect)(raise, []);
613
646
  if (!url)
614
- return (0, import_jsx_runtime8.jsx)(import_jsx_runtime8.Fragment, { children: "..." });
647
+ return (0, import_jsx_runtime9.jsx)(import_jsx_runtime9.Fragment, { children: "..." });
615
648
  function percentage(levels) {
616
649
  if (!levels) {
617
650
  return 0;
@@ -621,15 +654,15 @@ function InlineView5({ state, config, raise }) {
621
654
  const snapped = Math.floor(capped * 10) * 10;
622
655
  return Math.max(0, 100 - snapped);
623
656
  }
624
- return (0, import_jsx_runtime8.jsxs)("div", { className: "preview-outer-container", children: [(0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, import_jsx_runtime8.jsx)("input", { type: "checkbox", id: `video-toggle-${id}`, checked: showPreview, onChange: (e) => setShowPreview(e.target.checked), className: "h-4 w-4" }), (0, import_jsx_runtime8.jsx)("label", { htmlFor: `video-toggle-${id}`, className: "text-sm", children: "Show Preview" })] }), showPreview ? (0, import_jsx_runtime8.jsx)("div", { className: "preview-video", id: `preview-${id}`, children: (0, import_jsx_runtime8.jsx)("style", { children: `
657
+ return (0, import_jsx_runtime9.jsxs)("div", { className: "preview-outer-container", children: [(0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, import_jsx_runtime9.jsx)("input", { type: "checkbox", id: `video-toggle-${id}`, checked: showPreview, onChange: (e) => setShowPreview(e.target.checked), className: "h-4 w-4" }), (0, import_jsx_runtime9.jsx)("label", { htmlFor: `video-toggle-${id}`, className: "text-sm", children: "Show Preview" })] }), showPreview ? (0, import_jsx_runtime9.jsx)("div", { className: "preview-video", id: `preview-${id}`, children: (0, import_jsx_runtime9.jsx)("style", { children: `
625
658
  #preview-${id} video::-webkit-media-controls-play-button { display: none; },
626
- ` }) }) : (0, import_jsx_runtime8.jsx)("div", { className: "preview-video bg-black flex items-center justify-center text-white h-full", children: "Preview turned off" }), (0, import_jsx_runtime8.jsx)("div", { className: "preview-levels", children: (0, import_jsx_runtime8.jsx)("div", { className: `preview-level clip-${percentage(state.levels)}-preview` }) })] });
659
+ ` }) }) : (0, import_jsx_runtime9.jsx)("div", { className: "preview-video bg-black flex items-center justify-center text-white h-full", children: "Preview turned off" }), (0, import_jsx_runtime9.jsx)("div", { className: "preview-levels", children: (0, import_jsx_runtime9.jsx)("div", { className: `preview-level clip-${percentage(state.levels)}-preview` }) })] });
627
660
  }
628
- var import_jsx_runtime8, import_react6, import_webrtc_client, inline_view_default3;
661
+ var import_jsx_runtime9, import_react6, import_webrtc_client, inline_view_default3;
629
662
  var init_inline_view3 = __esm({
630
663
  "build/output.preview/inline-view.js"() {
631
664
  "use strict";
632
- import_jsx_runtime8 = __toESM(require_jsx_runtime());
665
+ import_jsx_runtime9 = __toESM(require_jsx_runtime());
633
666
  import_react6 = __toESM(require_react());
634
667
  import_webrtc_client = __toESM(require_webrtc_client());
635
668
  inline_view_default3 = InlineView5;
@@ -642,15 +675,15 @@ __export(inline_view_exports4, {
642
675
  default: () => inline_view_default4
643
676
  });
644
677
  function InlineView6({ state, config }) {
645
- const connected = (0, import_jsx_runtime9.jsx)("div", { className: "active text-green-500 dark:text-green-300", children: "Connected and publishing" });
646
- const disconnected = (0, import_jsx_runtime9.jsxs)("div", { className: "inactive text-orange-500 dark:text-orange-300", children: ["Disconnected ", state.connectRetries > 0 ? `- retrying(${state.connectRetries})` : ""] });
647
- return (0, import_jsx_runtime9.jsx)("div", { className: "rtmp-output", id: `rtmp-output-${config.id}`, children: state.connected ? connected : disconnected });
678
+ const connected = (0, import_jsx_runtime10.jsx)("div", { className: "active text-green-500 dark:text-green-300", children: "Connected and publishing" });
679
+ const disconnected = (0, import_jsx_runtime10.jsxs)("div", { className: "inactive text-orange-500 dark:text-orange-300", children: ["Disconnected ", state.connectRetries > 0 ? `- retrying(${state.connectRetries})` : ""] });
680
+ return (0, import_jsx_runtime10.jsx)("div", { className: "rtmp-output", id: `rtmp-output-${config.id}`, children: state.connected ? connected : disconnected });
648
681
  }
649
- var import_jsx_runtime9, inline_view_default4;
682
+ var import_jsx_runtime10, inline_view_default4;
650
683
  var init_inline_view4 = __esm({
651
684
  "build/output.rtmp/inline-view.js"() {
652
685
  "use strict";
653
- import_jsx_runtime9 = __toESM(require_jsx_runtime());
686
+ import_jsx_runtime10 = __toESM(require_jsx_runtime());
654
687
  inline_view_default4 = InlineView6;
655
688
  }
656
689
  });
@@ -737,23 +770,23 @@ __export(inline_view_exports5, {
737
770
  });
738
771
  function InlineView7({ state }) {
739
772
  if (!state.previous)
740
- return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
773
+ return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, {});
741
774
  const format = (stat) => Math.floor(stat).toLocaleString("en-US", { maximumFractionDigits: 0 });
742
- return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, { children: state.previous.allStreams.map((s, i) => {
775
+ return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: state.previous.allStreams.map((s, i) => {
743
776
  const metaCase = s.metadata.case;
744
777
  switch (metaCase) {
745
778
  case "audio":
746
- return (0, import_jsx_runtime10.jsxs)("div", { children: [(0, import_jsx_runtime10.jsxs)("div", { children: ["StreamKey: ", streamKey(s.streamKey)] }), (0, import_jsx_runtime10.jsxs)("div", { children: ["Bitrate: ", format(s.bitrate), "bps"] })] }, i);
779
+ return (0, import_jsx_runtime11.jsxs)("div", { children: [(0, import_jsx_runtime11.jsxs)("div", { children: ["StreamKey: ", streamKey(s.streamKey)] }), (0, import_jsx_runtime11.jsxs)("div", { children: ["Bitrate: ", format(s.bitrate), "bps"] })] }, i);
747
780
  case "video":
748
- return (0, import_jsx_runtime10.jsxs)("div", { children: [(0, import_jsx_runtime10.jsxs)("div", { children: ["StreamKey: ", streamKey(s.streamKey)] }), (0, import_jsx_runtime10.jsxs)("div", { children: ["Bitrate: ", format(s.bitrate), "bps"] })] }, i);
781
+ return (0, import_jsx_runtime11.jsxs)("div", { children: [(0, import_jsx_runtime11.jsxs)("div", { children: ["StreamKey: ", streamKey(s.streamKey)] }), (0, import_jsx_runtime11.jsxs)("div", { children: ["Bitrate: ", format(s.bitrate), "bps"] })] }, i);
749
782
  case "ancillary":
750
- return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
783
+ return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, {});
751
784
  case "subtitle":
752
- return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
785
+ return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, {});
753
786
  case "playlist":
754
- return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
787
+ return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, {});
755
788
  case void 0:
756
- return (0, import_jsx_runtime10.jsx)(import_jsx_runtime10.Fragment, {});
789
+ return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, {});
757
790
  default:
758
791
  assertUnreachable7(metaCase);
759
792
  }
@@ -762,11 +795,11 @@ function InlineView7({ state }) {
762
795
  function streamKey(streamKey2) {
763
796
  return streamKey2.streamId.toString();
764
797
  }
765
- var import_jsx_runtime10, inline_view_default5;
798
+ var import_jsx_runtime11, inline_view_default5;
766
799
  var init_inline_view5 = __esm({
767
800
  "build/output.statistics/inline-view.js"() {
768
801
  "use strict";
769
- import_jsx_runtime10 = __toESM(require_jsx_runtime());
802
+ import_jsx_runtime11 = __toESM(require_jsx_runtime());
770
803
  init_info();
771
804
  inline_view_default5 = InlineView7;
772
805
  }
@@ -823,6 +856,39 @@ var init_info = __esm({
823
856
  }
824
857
  });
825
858
 
859
+ // build/output.whep/summary-view.js
860
+ var summary_view_exports4 = {};
861
+ __export(summary_view_exports4, {
862
+ default: () => summary_view_default4
863
+ });
864
+ function SummaryView6({ state, sendCommand }) {
865
+ const handleEnableOutput = () => {
866
+ void enableOutput();
867
+ };
868
+ const enableOutput = async () => {
869
+ sendCommand({
870
+ type: "enable-output"
871
+ });
872
+ };
873
+ const handleDisableOutput = () => {
874
+ void disableOutput();
875
+ };
876
+ const disableOutput = async () => {
877
+ sendCommand({
878
+ type: "disable-output"
879
+ });
880
+ };
881
+ return (0, import_jsx_runtime12.jsx)("div", { className: "mb-5", children: (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center justify-between mb-3", children: [(0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center space-x-2", children: [(0, import_jsx_runtime12.jsx)("span", { className: `inline-block w-2 h-2 rounded-full ${state.enabled ? "bg-blue-500" : "bg-red-500"}` }), (0, import_jsx_runtime12.jsxs)("span", { className: "text-sm", children: ["Status: ", state.enabled ? "Enabled" : "Disabled"] })] }), (0, import_jsx_runtime12.jsx)("div", { children: state.enabled ? (0, import_jsx_runtime12.jsx)("button", { onClick: handleDisableOutput, className: "px-3 py-1 text-sm bg-red-600 hover:bg-red-700 text-white rounded", children: "Disable Output" }) : (0, import_jsx_runtime12.jsx)("button", { onClick: handleEnableOutput, className: "px-3 py-1 text-sm bg-blue-600 hover:bg-blue-700 text-white rounded", children: "Enable Output" }) })] }) });
882
+ }
883
+ var import_jsx_runtime12, summary_view_default4;
884
+ var init_summary_view4 = __esm({
885
+ "build/output.whep/summary-view.js"() {
886
+ "use strict";
887
+ import_jsx_runtime12 = __toESM(require_jsx_runtime());
888
+ summary_view_default4 = SummaryView6;
889
+ }
890
+ });
891
+
826
892
  // build/output.whep/inline-view.js
827
893
  var inline_view_exports6 = {};
828
894
  __export(inline_view_exports6, {
@@ -870,19 +936,19 @@ function InlineView8({ state, config, raise }) {
870
936
  }, [config.showPreview]);
871
937
  raise && (0, import_react11.useEffect)(raise, []);
872
938
  if (!url)
873
- return (0, import_jsx_runtime11.jsx)(import_jsx_runtime11.Fragment, { children: "..." });
939
+ return (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children: "..." });
874
940
  const videoStyles = `
875
941
  #whep-${id} video::-webkit-media-controls-play-button {
876
942
  display: none;
877
943
  }
878
944
  `;
879
- return (0, import_jsx_runtime11.jsxs)("div", { className: "whep-container", children: [(0, import_jsx_runtime11.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, import_jsx_runtime11.jsx)("input", { type: "checkbox", id: `video-toggle-${id}`, checked: showPreview, onChange: (e) => setShowPreview(e.target.checked), className: "h-4 w-4" }), (0, import_jsx_runtime11.jsx)("label", { htmlFor: `video-toggle-${id}`, className: "text-sm", children: "Show Preview" })] }), showPreview ? (0, import_jsx_runtime11.jsx)("div", { className: "whep-video", id: `whep-${id}`, children: (0, import_jsx_runtime11.jsx)("style", { children: videoStyles }) }) : (0, import_jsx_runtime11.jsx)("div", { className: "whep-video bg-black flex items-center justify-center text-white h-full", children: "Preview turned off" })] });
945
+ return (0, import_jsx_runtime13.jsxs)("div", { className: "whep-container", children: [(0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2 mb-2", children: [(0, import_jsx_runtime13.jsx)("input", { type: "checkbox", id: `video-toggle-${id}`, checked: showPreview, onChange: (e) => setShowPreview(e.target.checked), className: "h-4 w-4" }), (0, import_jsx_runtime13.jsx)("label", { htmlFor: `video-toggle-${id}`, className: "text-sm", children: "Show Preview" })] }), showPreview ? (0, import_jsx_runtime13.jsx)("div", { className: "whep-video", id: `whep-${id}`, children: (0, import_jsx_runtime13.jsx)("style", { children: videoStyles }) }) : (0, import_jsx_runtime13.jsx)("div", { className: "whep-video bg-black flex items-center justify-center text-white h-full", children: "Preview turned off" })] });
880
946
  }
881
- var import_jsx_runtime11, import_react11, import_webrtc_client2, inline_view_default6;
947
+ var import_jsx_runtime13, import_react11, import_webrtc_client2, inline_view_default6;
882
948
  var init_inline_view6 = __esm({
883
949
  "build/output.whep/inline-view.js"() {
884
950
  "use strict";
885
- import_jsx_runtime11 = __toESM(require_jsx_runtime());
951
+ import_jsx_runtime13 = __toESM(require_jsx_runtime());
886
952
  import_react11 = __toESM(require_react());
887
953
  import_webrtc_client2 = __toESM(require_webrtc_client());
888
954
  inline_view_default6 = InlineView8;
@@ -890,18 +956,18 @@ var init_inline_view6 = __esm({
890
956
  });
891
957
 
892
958
  // build/processor.browserOverlay/summary-view.js
893
- var summary_view_exports3 = {};
894
- __export(summary_view_exports3, {
895
- default: () => summary_view_default3
959
+ var summary_view_exports5 = {};
960
+ __export(summary_view_exports5, {
961
+ default: () => summary_view_default5
896
962
  });
897
- function SummaryView5({ state, sendCommand }) {
963
+ function SummaryView8({ state, sendCommand }) {
898
964
  const [url, setUrl] = (0, import_react13.useState)(state.currentUrl);
899
965
  const [enabled, setEnabled] = (0, import_react13.useState)(state.enabled);
900
966
  const stateChanged = (0, import_react13.useMemo)(() => {
901
967
  return url !== state.currentUrl || enabled !== state.enabled;
902
968
  }, [url, enabled]);
903
969
  const buttonClass = "mt-2 mb-5 text-white w-full justify-center bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800";
904
- return (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-3 mb-5", children: [(0, import_jsx_runtime12.jsx)("h2", { className: "text-xl font-bold text-gray-900 dark:text-white", children: "Controls" }), (0, import_jsx_runtime12.jsxs)("div", { className: "mb-5", children: [(0, import_jsx_runtime12.jsx)("label", { htmlFor: "url", className: "mb-2 mr-2 text-sm font-medium text-gray-900 dark:text-white", children: "URL" }), (0, import_jsx_runtime12.jsx)("input", { type: "email", id: "url", className: "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500", value: url, onChange: (e) => setUrl(e.target.value), required: true })] }), (0, import_jsx_runtime12.jsx)("div", { className: "mb-5", children: (0, import_jsx_runtime12.jsxs)("label", { className: "inline-flex items-center cursor-pointer", children: [(0, import_jsx_runtime12.jsx)("span", { className: "me-3 text-sm font-medium text-gray-900 dark:text-gray-300", children: "Enabled" }), (0, import_jsx_runtime12.jsx)("input", { type: "checkbox", checked: enabled, onChange: (e) => setEnabled(e.target.checked), className: "sr-only peer" }), (0, import_jsx_runtime12.jsx)("div", { className: "relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600" })] }) }), (0, import_jsx_runtime12.jsx)("button", { type: "button", className: `${buttonClass} ${!stateChanged ? "opacity-50 cursor-not-allowed" : ""}`, disabled: !stateChanged, onClick: () => {
970
+ return (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-3 mb-5", children: [(0, import_jsx_runtime14.jsx)("h2", { className: "text-xl font-bold text-gray-900 dark:text-white", children: "Controls" }), (0, import_jsx_runtime14.jsxs)("div", { className: "mb-5", children: [(0, import_jsx_runtime14.jsx)("label", { htmlFor: "url", className: "mb-2 mr-2 text-sm font-medium text-gray-900 dark:text-white", children: "URL" }), (0, import_jsx_runtime14.jsx)("input", { type: "email", id: "url", className: "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500", value: url, onChange: (e) => setUrl(e.target.value), required: true })] }), (0, import_jsx_runtime14.jsx)("div", { className: "mb-5", children: (0, import_jsx_runtime14.jsxs)("label", { className: "inline-flex items-center cursor-pointer", children: [(0, import_jsx_runtime14.jsx)("span", { className: "me-3 text-sm font-medium text-gray-900 dark:text-gray-300", children: "Enabled" }), (0, import_jsx_runtime14.jsx)("input", { type: "checkbox", checked: enabled, onChange: (e) => setEnabled(e.target.checked), className: "sr-only peer" }), (0, import_jsx_runtime14.jsx)("div", { className: "relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600" })] }) }), (0, import_jsx_runtime14.jsx)("button", { type: "button", className: `${buttonClass} ${!stateChanged ? "opacity-50 cursor-not-allowed" : ""}`, disabled: !stateChanged, onClick: () => {
905
971
  if (url !== state.currentUrl) {
906
972
  sendCommand({ type: "change-url", url });
907
973
  }
@@ -914,13 +980,13 @@ function SummaryView5({ state, sendCommand }) {
914
980
  }
915
981
  }, children: "Commit" })] });
916
982
  }
917
- var import_jsx_runtime12, import_react13, summary_view_default3;
918
- var init_summary_view3 = __esm({
983
+ var import_jsx_runtime14, import_react13, summary_view_default5;
984
+ var init_summary_view5 = __esm({
919
985
  "build/processor.browserOverlay/summary-view.js"() {
920
986
  "use strict";
921
- import_jsx_runtime12 = __toESM(require_jsx_runtime());
987
+ import_jsx_runtime14 = __toESM(require_jsx_runtime());
922
988
  import_react13 = __toESM(require_react());
923
- summary_view_default3 = SummaryView5;
989
+ summary_view_default5 = SummaryView8;
924
990
  }
925
991
  });
926
992
 
@@ -930,13 +996,13 @@ __export(inline_view_exports7, {
930
996
  default: () => inline_view_default7
931
997
  });
932
998
  function InlineView9({ state, config }) {
933
- return (0, import_jsx_runtime13.jsx)("div", { id: `browser-overlay-${config.id}`, children: (0, import_jsx_runtime13.jsxs)("div", { className: "w-64 grid grid-cols-[min-content,1fr] gap-2", children: [(0, import_jsx_runtime13.jsx)("div", { children: "URL:" }), (0, import_jsx_runtime13.jsx)("div", { className: "truncate", children: state.currentUrl }), (0, import_jsx_runtime13.jsx)("div", { children: "Enabled:" }), (0, import_jsx_runtime13.jsx)("div", { children: (0, import_jsx_runtime13.jsxs)("label", { className: "inline-flex items-center cursor-pointer", children: [(0, import_jsx_runtime13.jsx)("input", { type: "checkbox", checked: state.enabled, disabled: true, className: "sr-only peer" }), (0, import_jsx_runtime13.jsx)("div", { className: "relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600" })] }) })] }) });
999
+ return (0, import_jsx_runtime15.jsx)("div", { id: `browser-overlay-${config.id}`, children: (0, import_jsx_runtime15.jsxs)("div", { className: "w-64 grid grid-cols-[min-content,1fr] gap-2", children: [(0, import_jsx_runtime15.jsx)("div", { children: "URL:" }), (0, import_jsx_runtime15.jsx)("div", { className: "truncate", children: state.currentUrl }), (0, import_jsx_runtime15.jsx)("div", { children: "Enabled:" }), (0, import_jsx_runtime15.jsx)("div", { children: (0, import_jsx_runtime15.jsxs)("label", { className: "inline-flex items-center cursor-pointer", children: [(0, import_jsx_runtime15.jsx)("input", { type: "checkbox", checked: state.enabled, disabled: true, className: "sr-only peer" }), (0, import_jsx_runtime15.jsx)("div", { className: "relative w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full rtl:peer-checked:after:-translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:start-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600" })] }) })] }) });
934
1000
  }
935
- var import_jsx_runtime13, inline_view_default7;
1001
+ var import_jsx_runtime15, inline_view_default7;
936
1002
  var init_inline_view7 = __esm({
937
1003
  "build/processor.browserOverlay/inline-view.js"() {
938
1004
  "use strict";
939
- import_jsx_runtime13 = __toESM(require_jsx_runtime());
1005
+ import_jsx_runtime15 = __toESM(require_jsx_runtime());
940
1006
  inline_view_default7 = InlineView9;
941
1007
  }
942
1008
  });
@@ -952,10 +1018,10 @@ function OrderInput(props) {
952
1018
  }, [props.defaultValue]);
953
1019
  const [value, setValue] = (0, import_react15.useState)(props.defaultValue ?? []);
954
1020
  if (value.length == 0) {
955
- return (0, import_jsx_runtime14.jsx)("p", { className: "node-editor-helper-text", children: "Sources will appear here when subscriptions have been added to this node" });
1021
+ return (0, import_jsx_runtime16.jsx)("p", { className: "node-editor-helper-text", children: "Sources will appear here when subscriptions have been added to this node" });
956
1022
  } else {
957
- return (0, import_jsx_runtime14.jsx)("div", { id: props.id, children: (0, import_jsx_runtime14.jsx)("ul", { children: value.map((v, ix) => {
958
- return (0, import_jsx_runtime14.jsxs)("li", { className: "flex", children: [(0, import_jsx_runtime14.jsx)("span", { className: "node-editor-label flex-grow", children: v }), ix == 0 ? (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, {}) : (0, import_jsx_runtime14.jsx)("svg", { onClick: moveUp(ix), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, className: "w-4 h-6 shrink cursor-pointer stroke-gray-700 dark:stroke-gray-50", children: (0, import_jsx_runtime14.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 6.75L12 3m0 0l3.75 3.75M12 3v18" }) }), ix == value.length - 1 ? (0, import_jsx_runtime14.jsx)(import_jsx_runtime14.Fragment, {}) : (0, import_jsx_runtime14.jsx)("svg", { onClick: moveDown(ix), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, className: "w-4 h-6 shrink cursor-pointer stroke-gray-700 dark:stroke-gray-50", children: (0, import_jsx_runtime14.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 17.25L12 21m0 0l-3.75-3.75M12 21V3" }) })] }, v);
1023
+ return (0, import_jsx_runtime16.jsx)("div", { id: props.id, children: (0, import_jsx_runtime16.jsx)("ul", { children: value.map((v, ix) => {
1024
+ return (0, import_jsx_runtime16.jsxs)("li", { className: "flex", children: [(0, import_jsx_runtime16.jsx)("span", { className: "node-editor-label flex-grow", children: v }), ix == 0 ? (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, {}) : (0, import_jsx_runtime16.jsx)("svg", { onClick: moveUp(ix), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, className: "w-4 h-6 shrink cursor-pointer stroke-gray-700 dark:stroke-gray-50", children: (0, import_jsx_runtime16.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 6.75L12 3m0 0l3.75 3.75M12 3v18" }) }), ix == value.length - 1 ? (0, import_jsx_runtime16.jsx)(import_jsx_runtime16.Fragment, {}) : (0, import_jsx_runtime16.jsx)("svg", { onClick: moveDown(ix), xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, className: "w-4 h-6 shrink cursor-pointer stroke-gray-700 dark:stroke-gray-50", children: (0, import_jsx_runtime16.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 17.25L12 21m0 0l-3.75-3.75M12 21V3" }) })] }, v);
959
1025
  }) }) });
960
1026
  }
961
1027
  function moveUp(ix) {
@@ -977,11 +1043,11 @@ function OrderInput(props) {
977
1043
  };
978
1044
  }
979
1045
  }
980
- var import_jsx_runtime14, import_react15, source_selection_default;
1046
+ var import_jsx_runtime16, import_react15, source_selection_default;
981
1047
  var init_source_selection = __esm({
982
1048
  "build/processor.cascadingSwitch/source-selection.js"() {
983
1049
  "use strict";
984
- import_jsx_runtime14 = __toESM(require_jsx_runtime());
1050
+ import_jsx_runtime16 = __toESM(require_jsx_runtime());
985
1051
  import_react15 = __toESM(require_react());
986
1052
  source_selection_default = OrderInput;
987
1053
  }
@@ -993,13 +1059,13 @@ __export(inline_view_exports8, {
993
1059
  default: () => inline_view_default8
994
1060
  });
995
1061
  function InlineView11({ state, config }) {
996
- return (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [(0, import_jsx_runtime15.jsx)("h5", { children: "Sources" }), (0, import_jsx_runtime15.jsxs)("ul", { children: [config.sources.map((s, i) => state.activeSource == s ? (0, import_jsx_runtime15.jsxs)("li", { className: activeClasses, children: [s, " <--"] }, i) : state.availableSources.includes(s) ? (0, import_jsx_runtime15.jsxs)("li", { className: availableClasses, children: [s, " (available)"] }, i) : (0, import_jsx_runtime15.jsxs)("li", { className: inactiveClasses, children: [s, " (inactive)"] }, i)), (0, import_jsx_runtime15.jsx)("li", { className: state.activeSource == "fallback" ? activeClasses : availableClasses, children: "fallback" }, "fallback")] })] });
1062
+ return (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [(0, import_jsx_runtime17.jsx)("h5", { children: "Sources" }), (0, import_jsx_runtime17.jsxs)("ul", { children: [config.sources.map((s, i) => state.activeSource == s ? (0, import_jsx_runtime17.jsxs)("li", { className: activeClasses, children: [s, " <--"] }, i) : state.availableSources.includes(s) ? (0, import_jsx_runtime17.jsxs)("li", { className: availableClasses, children: [s, " (available)"] }, i) : (0, import_jsx_runtime17.jsxs)("li", { className: inactiveClasses, children: [s, " (inactive)"] }, i)), (0, import_jsx_runtime17.jsx)("li", { className: state.activeSource == "fallback" ? activeClasses : availableClasses, children: "fallback" }, "fallback")] })] });
997
1063
  }
998
- var import_jsx_runtime15, activeClasses, availableClasses, inactiveClasses, inline_view_default8;
1064
+ var import_jsx_runtime17, activeClasses, availableClasses, inactiveClasses, inline_view_default8;
999
1065
  var init_inline_view8 = __esm({
1000
1066
  "build/processor.cascadingSwitch/inline-view.js"() {
1001
1067
  "use strict";
1002
- import_jsx_runtime15 = __toESM(require_jsx_runtime());
1068
+ import_jsx_runtime17 = __toESM(require_jsx_runtime());
1003
1069
  activeClasses = "active text-green-500 dark:text-green-300";
1004
1070
  availableClasses = "available text-green-500 dark:text-green-300";
1005
1071
  inactiveClasses = "inactive text-orange-500 dark:text-orange-300";
@@ -1013,13 +1079,13 @@ __export(rung_view_exports, {
1013
1079
  default: () => rung_view_default
1014
1080
  });
1015
1081
  function rung_view_default(rung) {
1016
- return (0, import_jsx_runtime16.jsx)("div", { className: "text-gray-900 dark:text-white", children: rung.name });
1082
+ return (0, import_jsx_runtime18.jsx)("div", { className: "text-gray-900 dark:text-white", children: rung.name });
1017
1083
  }
1018
- var import_jsx_runtime16;
1084
+ var import_jsx_runtime18;
1019
1085
  var init_rung_view = __esm({
1020
1086
  "build/processor.fixedLadder/rung-view.js"() {
1021
1087
  "use strict";
1022
- import_jsx_runtime16 = __toESM(require_jsx_runtime());
1088
+ import_jsx_runtime18 = __toESM(require_jsx_runtime());
1023
1089
  }
1024
1090
  });
1025
1091
 
@@ -1042,7 +1108,7 @@ function CodecEditor(props) {
1042
1108
  target.style.height = target.scrollHeight + "px";
1043
1109
  }
1044
1110
  }, []);
1045
- return (0, import_jsx_runtime17.jsx)("textarea", { ref: textAreaRef, className: "w-full min-h-fit bg-white text-gray-900 dark:text-white dark:bg-black", onChange: (e) => {
1111
+ return (0, import_jsx_runtime19.jsx)("textarea", { ref: textAreaRef, className: "w-full min-h-fit bg-white text-gray-900 dark:text-white dark:bg-black", onChange: (e) => {
1046
1112
  const target = e.currentTarget;
1047
1113
  try {
1048
1114
  const codec = JSON.parse(target.value);
@@ -1052,11 +1118,11 @@ function CodecEditor(props) {
1052
1118
  }
1053
1119
  }, defaultValue: JSON.stringify(value, void 0, 2) });
1054
1120
  }
1055
- var import_jsx_runtime17, import_react16;
1121
+ var import_jsx_runtime19, import_react16;
1056
1122
  var init_codec_editor = __esm({
1057
1123
  "build/processor.fixedLadder/codec-editor.js"() {
1058
1124
  "use strict";
1059
- import_jsx_runtime17 = __toESM(require_jsx_runtime());
1125
+ import_jsx_runtime19 = __toESM(require_jsx_runtime());
1060
1126
  import_react16 = __toESM(require_react());
1061
1127
  }
1062
1128
  });
@@ -1067,13 +1133,13 @@ __export(codec_view_exports, {
1067
1133
  default: () => CodecEditor2
1068
1134
  });
1069
1135
  function CodecEditor2(props) {
1070
- return (0, import_jsx_runtime18.jsxs)("div", { className: "text-gray-900 dark:text-white", children: [props.width, "x", props.height] });
1136
+ return (0, import_jsx_runtime20.jsxs)("div", { className: "text-gray-900 dark:text-white", children: [props.width, "x", props.height] });
1071
1137
  }
1072
- var import_jsx_runtime18;
1138
+ var import_jsx_runtime20;
1073
1139
  var init_codec_view = __esm({
1074
1140
  "build/processor.fixedLadder/codec-view.js"() {
1075
1141
  "use strict";
1076
- import_jsx_runtime18 = __toESM(require_jsx_runtime());
1142
+ import_jsx_runtime20 = __toESM(require_jsx_runtime());
1077
1143
  }
1078
1144
  });
1079
1145
 
@@ -1102,34 +1168,34 @@ function GraphicSelection(props) {
1102
1168
  }, []);
1103
1169
  const [graphcs, setGraphics] = (0, import_react18.useState)([]);
1104
1170
  if (loading) {
1105
- return (0, import_jsx_runtime19.jsx)("div", { children: "Loading.." });
1171
+ return (0, import_jsx_runtime21.jsx)("div", { children: "Loading.." });
1106
1172
  }
1107
1173
  if (graphcs.length == 0) {
1108
- return (0, import_jsx_runtime19.jsx)("div", { children: "No graphics loaded" });
1174
+ return (0, import_jsx_runtime21.jsx)("div", { children: "No graphics loaded" });
1109
1175
  }
1110
- return (0, import_jsx_runtime19.jsx)("div", { children: (0, import_jsx_runtime19.jsxs)("select", { defaultValue: props.defaultValue, className: `node-editor-select-input`, id: props.id, onChange: myOnChange, onBlur: myOnChange, children: [(0, import_jsx_runtime19.jsx)("option", { value: "", children: "---" }, "empty"), graphcs.map((o, i) => {
1111
- return (0, import_jsx_runtime19.jsx)("option", { value: o, children: o }, i);
1176
+ return (0, import_jsx_runtime21.jsx)("div", { children: (0, import_jsx_runtime21.jsxs)("select", { defaultValue: props.defaultValue, className: `node-editor-select-input`, id: props.id, onChange: myOnChange, onBlur: myOnChange, children: [(0, import_jsx_runtime21.jsx)("option", { value: "", children: "---" }, "empty"), graphcs.map((o, i) => {
1177
+ return (0, import_jsx_runtime21.jsx)("option", { value: o, children: o }, i);
1112
1178
  })] }) });
1113
1179
  function myOnChange(e) {
1114
1180
  props.onChanged(e.target.value);
1115
1181
  }
1116
1182
  }
1117
- var import_jsx_runtime19, import_react18, image_selection_default;
1183
+ var import_jsx_runtime21, import_react18, image_selection_default;
1118
1184
  var init_image_selection = __esm({
1119
1185
  "build/processor.onscreenGraphic/image-selection.js"() {
1120
1186
  "use strict";
1121
- import_jsx_runtime19 = __toESM(require_jsx_runtime());
1187
+ import_jsx_runtime21 = __toESM(require_jsx_runtime());
1122
1188
  import_react18 = __toESM(require_react());
1123
1189
  image_selection_default = GraphicSelection;
1124
1190
  }
1125
1191
  });
1126
1192
 
1127
1193
  // build/processor.onscreenGraphic/summary-view.js
1128
- var summary_view_exports4 = {};
1129
- __export(summary_view_exports4, {
1130
- default: () => summary_view_default4
1194
+ var summary_view_exports6 = {};
1195
+ __export(summary_view_exports6, {
1196
+ default: () => summary_view_default6
1131
1197
  });
1132
- function SummaryView7({ state, sendCommand, urls }) {
1198
+ function SummaryView10({ state, sendCommand, urls }) {
1133
1199
  const [graphic, setGraphic] = (0, import_react19.useState)(state.activeGraphic?.file);
1134
1200
  const [position, setPosition] = (0, import_react19.useState)(state.activeGraphic?.position ?? { type: "named", position: "topleft" });
1135
1201
  const [graphics, setGraphics] = (0, import_react19.useState)([]);
@@ -1264,7 +1330,7 @@ function SummaryView7({ state, sendCommand, urls }) {
1264
1330
  const buttonClass = "mt-2 mb-5 text-white w-full justify-center bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800";
1265
1331
  const deleteButtonClass = "mt-2 text-white w-full justify-center bg-red-600 hover:bg-red-700 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-red-700 dark:hover:bg-red-800 dark:focus:ring-red-900";
1266
1332
  const fileInputClass = "block w-full text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400";
1267
- return (0, import_jsx_runtime20.jsxs)("div", { className: "space-y-3", children: [(0, import_jsx_runtime20.jsx)("h2", { className: "text-xl font-bold text-gray-900 dark:text-white", children: "Controls" }), (0, import_jsx_runtime20.jsxs)("div", { children: [(0, import_jsx_runtime20.jsx)("label", { htmlFor: "select-graphic", className: "block text-gray-900 dark:text-white mb-1", children: "Source" }), (0, import_jsx_runtime20.jsxs)("select", { id: "select-graphic", className: "w-full node-editor-select-input", value: graphic || "", onChange: (e) => setGraphic(e.target.value || void 0), children: [(0, import_jsx_runtime20.jsx)("option", { value: "", children: "---" }), graphics.map((s) => (0, import_jsx_runtime20.jsx)("option", { value: s, children: s }, s))] })] }), graphic && (0, import_jsx_runtime20.jsxs)("div", { children: [(0, import_jsx_runtime20.jsx)("label", { htmlFor: "select-position", className: "block text-gray-900 dark:text-white mb-1", children: "Graphic position" }), (0, import_jsx_runtime20.jsx)(PositionSelector, { initialPosition: position, onChange: setPosition, graphicChanged, ...state })] }), (0, import_jsx_runtime20.jsx)("button", { type: "button", className: `${buttonClass} ${!stateChanged ? "opacity-50 cursor-not-allowed" : ""}`, onClick: () => sendCommand({ type: "change-graphic", file: graphic, position }), disabled: !stateChanged, children: "Commit" }), !showFileInput && !uploadStatus.success && (0, import_jsx_runtime20.jsx)("button", { type: "button", className: buttonClass, onClick: () => setShowFileInput(true), style: { marginBottom: "1rem" }, children: "Upload Graphic" }), showFileInput && (0, import_jsx_runtime20.jsxs)("form", { style: { display: "block", marginBottom: "1rem" }, children: [(0, import_jsx_runtime20.jsx)("input", { type: "file", id: "file", name: "filename", onChange: onFileChange, className: fileInputClass }), showUploadButton && (0, import_jsx_runtime20.jsx)("button", { type: "button", className: buttonClass, onClick: uploadFile, children: "Upload" })] }), (0, import_jsx_runtime20.jsx)("button", { type: "button", className: deleteButtonClass, onClick: () => setShowDeleteDropdown(!showDeleteDropdown), style: { marginBottom: "1rem" }, children: showDeleteDropdown ? "Hide Delete Options" : "Delete Graphics" }), showDeleteDropdown && (0, import_jsx_runtime20.jsxs)("div", { className: "mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded-lg", children: [(0, import_jsx_runtime20.jsx)("h3", { className: "text-lg font-semibold mb-2 text-gray-900 dark:text-white", children: "Select Graphic to Delete" }), (0, import_jsx_runtime20.jsxs)("select", { className: "w-full mb-2 node-editor-select-input", value: graphicToDelete, onChange: (e) => setGraphicToDelete(e.target.value), children: [(0, import_jsx_runtime20.jsx)("option", { value: "", children: " Select a graphic" }), graphics.map((graphicName) => (0, import_jsx_runtime20.jsx)("option", { value: graphicName, children: graphicName }, graphicName))] }), (0, import_jsx_runtime20.jsx)("button", { onClick: deleteBug, disabled: !graphicToDelete, className: `${deleteButtonClass} ${!graphicToDelete ? "opacity-50 cursor-not-allowed" : ""}`, children: "Delete Selected Graphic" })] }), uploadStatus.message && (0, import_jsx_runtime20.jsx)("div", { className: `mt-2 text-center ${uploadStatus.success ? "text-green-600" : "text-red-600"}`, children: uploadStatus.message })] });
1333
+ return (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-3", children: [(0, import_jsx_runtime22.jsx)("h2", { className: "text-xl font-bold text-gray-900 dark:text-white", children: "Controls" }), (0, import_jsx_runtime22.jsxs)("div", { children: [(0, import_jsx_runtime22.jsx)("label", { htmlFor: "select-graphic", className: "block text-gray-900 dark:text-white mb-1", children: "Source" }), (0, import_jsx_runtime22.jsxs)("select", { id: "select-graphic", className: "w-full node-editor-select-input", value: graphic || "", onChange: (e) => setGraphic(e.target.value || void 0), children: [(0, import_jsx_runtime22.jsx)("option", { value: "", children: "---" }), graphics.map((s) => (0, import_jsx_runtime22.jsx)("option", { value: s, children: s }, s))] })] }), graphic && (0, import_jsx_runtime22.jsxs)("div", { children: [(0, import_jsx_runtime22.jsx)("label", { htmlFor: "select-position", className: "block text-gray-900 dark:text-white mb-1", children: "Graphic position" }), (0, import_jsx_runtime22.jsx)(PositionSelector, { initialPosition: position, onChange: setPosition, graphicChanged, ...state })] }), (0, import_jsx_runtime22.jsx)("button", { type: "button", className: `${buttonClass} ${!stateChanged ? "opacity-50 cursor-not-allowed" : ""}`, onClick: () => sendCommand({ type: "change-graphic", file: graphic, position }), disabled: !stateChanged, children: "Commit" }), !showFileInput && !uploadStatus.success && (0, import_jsx_runtime22.jsx)("button", { type: "button", className: buttonClass, onClick: () => setShowFileInput(true), style: { marginBottom: "1rem" }, children: "Upload Graphic" }), showFileInput && (0, import_jsx_runtime22.jsxs)("form", { style: { display: "block", marginBottom: "1rem" }, children: [(0, import_jsx_runtime22.jsx)("input", { type: "file", id: "file", name: "filename", onChange: onFileChange, className: fileInputClass }), showUploadButton && (0, import_jsx_runtime22.jsx)("button", { type: "button", className: buttonClass, onClick: uploadFile, children: "Upload" })] }), (0, import_jsx_runtime22.jsx)("button", { type: "button", className: deleteButtonClass, onClick: () => setShowDeleteDropdown(!showDeleteDropdown), style: { marginBottom: "1rem" }, children: showDeleteDropdown ? "Hide Delete Options" : "Delete Graphics" }), showDeleteDropdown && (0, import_jsx_runtime22.jsxs)("div", { className: "mt-2 p-2 bg-gray-100 dark:bg-gray-800 rounded-lg", children: [(0, import_jsx_runtime22.jsx)("h3", { className: "text-lg font-semibold mb-2 text-gray-900 dark:text-white", children: "Select Graphic to Delete" }), (0, import_jsx_runtime22.jsxs)("select", { className: "w-full mb-2 node-editor-select-input", value: graphicToDelete, onChange: (e) => setGraphicToDelete(e.target.value), children: [(0, import_jsx_runtime22.jsx)("option", { value: "", children: " Select a graphic" }), graphics.map((graphicName) => (0, import_jsx_runtime22.jsx)("option", { value: graphicName, children: graphicName }, graphicName))] }), (0, import_jsx_runtime22.jsx)("button", { onClick: deleteBug, disabled: !graphicToDelete, className: `${deleteButtonClass} ${!graphicToDelete ? "opacity-50 cursor-not-allowed" : ""}`, children: "Delete Selected Graphic" })] }), uploadStatus.message && (0, import_jsx_runtime22.jsx)("div", { className: `mt-2 text-center ${uploadStatus.success ? "text-green-600" : "text-red-600"}`, children: uploadStatus.message })] });
1268
1334
  }
1269
1335
  function convertPosition(givenPosition, currentVideo, currentGraphic) {
1270
1336
  if (!givenPosition)
@@ -1310,11 +1376,11 @@ function clamp(min, num, max) {
1310
1376
  function assertUnreachable12(_) {
1311
1377
  throw new Error("Didn't expect to get here");
1312
1378
  }
1313
- var import_jsx_runtime20, import_react19, PositionSelector, summary_view_default4;
1314
- var init_summary_view4 = __esm({
1379
+ var import_jsx_runtime22, import_react19, PositionSelector, summary_view_default6;
1380
+ var init_summary_view6 = __esm({
1315
1381
  "build/processor.onscreenGraphic/summary-view.js"() {
1316
1382
  "use strict";
1317
- import_jsx_runtime20 = __toESM(require_jsx_runtime());
1383
+ import_jsx_runtime22 = __toESM(require_jsx_runtime());
1318
1384
  import_react19 = __toESM(require_react());
1319
1385
  PositionSelector = ({ initialPosition: givenPosition = { type: "named", position: "topleft" }, onChange, currentVideo, currentGraphic, graphicChanged }) => {
1320
1386
  const convertPos = (pos) => convertPosition(pos, currentVideo, currentGraphic);
@@ -1382,7 +1448,7 @@ var init_summary_view4 = __esm({
1382
1448
  window.removeEventListener("mouseup", handleMouseUp);
1383
1449
  };
1384
1450
  }, [isDragging]);
1385
- return (0, import_jsx_runtime20.jsxs)("div", { className: "relative w-full max-w-lg mx-auto mt-4 mb-8", children: [(0, import_jsx_runtime20.jsxs)("div", { className: "mb-4 flex items-center gap-2", children: [(0, import_jsx_runtime20.jsx)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: "Position Type:" }), (0, import_jsx_runtime20.jsxs)("select", { value: position.type, onChange: (e) => {
1451
+ return (0, import_jsx_runtime22.jsxs)("div", { className: "relative w-full max-w-lg mx-auto mt-4 mb-8", children: [(0, import_jsx_runtime22.jsxs)("div", { className: "mb-4 flex items-center gap-2", children: [(0, import_jsx_runtime22.jsx)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: "Position Type:" }), (0, import_jsx_runtime22.jsxs)("select", { value: position.type, onChange: (e) => {
1386
1452
  const newType = e.target.value;
1387
1453
  if (newType === "named") {
1388
1454
  setPosition(convertPos({ type: "named", position: "topleft" }));
@@ -1390,12 +1456,12 @@ var init_summary_view4 = __esm({
1390
1456
  setPositionUnit("%");
1391
1457
  setPosition({ ...convertPos(position), type: "percentage" });
1392
1458
  }
1393
- }, className: "node-editor-select-input", children: [(0, import_jsx_runtime20.jsx)("option", { value: "coordinate", children: "Custom Position" }), (0, import_jsx_runtime20.jsx)("option", { value: "named", children: "Preset Position" })] })] }), position.type === "named" ? (0, import_jsx_runtime20.jsx)("div", { className: "mb-4", children: (0, import_jsx_runtime20.jsxs)("select", { value: position.position, onChange: (e) => {
1459
+ }, className: "node-editor-select-input", children: [(0, import_jsx_runtime22.jsx)("option", { value: "coordinate", children: "Custom Position" }), (0, import_jsx_runtime22.jsx)("option", { value: "named", children: "Preset Position" })] })] }), position.type === "named" ? (0, import_jsx_runtime22.jsx)("div", { className: "mb-4", children: (0, import_jsx_runtime22.jsxs)("select", { value: position.position, onChange: (e) => {
1394
1460
  setPosition(convertPos({
1395
1461
  type: "named",
1396
1462
  position: e.target.value
1397
1463
  }));
1398
- }, className: "w-full node-editor-select-input", children: [(0, import_jsx_runtime20.jsx)("option", { value: "topleft", children: "Top Left" }), (0, import_jsx_runtime20.jsx)("option", { value: "topright", children: "Top Right" }), (0, import_jsx_runtime20.jsx)("option", { value: "bottomleft", children: "Bottom Left" }), (0, import_jsx_runtime20.jsx)("option", { value: "bottomright", children: "Bottom Right" }), (0, import_jsx_runtime20.jsx)("option", { value: "center", children: "Centered" })] }) }) : (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [(0, import_jsx_runtime20.jsxs)("div", { className: "mb-4 flex items-center gap-2", children: [(0, import_jsx_runtime20.jsx)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: "Position Unit:" }), (0, import_jsx_runtime20.jsxs)("select", { value: positionUnit, onChange: (e) => {
1464
+ }, className: "w-full node-editor-select-input", children: [(0, import_jsx_runtime22.jsx)("option", { value: "topleft", children: "Top Left" }), (0, import_jsx_runtime22.jsx)("option", { value: "topright", children: "Top Right" }), (0, import_jsx_runtime22.jsx)("option", { value: "bottomleft", children: "Bottom Left" }), (0, import_jsx_runtime22.jsx)("option", { value: "bottomright", children: "Bottom Right" }), (0, import_jsx_runtime22.jsx)("option", { value: "center", children: "Centered" })] }) }) : (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [(0, import_jsx_runtime22.jsxs)("div", { className: "mb-4 flex items-center gap-2", children: [(0, import_jsx_runtime22.jsx)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: "Position Unit:" }), (0, import_jsx_runtime22.jsxs)("select", { value: positionUnit, onChange: (e) => {
1399
1465
  setPositionUnit(e.target.value);
1400
1466
  if (e.target.value === "px" && position.type !== "coordinate" && currentVideo && currentGraphic) {
1401
1467
  const { width: videoWidth, height: videoHeight } = currentVideo;
@@ -1420,18 +1486,18 @@ var init_summary_view4 = __esm({
1420
1486
  yStr: void 0
1421
1487
  });
1422
1488
  }
1423
- }, className: "node-editor-select-input", children: [(0, import_jsx_runtime20.jsx)("option", { value: "px", children: "Pixels" }), (0, import_jsx_runtime20.jsx)("option", { value: "%", children: "Percentage" })] })] }), (0, import_jsx_runtime20.jsxs)("div", { className: "relative bg-gray-200 dark:bg-gray-700 rounded-lg", style: {
1489
+ }, className: "node-editor-select-input", children: [(0, import_jsx_runtime22.jsx)("option", { value: "px", children: "Pixels" }), (0, import_jsx_runtime22.jsx)("option", { value: "%", children: "Percentage" })] })] }), (0, import_jsx_runtime22.jsxs)("div", { className: "relative bg-gray-200 dark:bg-gray-700 rounded-lg", style: {
1424
1490
  width: "100%",
1425
1491
  userSelect: "none",
1426
1492
  aspectRatio: currentVideo ? `${currentVideo.width} / ${currentVideo.height}` : `3 / 2`
1427
- }, ref: previewAreaRef, children: [(0, import_jsx_runtime20.jsxs)("div", { className: "absolute inset-0 flex flex-col items-center justify-center text-gray-500 dark:text-gray-400", children: [(0, import_jsx_runtime20.jsx)("span", { children: currentVideo ? "Video Preview Area" : "Video Dimensions Unknown" }), " ", currentVideo ? (0, import_jsx_runtime20.jsxs)("span", { children: [currentVideo.width, "x", currentVideo.height, "px"] }) : ""] }), (0, import_jsx_runtime20.jsx)("div", { className: `absolute cursor-move ${currentGraphic && !graphicChanged ? "" : "p-2"} rounded-lg bg-primary-500 bg-opacity-50 hover:bg-opacity-75 transition-colors
1493
+ }, ref: previewAreaRef, children: [(0, import_jsx_runtime22.jsxs)("div", { className: "absolute inset-0 flex flex-col items-center justify-center text-gray-500 dark:text-gray-400", children: [(0, import_jsx_runtime22.jsx)("span", { children: currentVideo ? "Video Preview Area" : "Video Dimensions Unknown" }), " ", currentVideo ? (0, import_jsx_runtime22.jsxs)("span", { children: [currentVideo.width, "x", currentVideo.height, "px"] }) : ""] }), (0, import_jsx_runtime22.jsx)("div", { className: `absolute cursor-move ${currentGraphic && !graphicChanged ? "" : "p-2"} rounded-lg bg-primary-500 bg-opacity-50 hover:bg-opacity-75 transition-colors
1428
1494
  ${isDragging ? "bg-opacity-75" : ""}`, style: {
1429
1495
  left: `${position.xPct}%`,
1430
1496
  top: `${position.yPct}%`,
1431
1497
  transform: `translate(-${position.xPct}%, -${position.yPct}%)`,
1432
1498
  aspectRatio: currentGraphic && !graphicChanged ? `${currentGraphic.width} / ${currentGraphic.height}` : `1`,
1433
1499
  width: currentGraphic && currentVideo && !graphicChanged ? currentGraphic.width / currentVideo.width * 100 + "%" : void 0
1434
- }, onMouseDown: handleMouseDown, ref: previewTargetRef, children: (0, import_jsx_runtime20.jsx)("svg", { className: `${currentGraphic && !graphicChanged ? "w-full h-full" : "w-6 h-6"} text-white`, "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: (0, import_jsx_runtime20.jsx)("path", { stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 6v12m-6-6h12m-6-6 1.5 1.5M12 6l-1.5 1.5m1.5 10.5L10.5 16.5M12 18l1.5-1.5M6 12l1.5-1.5M7.5 13.5 6 12m12 0-1.5-1.5M16.5 13.5 18 12" }) }) })] }), (0, import_jsx_runtime20.jsxs)("div", { className: "mt-2 text-sm text-gray-600 dark:text-gray-300 text-center", children: ["Position:", " ", position.type === "percentage" ? `${position.xPct.toFixed(1)}%, ${position.yPct.toFixed(1)}%` : `${Math.round(position.x)}px, ${Math.round(position.y)}px`] }), (0, import_jsx_runtime20.jsxs)("div", { className: "mt-2 flex gap-4", children: [(0, import_jsx_runtime20.jsxs)("div", { children: [(0, import_jsx_runtime20.jsxs)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: ["X Position ", positionUnit] }), (0, import_jsx_runtime20.jsx)("input", { type: "number", step: positionUnit === "%" ? "0.1" : "1", value: position.xStr ?? (positionUnit === "%" ? position.xPct.toFixed(1) : Math.round(position.x)), onChange: (e) => {
1500
+ }, onMouseDown: handleMouseDown, ref: previewTargetRef, children: (0, import_jsx_runtime22.jsx)("svg", { className: `${currentGraphic && !graphicChanged ? "w-full h-full" : "w-6 h-6"} text-white`, "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: (0, import_jsx_runtime22.jsx)("path", { stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 6v12m-6-6h12m-6-6 1.5 1.5M12 6l-1.5 1.5m1.5 10.5L10.5 16.5M12 18l1.5-1.5M6 12l1.5-1.5M7.5 13.5 6 12m12 0-1.5-1.5M16.5 13.5 18 12" }) }) })] }), (0, import_jsx_runtime22.jsxs)("div", { className: "mt-2 text-sm text-gray-600 dark:text-gray-300 text-center", children: ["Position:", " ", position.type === "percentage" ? `${position.xPct.toFixed(1)}%, ${position.yPct.toFixed(1)}%` : `${Math.round(position.x)}px, ${Math.round(position.y)}px`] }), (0, import_jsx_runtime22.jsxs)("div", { className: "mt-2 flex gap-4", children: [(0, import_jsx_runtime22.jsxs)("div", { children: [(0, import_jsx_runtime22.jsxs)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: ["X Position ", positionUnit] }), (0, import_jsx_runtime22.jsx)("input", { type: "number", step: positionUnit === "%" ? "0.1" : "1", value: position.xStr ?? (positionUnit === "%" ? position.xPct.toFixed(1) : Math.round(position.x)), onChange: (e) => {
1435
1501
  const newX = Number(e.target.value);
1436
1502
  setPosition(convertPos({
1437
1503
  type: positionUnit === "%" ? "percentage" : "coordinate",
@@ -1440,7 +1506,7 @@ var init_summary_view4 = __esm({
1440
1506
  y: position.y,
1441
1507
  yStr: position.yStr
1442
1508
  }));
1443
- }, className: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600" })] }), (0, import_jsx_runtime20.jsxs)("div", { children: [(0, import_jsx_runtime20.jsxs)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: ["Y Position ", positionUnit] }), (0, import_jsx_runtime20.jsx)("input", { type: "number", step: positionUnit === "%" ? "0.1" : "1", value: position.yStr ?? (positionUnit === "%" ? position.yPct.toFixed(1) : Math.round(position.y)), onChange: (e) => {
1509
+ }, className: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600" })] }), (0, import_jsx_runtime22.jsxs)("div", { children: [(0, import_jsx_runtime22.jsxs)("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300", children: ["Y Position ", positionUnit] }), (0, import_jsx_runtime22.jsx)("input", { type: "number", step: positionUnit === "%" ? "0.1" : "1", value: position.yStr ?? (positionUnit === "%" ? position.yPct.toFixed(1) : Math.round(position.y)), onChange: (e) => {
1444
1510
  const newY = Number(e.target.value);
1445
1511
  setPosition(convertPos({
1446
1512
  type: positionUnit === "%" ? "percentage" : "coordinate",
@@ -1451,7 +1517,7 @@ var init_summary_view4 = __esm({
1451
1517
  }));
1452
1518
  }, className: "mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-primary-500 focus:ring-primary-500 sm:text-sm dark:bg-gray-700 dark:border-gray-600" })] })] })] })] });
1453
1519
  };
1454
- summary_view_default4 = SummaryView7;
1520
+ summary_view_default6 = SummaryView10;
1455
1521
  }
1456
1522
  });
1457
1523
 
@@ -15840,13 +15906,13 @@ function InlineView12({ state, config: _2 }) {
15840
15906
  return;
15841
15907
  chartControl.data = makeData(state);
15842
15908
  }, [state]);
15843
- return (0, import_jsx_runtime21.jsx)("div", { className: "bg-gray-50 dark:bg-gray-700 rounded", style: { width: "360px", height: "200px", padding: "10px" }, children: (0, import_jsx_runtime21.jsx)("canvas", { className: "bg-gray-50 dark:bg-gray-700 rounded", ref: chartContainer }) });
15909
+ return (0, import_jsx_runtime23.jsx)("div", { className: "bg-gray-50 dark:bg-gray-700 rounded", style: { width: "360px", height: "200px", padding: "10px" }, children: (0, import_jsx_runtime23.jsx)("canvas", { className: "bg-gray-50 dark:bg-gray-700 rounded", ref: chartContainer }) });
15844
15910
  }
15845
- var import_jsx_runtime21, import_react21, inline_view_default9;
15911
+ var import_jsx_runtime23, import_react21, inline_view_default9;
15846
15912
  var init_inline_view9 = __esm({
15847
15913
  "build/util.stats.latency/inline-view.js"() {
15848
15914
  "use strict";
15849
- import_jsx_runtime21 = __toESM(require_jsx_runtime());
15915
+ import_jsx_runtime23 = __toESM(require_jsx_runtime());
15850
15916
  import_react21 = __toESM(require_react());
15851
15917
  init_auto();
15852
15918
  inline_view_default9 = InlineView12;
@@ -15859,22 +15925,22 @@ __export(source_node_selection_exports, {
15859
15925
  default: () => source_node_selection_default
15860
15926
  });
15861
15927
  function SourceNodeSelection(props) {
15862
- return (0, import_jsx_runtime22.jsx)("div", { children: (0, import_jsx_runtime22.jsxs)("select", { defaultValue: props.defaultValue, className: `node-editor-select-input`, id: props.id, onChange: myOnChange, onBlur: myOnChange, children: [(0, import_jsx_runtime22.jsx)("option", { value: "", children: "---" }, "empty"), Object.values(props.latestDocument.components).map((o, i) => {
15928
+ return (0, import_jsx_runtime24.jsx)("div", { children: (0, import_jsx_runtime24.jsxs)("select", { defaultValue: props.defaultValue, className: `node-editor-select-input`, id: props.id, onChange: myOnChange, onBlur: myOnChange, children: [(0, import_jsx_runtime24.jsx)("option", { value: "", children: "---" }, "empty"), Object.values(props.latestDocument.components).map((o, i) => {
15863
15929
  if (o.id == props.id)
15864
- return (0, import_jsx_runtime22.jsx)(import_jsx_runtime22.Fragment, {});
15930
+ return (0, import_jsx_runtime24.jsx)(import_jsx_runtime24.Fragment, {});
15865
15931
  if (o.info.category === "output")
15866
15932
  return;
15867
- return (0, import_jsx_runtime22.jsx)("option", { value: o.id, children: o.config.displayName }, i);
15933
+ return (0, import_jsx_runtime24.jsx)("option", { value: o.id, children: o.config.displayName }, i);
15868
15934
  })] }) });
15869
15935
  function myOnChange(e) {
15870
15936
  props.onChanged(e.target.value);
15871
15937
  }
15872
15938
  }
15873
- var import_jsx_runtime22, source_node_selection_default;
15939
+ var import_jsx_runtime24, source_node_selection_default;
15874
15940
  var init_source_node_selection = __esm({
15875
15941
  "build/util.stats.latency/source-node-selection.js"() {
15876
15942
  "use strict";
15877
- import_jsx_runtime22 = __toESM(require_jsx_runtime());
15943
+ import_jsx_runtime24 = __toESM(require_jsx_runtime());
15878
15944
  source_node_selection_default = SourceNodeSelection;
15879
15945
  }
15880
15946
  });
@@ -15939,13 +16005,6 @@ function info_default({ defineComponent, Av, validation: { Z, Port, SourceName,
15939
16005
  },
15940
16006
  configForm: {
15941
16007
  form: {
15942
- notes: {
15943
- help: "Notes about this component",
15944
- hint: {
15945
- type: "text",
15946
- optional: true
15947
- }
15948
- },
15949
16008
  port: { help: "The port this RTMP input will listen on", hint: { type: "numeric", validation: Port, defaultValue: defaultPort, global: unique("port") } },
15950
16009
  ssl: { help: "Optional: SSL", hint: { type: "boolean", optional: true } },
15951
16010
  appName: { help: "Name of the app", hint: { type: "text", validation: Z.string().min(1), defaultValue: "norsk" } },
@@ -15957,6 +16016,13 @@ function info_default({ defineComponent, Av, validation: { Z, Port, SourceName,
15957
16016
  validation: Z.array(SourceName),
15958
16017
  global: unique("sourceName")
15959
16018
  }
16019
+ },
16020
+ notes: {
16021
+ help: "Additional notes about this component",
16022
+ hint: {
16023
+ type: "text",
16024
+ optional: true
16025
+ }
15960
16026
  }
15961
16027
  }
15962
16028
  }
@@ -15987,13 +16053,6 @@ function info_default2({ defineComponent, Audio }) {
15987
16053
  },
15988
16054
  configForm: {
15989
16055
  form: {
15990
- notes: {
15991
- help: "Notes about this component",
15992
- hint: {
15993
- type: "text",
15994
- optional: true
15995
- }
15996
- },
15997
16056
  sampleRate: {
15998
16057
  help: "Samplerate in Hz of the generated audio",
15999
16058
  hint: {
@@ -16015,6 +16074,13 @@ function info_default2({ defineComponent, Audio }) {
16015
16074
  ],
16016
16075
  defaultValue: "stereo"
16017
16076
  }
16077
+ },
16078
+ notes: {
16079
+ help: "Additional notes about this component",
16080
+ hint: {
16081
+ type: "text",
16082
+ optional: true
16083
+ }
16018
16084
  }
16019
16085
  }
16020
16086
  }
@@ -16094,13 +16160,6 @@ function info_default3({ defineComponent, Av, validation }) {
16094
16160
  },
16095
16161
  configForm: {
16096
16162
  form: {
16097
- notes: {
16098
- help: "Notes about this component",
16099
- hint: {
16100
- type: "text",
16101
- optional: true
16102
- }
16103
- },
16104
16163
  port: { help: "The port this SRT input will connect to", hint: { type: "numeric", validation: Port, defaultValue: 5001 } },
16105
16164
  host: { help: "The IP address/hostname this SRT input will connect to", hint: { type: "text", validation: Hostname, defaultValue: "0.0.0.0" } },
16106
16165
  sourceName: { help: "Source name to identify this by", hint: { type: "text", validation: SourceName, defaultValue: "camera1" } },
@@ -16113,6 +16172,13 @@ function info_default3({ defineComponent, Av, validation }) {
16113
16172
  view: SocketConfiguration2,
16114
16173
  form: srt_socket_options_default(validation)
16115
16174
  }
16175
+ },
16176
+ notes: {
16177
+ help: "Additional notes about this component",
16178
+ hint: {
16179
+ type: "text",
16180
+ optional: true
16181
+ }
16116
16182
  }
16117
16183
  }
16118
16184
  }
@@ -16184,13 +16250,6 @@ function info_default4({ defineComponent, Av, validation }) {
16184
16250
  },
16185
16251
  configForm: {
16186
16252
  form: {
16187
- notes: {
16188
- help: "Notes about this component",
16189
- hint: {
16190
- type: "text",
16191
- optional: true
16192
- }
16193
- },
16194
16253
  port: {
16195
16254
  help: "The port this SRT input will listen on",
16196
16255
  hint: {
@@ -16246,6 +16305,13 @@ function info_default4({ defineComponent, Av, validation }) {
16246
16305
  validation: Z.array(SourceName),
16247
16306
  global: unique("sourceName")
16248
16307
  }
16308
+ },
16309
+ notes: {
16310
+ help: "Additional notes about this component",
16311
+ hint: {
16312
+ type: "text",
16313
+ optional: true
16314
+ }
16249
16315
  }
16250
16316
  }
16251
16317
  }
@@ -16277,13 +16343,13 @@ function info_default5({ defineComponent, Av, validation: { Z, Port, Hostname, S
16277
16343
  },
16278
16344
  configForm: {
16279
16345
  form: {
16280
- notes: { help: "Notes about this component", hint: { type: "text", optional: true } },
16281
16346
  port: { help: "The receiving port", hint: { type: "numeric", validation: Port, defaultValue: 5001, global: unique("port") } },
16282
16347
  host: { help: "The receiving IP address/hostname", hint: { type: "text", validation: Hostname, defaultValue: "127.0.0.1" } },
16283
16348
  sourceName: { help: "Source name to identify this by", hint: { type: "text", validation: SourceName, defaultValue: "udp-ts", global: unique("sourceName") } },
16284
16349
  interface: { help: "Optional interface to bind to", hint: { type: "text", optional: true, validation: Z.union([Z.string().min(2).max(32), Z.string().length(0)]).optional() } },
16285
16350
  timeout: { help: "Timeout in milliseconds before determining the input is closed", hint: { type: "numeric", validation: Z.number().refine((value) => value > 0 && value < 6e5, "Timeout must be less than 10 minutes"), defaultValue: 1e3 } },
16286
- rtpDecapsulate: { help: "Whether to expect the input TS to be encapsulated in RTP via RFC 2250 (default: false)", hint: { type: "boolean" } }
16351
+ rtpDecapsulate: { help: "Whether to expect the input TS to be encapsulated in RTP via RFC 2250 (default: false)", hint: { type: "boolean" } },
16352
+ notes: { help: "Additional notes about this component", hint: { type: "text", optional: true } }
16287
16353
  }
16288
16354
  }
16289
16355
  });
@@ -16312,13 +16378,6 @@ function info_default6({ defineComponent, Video, validation: { SourceName, uniqu
16312
16378
  },
16313
16379
  configForm: {
16314
16380
  form: {
16315
- notes: {
16316
- help: "Notes about this component",
16317
- hint: {
16318
- type: "text",
16319
- optional: true
16320
- }
16321
- },
16322
16381
  resolution: {
16323
16382
  help: "The resolution of the test card stream",
16324
16383
  hint: { type: "select", options: Resolutions, defaultValue: { width: 1280, height: 720 } }
@@ -16342,6 +16401,10 @@ function info_default6({ defineComponent, Video, validation: { SourceName, uniqu
16342
16401
  { value: "smpte100", display: "SMPTE100" }
16343
16402
  ]
16344
16403
  }
16404
+ },
16405
+ notes: {
16406
+ help: "Additional notes about this component",
16407
+ hint: { type: "text", optional: true }
16345
16408
  }
16346
16409
  }
16347
16410
  }
@@ -16353,6 +16416,7 @@ var import_config = __toESM(require_config());
16353
16416
  var import_react5 = __toESM(require_react());
16354
16417
  function info_default7(R) {
16355
16418
  const { defineComponent, All, validation: { Z, Hostname } } = R;
16419
+ const SummaryView11 = import_react5.default.lazy(async () => Promise.resolve().then(() => (init_summary_view3(), summary_view_exports3)));
16356
16420
  const FullscreenView2 = import_react5.default.lazy(async () => Promise.resolve().then(() => (init_fullscreen(), fullscreen_exports)));
16357
16421
  const SegmentConfiguration2 = import_react5.default.lazy(async () => {
16358
16422
  const views = await Promise.resolve().then(() => (init_form_views(), form_views_exports));
@@ -16435,7 +16499,7 @@ function info_default7(R) {
16435
16499
  }
16436
16500
  return { ...state };
16437
16501
  },
16438
- //summary: SummaryView,
16502
+ summary: SummaryView11,
16439
16503
  fullscreen: FullscreenView2
16440
16504
  },
16441
16505
  configForm: {
@@ -16452,13 +16516,6 @@ function info_default7(R) {
16452
16516
  validation: Z.string().min(5).max(15)
16453
16517
  }
16454
16518
  },
16455
- notes: {
16456
- help: "Notes about this component",
16457
- hint: {
16458
- type: "text",
16459
- optional: true
16460
- }
16461
- },
16462
16519
  sessionId: {
16463
16520
  help: "Generate a unique session id per run to avoid cache collisions",
16464
16521
  hint: {
@@ -16579,6 +16636,13 @@ function info_default7(R) {
16579
16636
  }
16580
16637
  ]
16581
16638
  }
16639
+ },
16640
+ notes: {
16641
+ help: "Additional notes about this component",
16642
+ hint: {
16643
+ type: "text",
16644
+ optional: true
16645
+ }
16582
16646
  }
16583
16647
  }
16584
16648
  }
@@ -16652,16 +16716,13 @@ function info_default8(R) {
16652
16716
  hardware: (0, import_config2.HardwareSelection)()
16653
16717
  },
16654
16718
  form: {
16655
- notes: {
16656
- help: "Notes about this component",
16657
- hint: {
16658
- type: "text",
16659
- optional: true
16660
- }
16661
- },
16662
16719
  bufferDelayMs: { help: "How many milliseconds in the jitter buffer", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 500 } },
16663
16720
  skipTranscode: { help: "Skip transcoding for WebRTC-ready streams", hint: { type: "boolean", defaultValue: false } },
16664
- showPreview: { help: "Show video preview", hint: { type: "boolean", defaultValue: true } }
16721
+ showPreview: { help: "Show video preview", hint: { type: "boolean", defaultValue: true } },
16722
+ notes: {
16723
+ help: "Additional notes about this component",
16724
+ hint: { type: "text", optional: true }
16725
+ }
16665
16726
  }
16666
16727
  }
16667
16728
  });
@@ -16716,11 +16777,14 @@ function info_default9({ defineComponent, Av, validation: { Z, JitterBuffer } })
16716
16777
  },
16717
16778
  configForm: {
16718
16779
  form: {
16719
- notes: { help: "Notes about this component", hint: { type: "text", optional: true } },
16720
16780
  url: { help: "The URL of the remote RTMP server to connect to, including the full stream path and credentials", hint: { type: "text", validation: Z.string().min(5) } },
16721
16781
  bufferDelayMs: { help: "How many milliseconds in the jitter buffer", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 500 } },
16722
16782
  avDelayMs: { help: "How many milliseconds to delay A/V to account for subtitles", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 50 } },
16723
- retryConnectionTimeout: { help: "Number of seconds to wait until a retry is attempted to the RTMP server", hint: { type: "numeric", validation: Z.number().min(1).max(10), defaultValue: 5 } }
16783
+ retryConnectionTimeout: { help: "Number of seconds to wait until a retry is attempted to the RTMP server", hint: { type: "numeric", validation: Z.number().min(1).max(10), defaultValue: 5 } },
16784
+ notes: {
16785
+ help: "Additional notes about this component",
16786
+ hint: { type: "text", optional: true }
16787
+ }
16724
16788
  }
16725
16789
  }
16726
16790
  });
@@ -16781,7 +16845,6 @@ function info_default10(registration) {
16781
16845
  },
16782
16846
  configForm: {
16783
16847
  form: {
16784
- notes: { help: "Notes about this component", hint: { type: "text", optional: true } },
16785
16848
  port: {
16786
16849
  help: "The port this SRT output will connect to or listen on",
16787
16850
  hint: {
@@ -16824,6 +16887,10 @@ function info_default10(registration) {
16824
16887
  view: SocketConfiguration2,
16825
16888
  form: srt_socket_options_default(validation)
16826
16889
  }
16890
+ },
16891
+ notes: {
16892
+ help: "Additional notes about this component",
16893
+ hint: { type: "text", optional: true }
16827
16894
  }
16828
16895
  }
16829
16896
  }
@@ -16858,11 +16925,14 @@ function info_default12({ defineComponent, All, validation: { Port, Hostname, Ji
16858
16925
  },
16859
16926
  configForm: {
16860
16927
  form: {
16861
- notes: { help: "Notes about this component", hint: { type: "text", optional: true } },
16862
16928
  port: { help: "The port this UDP TS output will send to", hint: { type: "numeric", validation: Port, defaultValue: 8001 } },
16863
16929
  destinationHost: { help: "The IP address/Hostname this UDP TS output will send to", hint: { type: "text", validation: Hostname, defaultValue: "127.0.0.1" } },
16864
16930
  bufferDelayMs: { help: "How many milliseconds in the jitter buffer", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 500 } },
16865
- interface: { help: "Which interface to bind to for publishing", hint: { type: "text", validation: Z.union([Z.string().length(0), Iface]), defaultValue: "any" } }
16931
+ interface: { help: "Which interface to bind to for publishing", hint: { type: "text", validation: Z.union([Z.string().length(0), Iface]), defaultValue: "any" } },
16932
+ notes: {
16933
+ help: "Additional notes about this component",
16934
+ hint: { type: "text", optional: true }
16935
+ }
16866
16936
  }
16867
16937
  }
16868
16938
  });
@@ -16871,6 +16941,7 @@ function info_default12({ defineComponent, All, validation: { Port, Hostname, Ji
16871
16941
  // build/output.whep/info.js
16872
16942
  var import_config3 = __toESM(require_config());
16873
16943
  var import_react12 = __toESM(require_react());
16944
+ var SummaryView7 = import_react12.default.lazy(async () => Promise.resolve().then(() => (init_summary_view4(), summary_view_exports4)));
16874
16945
  function info_default13(R) {
16875
16946
  const { defineComponent, Av, validation: { JitterBuffer } } = R;
16876
16947
  const InlineView13 = import_react12.default.lazy(async () => Promise.resolve().then(() => (init_inline_view6(), inline_view_exports6)));
@@ -16895,28 +16966,38 @@ function info_default13(R) {
16895
16966
  },
16896
16967
  css: ["styles.css"],
16897
16968
  runtime: {
16898
- initialState: () => ({}),
16969
+ initialState: () => ({ enabled: true }),
16899
16970
  handleEvent(ev, state) {
16900
16971
  const evType = ev.type;
16901
16972
  switch (evType) {
16902
16973
  case "url-published":
16903
16974
  state.url = ev.url;
16904
16975
  break;
16976
+ case "output-enabled":
16977
+ state.enabled = true;
16978
+ break;
16979
+ case "output-disabled":
16980
+ state.enabled = false;
16981
+ break;
16905
16982
  default:
16906
16983
  assertUnreachable8(evType);
16907
16984
  }
16908
16985
  return { ...state };
16909
16986
  },
16910
- inline: InlineView13
16987
+ inline: InlineView13,
16988
+ summary: SummaryView7
16911
16989
  },
16912
16990
  configForm: {
16913
16991
  global: {
16914
16992
  iceServers: (0, import_config3.GlobalIceServers)(R)
16915
16993
  },
16916
16994
  form: {
16917
- notes: { help: "Notes about this component", hint: { type: "text", optional: true } },
16918
16995
  bufferDelayMs: { help: "How many milliseconds in the jitter buffer", hint: { type: "numeric", validation: JitterBuffer, defaultValue: 500 } },
16919
- showPreview: { help: "Show video preview", hint: { type: "boolean", defaultValue: true } }
16996
+ showPreview: { help: "Show video preview", hint: { type: "boolean", defaultValue: true } },
16997
+ notes: {
16998
+ help: "Additional notes about this component",
16999
+ hint: { type: "text", optional: true }
17000
+ }
16920
17001
  }
16921
17002
  }
16922
17003
  });
@@ -16928,7 +17009,7 @@ function assertUnreachable8(_) {
16928
17009
  // build/processor.browserOverlay/info.js
16929
17010
  var import_config4 = __toESM(require_config());
16930
17011
  var import_react14 = __toESM(require_react());
16931
- var SummaryView6 = import_react14.default.lazy(async () => Promise.resolve().then(() => (init_summary_view3(), summary_view_exports3)));
17012
+ var SummaryView9 = import_react14.default.lazy(async () => Promise.resolve().then(() => (init_summary_view5(), summary_view_exports5)));
16932
17013
  var InlineView10 = import_react14.default.lazy(async () => Promise.resolve().then(() => (init_inline_view7(), inline_view_exports7)));
16933
17014
  function info_default14({ defineComponent, Video, validation: { Z } }) {
16934
17015
  return defineComponent({
@@ -16956,7 +17037,7 @@ function info_default14({ defineComponent, Video, validation: { Z } }) {
16956
17037
  };
16957
17038
  },
16958
17039
  runtime: {
16959
- summary: SummaryView6,
17040
+ summary: SummaryView9,
16960
17041
  inline: InlineView10,
16961
17042
  initialState: () => ({
16962
17043
  currentUrl: "",
@@ -17463,7 +17544,7 @@ var import_config6 = __toESM(require_config());
17463
17544
  var import_react20 = __toESM(require_react());
17464
17545
  function info_default17({ defineComponent, Video }) {
17465
17546
  const GraphicSelection2 = import_react20.default.lazy(async () => Promise.resolve().then(() => (init_image_selection(), image_selection_exports)));
17466
- const SummaryView8 = import_react20.default.lazy(async () => Promise.resolve().then(() => (init_summary_view4(), summary_view_exports4)));
17547
+ const SummaryView11 = import_react20.default.lazy(async () => Promise.resolve().then(() => (init_summary_view6(), summary_view_exports6)));
17467
17548
  return defineComponent({
17468
17549
  identifier: "processor.onscreenGraphic",
17469
17550
  category: "processor",
@@ -17489,7 +17570,7 @@ function info_default17({ defineComponent, Video }) {
17489
17570
  };
17490
17571
  },
17491
17572
  runtime: {
17492
- summary: SummaryView8,
17573
+ summary: SummaryView11,
17493
17574
  initialState: () => ({}),
17494
17575
  handleEvent: (ev, state) => {
17495
17576
  const evType = ev.type;