@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.
- package/dist/components/panel/audio-panel.d.ts +1 -1
- package/dist/components/panel/image-panel.d.ts +1 -1
- package/dist/components/panel/video-panel.d.ts +1 -1
- package/dist/components/shared/media-manager.d.ts +1 -0
- package/dist/index.js +170 -101
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +170 -101
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { AudioPanelProps } from '../../types/media-panel';
|
|
2
2
|
|
|
3
|
-
export declare const AudioPanel: ({ items, onItemSelect,
|
|
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,
|
|
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,
|
|
3
|
+
export declare function VideoPanel({ items, onItemSelect, onUrlAdd, }: VideoPanelProps): import("react/jsx-runtime").JSX.Element;
|
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
|
-
|
|
786
|
-
|
|
787
|
-
|
|
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",
|