@twick/studio 0.14.9 → 0.14.11

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.
@@ -1,3 +1,3 @@
1
1
  import { AudioPanelProps } from '../../types/media-panel';
2
2
 
3
- export declare const AudioPanel: ({ items, onItemSelect, onFileUpload, acceptFileTypes, onUrlAdd, }: AudioPanelProps) => import("react/jsx-runtime").JSX.Element;
3
+ export declare const AudioPanel: ({ items, onItemSelect, onUrlAdd, }: AudioPanelProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,3 @@
1
1
  import { ImagePanelProps } from '../../types/media-panel';
2
2
 
3
- export declare function ImagePanel({ items, onItemSelect, onFileUpload, acceptFileTypes, onUrlAdd, }: ImagePanelProps): import("react/jsx-runtime").JSX.Element;
3
+ export declare function ImagePanel({ items, onItemSelect, onUrlAdd, }: ImagePanelProps): import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,3 @@
1
1
  import { VideoPanelProps } from '../../types/media-panel';
2
2
 
3
- export declare function VideoPanel({ items, onItemSelect, onFileUpload, acceptFileTypes, onUrlAdd, }: VideoPanelProps): import("react/jsx-runtime").JSX.Element;
3
+ export declare function VideoPanel({ items, onItemSelect, onUrlAdd, }: VideoPanelProps): import("react/jsx-runtime").JSX.Element;
@@ -1,3 +1,4 @@
1
1
  import { BrowserMediaManager } from '@twick/video-editor';
2
2
 
3
3
  export declare const getMediaManager: () => BrowserMediaManager;
4
+ export declare const initializeDefaultVideos: () => Promise<void>;
package/dist/index.js CHANGED
@@ -590,65 +590,6 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
590
590
  updateElement
591
591
  };
592
592
  };
593
- const FileInput = ({
594
- acceptFileTypes,
595
- onFileLoad,
596
- buttonText,
597
- id,
598
- className,
599
- icon
600
- }) => {
601
- const onFileChange = (e) => {
602
- var _a;
603
- const file = (_a = e.target.files) == null ? void 0 : _a[0];
604
- if (file) {
605
- const reader = new FileReader();
606
- reader.onload = (event) => {
607
- var _a2;
608
- try {
609
- onFileLoad({
610
- content: file.type === "application/json" ? (_a2 = event.target) == null ? void 0 : _a2.result : void 0,
611
- type: file.type,
612
- name: file.name,
613
- file,
614
- blobUrl: URL.createObjectURL(file)
615
- });
616
- } catch (error) {
617
- console.error("Error parsing file:", error);
618
- }
619
- };
620
- console.log("file", file);
621
- if (file.type === "application/json") {
622
- reader.readAsText(file);
623
- } else {
624
- reader.readAsDataURL(file);
625
- }
626
- }
627
- };
628
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "file-input-container", children: [
629
- /* @__PURE__ */ jsxRuntime.jsx(
630
- "input",
631
- {
632
- type: "file",
633
- accept: acceptFileTypes.join(","),
634
- className: "file-input-hidden",
635
- id,
636
- onChange: onFileChange
637
- }
638
- ),
639
- /* @__PURE__ */ jsxRuntime.jsxs(
640
- "label",
641
- {
642
- htmlFor: id,
643
- className: className || "btn-primary file-input-label",
644
- children: [
645
- icon || /* @__PURE__ */ jsxRuntime.jsx(Upload, { className: "icon-sm" }),
646
- buttonText ?? "Upload"
647
- ]
648
- }
649
- )
650
- ] });
651
- };
652
593
  const _MediaManagerSingleton = class _MediaManagerSingleton {
653
594
  constructor() {
654
595
  }
@@ -658,10 +599,173 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
658
599
  }
659
600
  return _MediaManagerSingleton.instance;
660
601
  }
