@geekapps/silo-elements-nextjs 0.3.7 → 0.3.9
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/MediaUploader.js +149 -4
- package/dist/MediaUploader.js.map +1 -1
- package/dist/VideoPlayer.js +10 -2
- package/dist/VideoPlayer.js.map +1 -1
- package/dist/VideoUploader.js +147 -2
- package/dist/VideoUploader.js.map +1 -1
- package/dist/index.js +159 -6
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +48 -48
- package/styles.css +1 -1
package/dist/MediaUploader.js
CHANGED
|
@@ -158,7 +158,7 @@ var FORMATS = [
|
|
|
158
158
|
{ value: "png", label: "PNG", hint: "Sem perda" }
|
|
159
159
|
];
|
|
160
160
|
function ImageOptions({ value, onChange, style }) {
|
|
161
|
-
const
|
|
161
|
+
const fmt2 = value.format ?? "webp";
|
|
162
162
|
const optimize = value.optimize ?? true;
|
|
163
163
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2.5", style, children: [
|
|
164
164
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -169,7 +169,7 @@ function ImageOptions({ value, onChange, style }) {
|
|
|
169
169
|
type: "button",
|
|
170
170
|
onClick: () => onChange({ ...value, format: f.value }),
|
|
171
171
|
title: f.hint,
|
|
172
|
-
style:
|
|
172
|
+
style: fmt2 === f.value ? { border: "1px solid #6366f1", background: "#6366f1", color: "#fff", padding: "4px 12px", borderRadius: 6, fontSize: 12, fontWeight: 600, cursor: "pointer" } : { border: "1px solid rgba(255,255,255,0.2)", background: "rgba(255,255,255,0.06)", color: "rgba(255,255,255,0.8)", padding: "4px 12px", borderRadius: 6, fontSize: 12, fontWeight: 600, cursor: "pointer" },
|
|
173
173
|
children: f.label
|
|
174
174
|
},
|
|
175
175
|
f.value
|
|
@@ -693,6 +693,128 @@ function VideoOptions({ value, onChange, style }) {
|
|
|
693
693
|
)
|
|
694
694
|
] });
|
|
695
695
|
}
|
|
696
|
+
var CODEC_MESSAGES = {
|
|
697
|
+
AV1: { title: "AV1 n\xE3o \xE9 suportado como entrada", detail: "O pipeline de transcodifica\xE7\xE3o n\xE3o aceita arquivos AV1. Converta para H.264 ou H.265 antes de enviar." },
|
|
698
|
+
VP9: { title: "VP9 n\xE3o \xE9 suportado como entrada", detail: "Arquivos WebM/VP9 n\xE3o s\xE3o aceitos. Converta para H.264 ou H.265 antes de enviar." },
|
|
699
|
+
VP8: { title: "VP8 n\xE3o \xE9 suportado como entrada", detail: "Arquivos WebM/VP8 n\xE3o s\xE3o aceitos. Converta para H.264 antes de enviar." },
|
|
700
|
+
"MPEG-1 Video": { title: "MPEG-1 n\xE3o \xE9 suportado", detail: "Formato muito antigo. Converta para H.264 antes de enviar." },
|
|
701
|
+
"MPEG-2 Video": { title: "MPEG-2 n\xE3o \xE9 suportado", detail: "Converta para H.264 antes de enviar." }
|
|
702
|
+
};
|
|
703
|
+
var CONTAINER_MESSAGES = {
|
|
704
|
+
FLV: { title: "Formato FLV n\xE3o suportado", detail: "Arquivos Flash Video n\xE3o s\xE3o aceitos. Converta para MP4 (H.264) antes de enviar." },
|
|
705
|
+
"Flash Video": { title: "Formato FLV n\xE3o suportado", detail: "Arquivos Flash Video n\xE3o s\xE3o aceitos. Converta para MP4 (H.264) antes de enviar." },
|
|
706
|
+
RealMedia: { title: "Formato RealMedia n\xE3o suportado", detail: "Converta para MP4 (H.264) antes de enviar." },
|
|
707
|
+
ASF: { title: "Formato ASF/WMV n\xE3o suportado", detail: "Converta para MP4 (H.264) antes de enviar." }
|
|
708
|
+
};
|
|
709
|
+
function issueMessage(issue) {
|
|
710
|
+
if (issue.code === "unsupported_codec") {
|
|
711
|
+
return CODEC_MESSAGES[issue.codec] ?? { title: `Codec ${issue.codec} n\xE3o suportado`, detail: "Converta para H.264 ou H.265 antes de enviar." };
|
|
712
|
+
}
|
|
713
|
+
const key = Object.keys(CONTAINER_MESSAGES).find((k) => issue.container.includes(k));
|
|
714
|
+
return (key ? CONTAINER_MESSAGES[key] : null) ?? { title: `Container ${issue.container} n\xE3o suportado`, detail: "Converta para MP4 (H.264) antes de enviar." };
|
|
715
|
+
}
|
|
716
|
+
function fmt(n, unit) {
|
|
717
|
+
return `${n.toLocaleString("pt-BR")}${unit}`;
|
|
718
|
+
}
|
|
719
|
+
function fmtDuration(secs) {
|
|
720
|
+
const h = Math.floor(secs / 3600);
|
|
721
|
+
const m = Math.floor(secs % 3600 / 60);
|
|
722
|
+
const s = Math.floor(secs % 60);
|
|
723
|
+
if (h > 0) return `${h}h ${m}m ${s}s`;
|
|
724
|
+
if (m > 0) return `${m}m ${s}s`;
|
|
725
|
+
return `${s}s`;
|
|
726
|
+
}
|
|
727
|
+
function VideoCompatAlert({ info, issues, analyzing }) {
|
|
728
|
+
if (analyzing) {
|
|
729
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, padding: "10px 14px", background: "rgba(99,102,241,0.06)", border: "1px solid rgba(99,102,241,0.18)", borderRadius: 10 }, children: [
|
|
730
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14 }, children: "\u{1F50D}" }),
|
|
731
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 12, color: "rgba(165,180,252,0.9)" }, children: "Analisando arquivo\u2026" })
|
|
732
|
+
] });
|
|
733
|
+
}
|
|
734
|
+
const v = info.video;
|
|
735
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
736
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: 6 }, children: [
|
|
737
|
+
v && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
738
|
+
/* @__PURE__ */ jsx(Chip, { label: v.codec || "?", color: "neutral" }),
|
|
739
|
+
v.width > 0 && v.height > 0 && /* @__PURE__ */ jsx(Chip, { label: `${v.width}\xD7${v.height}`, color: "neutral" }),
|
|
740
|
+
v.duration > 0 && /* @__PURE__ */ jsx(Chip, { label: fmtDuration(v.duration), color: "neutral" }),
|
|
741
|
+
v.frameRate > 0 && /* @__PURE__ */ jsx(Chip, { label: fmt(Math.round(v.frameRate), " fps"), color: "neutral" }),
|
|
742
|
+
v.hdr && /* @__PURE__ */ jsx(Chip, { label: "HDR", color: "purple" })
|
|
743
|
+
] }),
|
|
744
|
+
info.audio && /* @__PURE__ */ jsx(Chip, { label: info.audio.codec || "sem \xE1udio", color: "neutral" }),
|
|
745
|
+
/* @__PURE__ */ jsx(Chip, { label: formatBytes(info.fileSize), color: "neutral" })
|
|
746
|
+
] }),
|
|
747
|
+
issues.map((issue, i) => {
|
|
748
|
+
const msg = issueMessage(issue);
|
|
749
|
+
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, padding: "10px 14px", background: "rgba(239,68,68,0.07)", border: "1px solid rgba(239,68,68,0.22)", borderRadius: 10 }, children: [
|
|
750
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, flexShrink: 0 }, children: "\u{1F6AB}" }),
|
|
751
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
752
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 12, fontWeight: 700, color: "#f87171", marginBottom: 2 }, children: msg.title }),
|
|
753
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 11, color: "rgba(255,255,255,0.5)", lineHeight: 1.55 }, children: msg.detail })
|
|
754
|
+
] })
|
|
755
|
+
] }, i);
|
|
756
|
+
})
|
|
757
|
+
] });
|
|
758
|
+
}
|
|
759
|
+
function Chip({ label, color }) {
|
|
760
|
+
const s = color === "purple" ? { background: "rgba(168,85,247,0.12)", border: "1px solid rgba(168,85,247,0.25)", color: "#c084fc" } : { background: "rgba(255,255,255,0.05)", border: "1px solid rgba(255,255,255,0.1)", color: "rgba(255,255,255,0.6)" };
|
|
761
|
+
return /* @__PURE__ */ jsx("span", { style: { ...s, fontSize: 11, fontWeight: 600, borderRadius: 6, padding: "2px 8px", display: "inline-block" }, children: label });
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
// src/utils/videoInfo.ts
|
|
765
|
+
var UNSUPPORTED_CODECS = ["AV1", "VP8", "VP9", "MPEG-1 Video", "MPEG-2 Video", "Theora", "RealVideo"];
|
|
766
|
+
var UNSUPPORTED_CONTAINERS = ["FLV", "Flash Video", "RealMedia", "ASF"];
|
|
767
|
+
function getCompatIssues(info) {
|
|
768
|
+
const issues = [];
|
|
769
|
+
if (info.video && UNSUPPORTED_CODECS.includes(info.video.codec)) {
|
|
770
|
+
issues.push({ code: "unsupported_codec", codec: info.video.codec });
|
|
771
|
+
}
|
|
772
|
+
if (UNSUPPORTED_CONTAINERS.some((c) => info.container.includes(c))) {
|
|
773
|
+
issues.push({ code: "unsupported_container", container: info.container });
|
|
774
|
+
}
|
|
775
|
+
return issues;
|
|
776
|
+
}
|
|
777
|
+
async function analyzeVideoFile(file) {
|
|
778
|
+
const wasmUrl = `https://cdn.jsdelivr.net/npm/mediainfo.js@0.3.7/dist/MediaInfoModule.wasm`;
|
|
779
|
+
const { default: MediaInfoFactory } = await import('mediainfo.js');
|
|
780
|
+
const mediainfo = await MediaInfoFactory({ format: "object", locateFile: () => wasmUrl });
|
|
781
|
+
const getSize = () => file.size;
|
|
782
|
+
const readChunk = (chunkSize, offset) => new Promise((resolve, reject) => {
|
|
783
|
+
const reader = new FileReader();
|
|
784
|
+
reader.onload = (e) => resolve(new Uint8Array(e.target.result));
|
|
785
|
+
reader.onerror = reject;
|
|
786
|
+
reader.readAsArrayBuffer(file.slice(offset, offset + chunkSize));
|
|
787
|
+
});
|
|
788
|
+
const result = await mediainfo.analyzeData(getSize, readChunk);
|
|
789
|
+
mediainfo.close();
|
|
790
|
+
const tracks = result.media?.track ?? [];
|
|
791
|
+
const general = tracks.find((t) => t["@type"] === "General");
|
|
792
|
+
const video = tracks.find((t) => t["@type"] === "Video");
|
|
793
|
+
const audio = tracks.find((t) => t["@type"] === "Audio");
|
|
794
|
+
const str = (v) => typeof v === "string" ? v : "";
|
|
795
|
+
const num = (v) => parseFloat(str(v)) || 0;
|
|
796
|
+
const hdrFormats = str(video?.["HDR_Format"] ?? video?.["transfer_characteristics"]);
|
|
797
|
+
const isHdr = hdrFormats.length > 0 && !hdrFormats.toLowerCase().includes("bt.709") && !hdrFormats.toLowerCase().includes("sdr");
|
|
798
|
+
return {
|
|
799
|
+
container: str(general?.["Format"]) || file.type || "Unknown",
|
|
800
|
+
fileSize: file.size,
|
|
801
|
+
video: video ? {
|
|
802
|
+
codec: str(video["Format"]),
|
|
803
|
+
width: num(video["Width"]),
|
|
804
|
+
height: num(video["Height"]),
|
|
805
|
+
duration: num(video["Duration"]) / 1e3,
|
|
806
|
+
bitrate: num(video["BitRate"]),
|
|
807
|
+
frameRate: num(video["FrameRate"]),
|
|
808
|
+
hdr: isHdr,
|
|
809
|
+
colorSpace: str(video["colour_primaries"]) || str(video["ColorSpace"])
|
|
810
|
+
} : null,
|
|
811
|
+
audio: audio ? {
|
|
812
|
+
codec: str(audio["Format"]),
|
|
813
|
+
channels: num(audio["Channels"]),
|
|
814
|
+
sampleRate: num(audio["SamplingRate"])
|
|
815
|
+
} : null
|
|
816
|
+
};
|
|
817
|
+
}
|
|
696
818
|
var DEFAULT_VIDEO_OPTS = {
|
|
697
819
|
thumbnails: true,
|
|
698
820
|
storyboard: false,
|
|
@@ -737,6 +859,9 @@ function VideoUploader({
|
|
|
737
859
|
const [preview, setPreview] = useState(null);
|
|
738
860
|
const [videoOpts, setVideoOpts] = useState(() => createInitialVideoOpts(video));
|
|
739
861
|
const [stagedFile, setStagedFile] = useState(null);
|
|
862
|
+
const [videoInfo, setVideoInfo] = useState(null);
|
|
863
|
+
const [videoIssues, setVideoIssues] = useState([]);
|
|
864
|
+
const [analyzing, setAnalyzing] = useState(false);
|
|
740
865
|
const t = resolveTheme(theme);
|
|
741
866
|
const vars = themeToVars(t);
|
|
742
867
|
const doUpload = useCallback(async (file, opts) => {
|
|
@@ -753,8 +878,19 @@ function VideoUploader({
|
|
|
753
878
|
if (!file) return;
|
|
754
879
|
if (showVideoOptions) {
|
|
755
880
|
setVideoOpts(createInitialVideoOpts(video));
|
|
881
|
+
setVideoInfo(null);
|
|
882
|
+
setVideoIssues([]);
|
|
756
883
|
setStagedFile(file);
|
|
757
884
|
if (showPreview) setPreview(URL.createObjectURL(file));
|
|
885
|
+
setAnalyzing(true);
|
|
886
|
+
try {
|
|
887
|
+
const info = await analyzeVideoFile(file);
|
|
888
|
+
setVideoInfo(info);
|
|
889
|
+
setVideoIssues(getCompatIssues(info));
|
|
890
|
+
} catch {
|
|
891
|
+
} finally {
|
|
892
|
+
setAnalyzing(false);
|
|
893
|
+
}
|
|
758
894
|
} else {
|
|
759
895
|
await doUpload(file, video ?? videoOpts);
|
|
760
896
|
}
|
|
@@ -797,7 +933,11 @@ function VideoUploader({
|
|
|
797
933
|
),
|
|
798
934
|
showVideoOptions && stagedFile && !isUploading && state.status !== "done" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
799
935
|
preview && /* @__PURE__ */ jsx("div", { className: "border border-slate-200 rounded-xl overflow-hidden bg-black", children: /* @__PURE__ */ jsx("video", { src: preview, className: "w-full max-h-[200px] block", muted: true, playsInline: true, controls: true }) }),
|
|
800
|
-
/* @__PURE__ */ jsxs("div", { className: "border border-slate-200 rounded-xl overflow-hidden", children: [
|
|
936
|
+
(analyzing || videoInfo) && /* @__PURE__ */ jsxs("div", { className: "border border-slate-200 rounded-xl overflow-hidden", children: [
|
|
937
|
+
/* @__PURE__ */ jsx("div", { className: "px-3.5 py-2 bg-slate-100 text-[12px] font-bold text-slate-500 tracking-[0.04em]", children: "\u{1F4CB} Informa\xE7\xF5es do arquivo" }),
|
|
938
|
+
/* @__PURE__ */ jsx("div", { className: "p-3.5", children: /* @__PURE__ */ jsx(VideoCompatAlert, { info: videoInfo, issues: videoIssues, analyzing }) })
|
|
939
|
+
] }),
|
|
940
|
+
videoIssues.length === 0 && /* @__PURE__ */ jsxs("div", { className: "border border-slate-200 rounded-xl overflow-hidden", children: [
|
|
801
941
|
/* @__PURE__ */ jsx("div", { className: "px-3.5 py-2 bg-slate-100 text-[12px] font-bold text-slate-500 tracking-[0.04em]", children: "\u{1F3AC} Configura\xE7\xF5es de v\xEDdeo" }),
|
|
802
942
|
/* @__PURE__ */ jsx(VideoOptions, { value: videoOpts, onChange: setVideoOpts, style: { padding: "12px 14px" } })
|
|
803
943
|
] }),
|
|
@@ -809,6 +949,8 @@ function VideoUploader({
|
|
|
809
949
|
onClick: () => {
|
|
810
950
|
setStagedFile(null);
|
|
811
951
|
setPreview(null);
|
|
952
|
+
setVideoInfo(null);
|
|
953
|
+
setVideoIssues([]);
|
|
812
954
|
setVideoOpts(createInitialVideoOpts(video));
|
|
813
955
|
},
|
|
814
956
|
children: "Cancelar"
|
|
@@ -817,10 +959,13 @@ function VideoUploader({
|
|
|
817
959
|
/* @__PURE__ */ jsx(
|
|
818
960
|
"button",
|
|
819
961
|
{
|
|
820
|
-
|
|
962
|
+
disabled: videoIssues.length > 0 || analyzing,
|
|
963
|
+
className: "flex-1 inline-flex items-center justify-center gap-1.5 text-sm font-bold py-2.5 px-4 rounded-xl border-transparent bg-indigo-500 text-white cursor-pointer hover:opacity-90 disabled:opacity-40 disabled:cursor-not-allowed",
|
|
821
964
|
onClick: () => {
|
|
822
965
|
const f = stagedFile;
|
|
823
966
|
setStagedFile(null);
|
|
967
|
+
setVideoInfo(null);
|
|
968
|
+
setVideoIssues([]);
|
|
824
969
|
void doUpload(f, videoOpts);
|
|
825
970
|
setVideoOpts(createInitialVideoOpts(video));
|
|
826
971
|
},
|