602
+ static async initializeDefaults() {
603
+ if (_MediaManagerSingleton.isInitialized) {
604
+ return;
605
+ }
606
+ if (_MediaManagerSingleton.initializationPromise) {
607
+ await _MediaManagerSingleton.initializationPromise;
608
+ return;
609
+ }
610
+ let resolvePromise;
611
+ let rejectPromise;
612
+ _MediaManagerSingleton.initializationPromise = new Promise((resolve, reject) => {
613
+ resolvePromise = resolve;
614
+ rejectPromise = reject;
615
+ });
616
+ (async () => {
617
+ try {
618
+ await _MediaManagerSingleton.doInitializeDefaults();
619
+ _MediaManagerSingleton.isInitialized = true;
620
+ resolvePromise();
621
+ } catch (error) {
622
+ _MediaManagerSingleton.initializationPromise = null;
623
+ console.error("Error initializing default media:", error);
624
+ rejectPromise(error);
625
+ }
626
+ })();
627
+ return _MediaManagerSingleton.initializationPromise;
628
+ }
629
+ static async doInitializeDefaults() {
630
+ const manager = _MediaManagerSingleton.getInstance();
631
+ const defaultVideos = [
632
+ {
633
+ name: "Mountain Road",
634
+ url: "https://videos.pexels.com/video-files/31708803/13510402_1080_1920_30fps.mp4",
635
+ type: "video",
636
+ metadata: {
637
+ name: "Mountain Road",
638
+ source: "pexels"
639
+ }
640
+ },
641
+ {
642
+ name: "Vase",
643
+ url: "https://videos.pexels.com/video-files/4622990/4622990-uhd_1440_2560_30fps.mp4",
644
+ type: "video",
645
+ metadata: {
646
+ name: "Vase",
647
+ source: "pexels"
648
+ }
649
+ }
650
+ ];
651
+ const defaultImages = [
652
+ {
653
+ name: "Mountain Road",
654
+ url: "https://images.pexels.com/photos/1955134/pexels-photo-1955134.jpeg",
655
+ type: "image",
656
+ metadata: {
657
+ name: "Mountain Road",
658
+ source: "pexels"
659
+ }
660
+ },
661
+ {
662
+ name: "Waterfall",
663
+ url: "https://images.pexels.com/photos/358457/pexels-photo-358457.jpeg",
664
+ type: "image",
665
+ metadata: {
666
+ name: "Waterfall",
667
+ source: "pexels"
668
+ }
669
+ }
670
+ ];
671
+ const defaultAudios = [
672
+ {
673
+ name: "Audio 1",
674
+ url: "https://cdn.pixabay.com/audio/2022/03/14/audio_782eeb590e.mp3",
675
+ type: "audio",
676
+ metadata: {
677
+ name: "Audio 1",
678
+ source: "pixabay"
679
+ }
680
+ },
681
+ {
682
+ name: "Audio 2",
683
+ url: "https://cdn.pixabay.com/audio/2025/01/24/audio_24048c78b6.mp3",
684
+ type: "audio",
685
+ metadata: {
686
+ name: "Audio 2",
687
+ source: "pixabay"
688
+ }
689
+ }
690
+ ];
691
+ try {
692
+ const existingVideos = await manager.search({
693
+ type: "video",
694
+ query: ""
695
+ });
696
+ const existingVideoUrls = new Set(existingVideos.map((v) => v.url));
697
+ const videosToAdd = defaultVideos.filter(
698
+ (video) => !existingVideoUrls.has(video.url)
699
+ );
700
+ if (videosToAdd.length > 0) {
701
+ const finalCheck = await manager.search({
702
+ type: "video",
703
+ query: ""
704
+ });
705
+ const finalVideoUrls = new Set(finalCheck.map((v) => v.url));
706
+ const finalVideosToAdd = videosToAdd.filter(
707
+ (video) => !finalVideoUrls.has(video.url)
708
+ );
709
+ if (finalVideosToAdd.length > 0) {
710
+ await manager.addItems(finalVideosToAdd);
711
+ console.log(`Added ${finalVideosToAdd.length} default video(s) to media library`);
712
+ }
713
+ }
714
+ const existingImages = await manager.search({
715
+ type: "image",
716
+ query: ""
717
+ });
718
+ const existingImageUrls = new Set(existingImages.map((img) => img.url));
719
+ const imagesToAdd = defaultImages.filter(
720
+ (image) => !existingImageUrls.has(image.url)
721
+ );
722
+ if (imagesToAdd.length > 0) {
723
+ const finalCheck = await manager.search({
724
+ type: "image",
725
+ query: ""
726
+ });
727
+ const finalImageUrls = new Set(finalCheck.map((img) => img.url));
728
+ const finalImagesToAdd = imagesToAdd.filter(
729
+ (image) => !finalImageUrls.has(image.url)
730
+ );
731
+ if (finalImagesToAdd.length > 0) {
732
+ await manager.addItems(finalImagesToAdd);
733
+ console.log(`Added ${finalImagesToAdd.length} default image(s) to media library`);
734
+ }
735
+ }
736
+ const existingAudios = await manager.search({
737
+ type: "audio",
738
+ query: ""
739
+ });
740
+ const existingAudioUrls = new Set(existingAudios.map((a) => a.url));
741
+ const audiosToAdd = defaultAudios.filter(
742
+ (audio) => !existingAudioUrls.has(audio.url)
743
+ );
744
+ if (audiosToAdd.length > 0) {
745
+ const finalCheck = await manager.search({
746
+ type: "audio",
747
+ query: ""
748
+ });
749
+ const finalAudioUrls = new Set(finalCheck.map((a) => a.url));
750
+ const finalAudiosToAdd = audiosToAdd.filter(
751
+ (audio) => !finalAudioUrls.has(audio.url)
752
+ );
753
+ if (finalAudiosToAdd.length > 0) {
754
+ await manager.addItems(finalAudiosToAdd);
755
+ console.log(`Added ${finalAudiosToAdd.length} default audio file(s) to media library`);
756
+ }
757
+ }
758
+ } catch (error) {
759
+ throw error;
760
+ }
761
+ }
661
762
  };
662
763
  __publicField(_MediaManagerSingleton, "instance", null);
764
+ __publicField(_MediaManagerSingleton, "initializationPromise", null);
765
+ __publicField(_MediaManagerSingleton, "isInitialized", false);
663
766
  let MediaManagerSingleton = _MediaManagerSingleton;
664
767
  const getMediaManager = () => MediaManagerSingleton.getInstance();
768
+ const initializeDefaultVideos = () => MediaManagerSingleton.initializeDefaults();
665
769
  const EXTENSIONS = {
666
770
  video: ["mp4", "webm", "ogg", "mov", "mkv", "m3u8"],
667
771
  audio: ["mp3", "wav", "ogg", "m4a", "aac", "flac"],
@@ -782,9 +886,13 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
782
886
  }
783
887
  };
784
888
  react.useEffect(() => {
785
- loadItems("video", "");
786
- loadItems("audio", "");
787
- loadItems("image", "");
889
+ const initialize = async () => {
890
+ await initializeDefaultVideos();
891
+ loadItems("video", "");
892
+ loadItems("audio", "");
893
+ loadItems("image", "");
894
+ };
895
+ initialize();
788
896
  }, []);
789
897
  const setSearchQuery = (type, query) => {
790
898
  const [state, setState] = getStateAndSetter(type);
@@ -946,25 +1054,12 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
946
1054
  const AudioPanel = ({
947
1055
  items,
948
1056
  onItemSelect,
949
- onFileUpload,
950
- acceptFileTypes,
951
1057
  onUrlAdd
952
1058
  }) => {
953
1059
  const { playingAudio, togglePlayPause } = useAudioPreview();
954
1060
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "panel-container", children: [
955
1061
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "panel-title", children: "Audio Library" }),
956
1062
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "panel-section", children: /* @__PURE__ */ jsxRuntime.jsx(UrlInput, { type: "audio", onSubmit: onUrlAdd }) }),
957
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex panel-section", children: /* @__PURE__ */ jsxRuntime.jsx(
958
- FileInput,
959
- {
960
- id: "audio-upload",
961
- acceptFileTypes,
962
- onFileLoad: onFileUpload,
963
- buttonText: "Import media",
964
- className: "btn-primary w-full",
965
- icon: /* @__PURE__ */ jsxRuntime.jsx(Upload, { className: "icon-sm" })
966
- }
967
- ) }),
968
1063
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "media-content", children: [
969
1064
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "media-list", children: (items || []).map((item) => {
970
1065
  var _a, _b;
@@ -1065,24 +1160,11 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
1065
1160
  function ImagePanel({
1066
1161
  items,
1067
1162
  onItemSelect,
1068
- onFileUpload,
1069
- acceptFileTypes,
1070
1163
  onUrlAdd
1071
1164
  }) {
1072
1165
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "panel-container", children: [
1073
1166
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "panel-title", children: "Image Library" }),
1074
1167
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "panel-section", children: /* @__PURE__ */ jsxRuntime.jsx(UrlInput, { type: "image", onSubmit: onUrlAdd }) }),
1075
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex panel-section", children: /* @__PURE__ */ jsxRuntime.jsx(
1076
- FileInput,
1077
- {
1078
- id: "image-upload",
1079
- acceptFileTypes,
1080
- onFileLoad: onFileUpload,
1081
- buttonText: "Import media",
1082
- className: "btn-primary w-full",
1083
- icon: /* @__PURE__ */ jsxRuntime.jsx(Upload, { className: "icon-sm" })
1084
- }
1085
- ) }),
1086
1168
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "media-content", children: [
1087
1169
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "media-grid", children: (items || []).map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
1088
1170
  "div",
@@ -1206,25 +1288,12 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
1206
1288
  function VideoPanel({
1207
1289
  items,
1208
1290
  onItemSelect,
1209
- onFileUpload,
1210
- acceptFileTypes,
1211
1291
  onUrlAdd
1212
1292
  }) {
1213
1293
  const { playingVideo, togglePlayPause } = useVideoPreview();
1214
1294
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "panel-container", children: [
1215
1295
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "panel-title", children: "Video Library" }),
1216
1296
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex panel-section", children: /* @__PURE__ */ jsxRuntime.jsx(UrlInput, { type: "video", onSubmit: onUrlAdd }) }),
1217
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex panel-section", children: /* @__PURE__ */ jsxRuntime.jsx(
1218
- FileInput,
1219
- {
1220
- id: "video-upload",
1221
- acceptFileTypes,
1222
- onFileLoad: onFileUpload,
1223
- buttonText: "Import media",
1224
- className: "btn-primary w-full",
1225
- icon: /* @__PURE__ */ jsxRuntime.jsx(Upload, { className: "icon-sm" })
1226
- }
1227
- ) }),
1228
1297
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "media-content", children: [
1229
1298
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "media-grid", children: (items || []).map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
1230
1299
  "div",