@scalemule/nextjs 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +112 -1
- package/dist/index.d.ts +112 -1
- package/dist/index.js +389 -190
- package/dist/index.mjs +181 -2
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
1
2
|
import { createContext, useState, useMemo, useEffect, useCallback, useContext, useRef } from 'react';
|
|
2
3
|
import { createMoneyClient } from '@scalemule/money';
|
|
3
4
|
export { MoneyClient, createMoneyClient } from '@scalemule/money';
|
|
4
|
-
import { jsx,
|
|
5
|
+
import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
|
|
5
6
|
|
|
6
7
|
var __defProp = Object.defineProperty;
|
|
7
8
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -8885,6 +8886,8 @@ function useMedia() {
|
|
|
8885
8886
|
setError(null);
|
|
8886
8887
|
const isPublic = options?.is_public ?? false;
|
|
8887
8888
|
const mimeType = file.type || "application/octet-stream";
|
|
8889
|
+
const policy = options?.policy ?? "safe_visible";
|
|
8890
|
+
const gateOnPipeline = policy === "safe_public" || policy === "moderated" || policy === "compliance";
|
|
8888
8891
|
const sharedOpts = {
|
|
8889
8892
|
filename: options?.filename,
|
|
8890
8893
|
metadata: options?.metadata,
|
|
@@ -8897,6 +8900,9 @@ function useMedia() {
|
|
|
8897
8900
|
if (r2.error || !r2.data) {
|
|
8898
8901
|
throw r2.error ?? { code: "upload_error", message: "Upload failed", status: 0 };
|
|
8899
8902
|
}
|
|
8903
|
+
if (gateOnPipeline) {
|
|
8904
|
+
await r2.data.optimized_url_promise;
|
|
8905
|
+
}
|
|
8900
8906
|
return {
|
|
8901
8907
|
file_id: r2.data.file_id,
|
|
8902
8908
|
photo_id: r2.data.photo_id,
|
|
@@ -8912,6 +8918,9 @@ function useMedia() {
|
|
|
8912
8918
|
if (r2.error || !r2.data) {
|
|
8913
8919
|
throw r2.error ?? { code: "upload_error", message: "Upload failed", status: 0 };
|
|
8914
8920
|
}
|
|
8921
|
+
if (gateOnPipeline) {
|
|
8922
|
+
await r2.data.hls_url_promise;
|
|
8923
|
+
}
|
|
8915
8924
|
return {
|
|
8916
8925
|
file_id: r2.data.file_id,
|
|
8917
8926
|
photo_id: null,
|
|
@@ -9029,6 +9038,176 @@ function useFileStatus(options) {
|
|
|
9029
9038
|
const isReady = status?.scan.status === "clean";
|
|
9030
9039
|
return { status, loading, error, isReady, refresh: fetchStatus };
|
|
9031
9040
|
}
|
|
9041
|
+
function ScaleMuleMedia(props) {
|
|
9042
|
+
const {
|
|
9043
|
+
fileId,
|
|
9044
|
+
mimeType,
|
|
9045
|
+
blobPreview,
|
|
9046
|
+
width,
|
|
9047
|
+
height,
|
|
9048
|
+
className,
|
|
9049
|
+
style,
|
|
9050
|
+
alt,
|
|
9051
|
+
pollIntervalMs = 2e3,
|
|
9052
|
+
renderPlaceholder,
|
|
9053
|
+
renderBlocked,
|
|
9054
|
+
renderOverride
|
|
9055
|
+
} = props;
|
|
9056
|
+
const { status, isReady } = useFileStatus({ fileId, pollIntervalMs });
|
|
9057
|
+
const isImage = mimeType.startsWith("image/");
|
|
9058
|
+
const isVideo = mimeType.startsWith("video/");
|
|
9059
|
+
const isAudio = mimeType.startsWith("audio/");
|
|
9060
|
+
const src = useMemo(() => {
|
|
9061
|
+
const scan = status?.scan.status;
|
|
9062
|
+
if (scan === "threat" || scan === "quarantined") return null;
|
|
9063
|
+
if (status && isReady) {
|
|
9064
|
+
if (isImage && status.urls.optimized) return status.urls.optimized;
|
|
9065
|
+
if (isVideo && status.urls.hls) return status.urls.hls;
|
|
9066
|
+
return status.urls.original ?? null;
|
|
9067
|
+
}
|
|
9068
|
+
if (blobPreview) return blobPreview;
|
|
9069
|
+
return null;
|
|
9070
|
+
}, [status, isReady, isImage, isVideo, blobPreview]);
|
|
9071
|
+
const renderState = useMemo(() => {
|
|
9072
|
+
const scan = status?.scan.status;
|
|
9073
|
+
if (scan === "threat" || scan === "quarantined") return "blocked";
|
|
9074
|
+
if (isReady) return "ready";
|
|
9075
|
+
if (blobPreview) return "preview";
|
|
9076
|
+
return "pending";
|
|
9077
|
+
}, [status?.scan.status, isReady, blobPreview]);
|
|
9078
|
+
const videoRef = React.useRef(null);
|
|
9079
|
+
useEffect(() => {
|
|
9080
|
+
if (!isVideo) return;
|
|
9081
|
+
if (!src) return;
|
|
9082
|
+
if (!src.endsWith(".m3u8")) return;
|
|
9083
|
+
const el = videoRef.current;
|
|
9084
|
+
if (!el) return;
|
|
9085
|
+
if (el.canPlayType("application/vnd.apple.mpegurl")) {
|
|
9086
|
+
el.src = src;
|
|
9087
|
+
return;
|
|
9088
|
+
}
|
|
9089
|
+
let cancelled = false;
|
|
9090
|
+
let hls = null;
|
|
9091
|
+
void (async () => {
|
|
9092
|
+
try {
|
|
9093
|
+
const moduleName = "hls.js";
|
|
9094
|
+
const mod = await import(
|
|
9095
|
+
/* @vite-ignore */
|
|
9096
|
+
/* webpackIgnore: true */
|
|
9097
|
+
moduleName
|
|
9098
|
+
).catch(
|
|
9099
|
+
() => null
|
|
9100
|
+
);
|
|
9101
|
+
if (cancelled || !mod) return;
|
|
9102
|
+
const Hls = mod.default ?? mod;
|
|
9103
|
+
if (Hls.isSupported()) {
|
|
9104
|
+
hls = new Hls();
|
|
9105
|
+
hls.loadSource(src);
|
|
9106
|
+
hls.attachMedia(el);
|
|
9107
|
+
} else {
|
|
9108
|
+
el.src = src;
|
|
9109
|
+
}
|
|
9110
|
+
} catch {
|
|
9111
|
+
}
|
|
9112
|
+
})();
|
|
9113
|
+
return () => {
|
|
9114
|
+
cancelled = true;
|
|
9115
|
+
if (hls) hls.destroy();
|
|
9116
|
+
};
|
|
9117
|
+
}, [isVideo, src]);
|
|
9118
|
+
if (renderOverride) {
|
|
9119
|
+
return /* @__PURE__ */ jsx(Fragment, { children: renderOverride({ src, state: renderState }) });
|
|
9120
|
+
}
|
|
9121
|
+
if (renderState === "blocked") {
|
|
9122
|
+
return /* @__PURE__ */ jsx(Fragment, { children: renderBlocked ? renderBlocked() : /* @__PURE__ */ jsx(
|
|
9123
|
+
"div",
|
|
9124
|
+
{
|
|
9125
|
+
role: "alert",
|
|
9126
|
+
className,
|
|
9127
|
+
style: { padding: 12, color: "#a00", ...style },
|
|
9128
|
+
children: "This file was blocked."
|
|
9129
|
+
}
|
|
9130
|
+
) });
|
|
9131
|
+
}
|
|
9132
|
+
if (renderState === "pending" && !src) {
|
|
9133
|
+
return /* @__PURE__ */ jsx(Fragment, { children: renderPlaceholder ? renderPlaceholder() : /* @__PURE__ */ jsx(
|
|
9134
|
+
"div",
|
|
9135
|
+
{
|
|
9136
|
+
role: "status",
|
|
9137
|
+
"aria-busy": true,
|
|
9138
|
+
className,
|
|
9139
|
+
style: { padding: 12, color: "#666", ...style },
|
|
9140
|
+
children: "Loading\u2026"
|
|
9141
|
+
}
|
|
9142
|
+
) });
|
|
9143
|
+
}
|
|
9144
|
+
if (isImage) {
|
|
9145
|
+
const finalSrc = src && status?.urls.optimized && (width || height) ? appendQuery(src, {
|
|
9146
|
+
width: width ? String(width) : void 0,
|
|
9147
|
+
height: height ? String(height) : void 0,
|
|
9148
|
+
fit: "cover"
|
|
9149
|
+
}) : src;
|
|
9150
|
+
return /* @__PURE__ */ jsx(
|
|
9151
|
+
"img",
|
|
9152
|
+
{
|
|
9153
|
+
src: finalSrc ?? void 0,
|
|
9154
|
+
alt: alt ?? "",
|
|
9155
|
+
width,
|
|
9156
|
+
height,
|
|
9157
|
+
className,
|
|
9158
|
+
style
|
|
9159
|
+
}
|
|
9160
|
+
);
|
|
9161
|
+
}
|
|
9162
|
+
if (isVideo) {
|
|
9163
|
+
return /* @__PURE__ */ jsx(
|
|
9164
|
+
"video",
|
|
9165
|
+
{
|
|
9166
|
+
ref: videoRef,
|
|
9167
|
+
src: src && !src.endsWith(".m3u8") ? src : void 0,
|
|
9168
|
+
controls: true,
|
|
9169
|
+
playsInline: true,
|
|
9170
|
+
preload: "metadata",
|
|
9171
|
+
className,
|
|
9172
|
+
style,
|
|
9173
|
+
"aria-label": alt,
|
|
9174
|
+
width,
|
|
9175
|
+
height
|
|
9176
|
+
}
|
|
9177
|
+
);
|
|
9178
|
+
}
|
|
9179
|
+
if (isAudio) {
|
|
9180
|
+
return /* @__PURE__ */ jsx(
|
|
9181
|
+
"audio",
|
|
9182
|
+
{
|
|
9183
|
+
src: src ?? void 0,
|
|
9184
|
+
controls: true,
|
|
9185
|
+
preload: "metadata",
|
|
9186
|
+
className,
|
|
9187
|
+
style,
|
|
9188
|
+
"aria-label": alt
|
|
9189
|
+
}
|
|
9190
|
+
);
|
|
9191
|
+
}
|
|
9192
|
+
return /* @__PURE__ */ jsx(
|
|
9193
|
+
"a",
|
|
9194
|
+
{
|
|
9195
|
+
href: src ?? "#",
|
|
9196
|
+
target: "_blank",
|
|
9197
|
+
rel: "noopener noreferrer",
|
|
9198
|
+
className,
|
|
9199
|
+
style,
|
|
9200
|
+
children: alt ?? "Download file"
|
|
9201
|
+
}
|
|
9202
|
+
);
|
|
9203
|
+
}
|
|
9204
|
+
function appendQuery(url, params) {
|
|
9205
|
+
const filtered = Object.entries(params).filter(([, v]) => v != null && v !== "");
|
|
9206
|
+
if (filtered.length === 0) return url;
|
|
9207
|
+
const sep = url.includes("?") ? "&" : "?";
|
|
9208
|
+
const qs = new URLSearchParams(filtered).toString();
|
|
9209
|
+
return url + sep + qs;
|
|
9210
|
+
}
|
|
9032
9211
|
|
|
9033
9212
|
// src/hooks/useMoney.ts
|
|
9034
9213
|
var useMoney = useMoneyClient;
|
|
@@ -10815,4 +10994,4 @@ function createSafeLogger(prefix) {
|
|
|
10815
10994
|
};
|
|
10816
10995
|
}
|
|
10817
10996
|
|
|
10818
|
-
export { FeedbackWidget, ScaleMuleApiError, ScaleMuleClient2 as ScaleMuleClient, ScaleMuleProvider, composePhone, createClient, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
|
|
10997
|
+
export { FeedbackWidget, ScaleMuleApiError, ScaleMuleClient2 as ScaleMuleClient, ScaleMuleMedia, ScaleMuleProvider, composePhone, createClient, createSafeLogger, normalizePhone, phoneCountries, sanitizeForLog, useAnalytics, useAuth, useBilling, useContent, useFeatureFlags, useFeedback, useFileStatus, useMedia, useMoney, useMoneyClient, usePushNotifications, useRealtime, useScaleMule, useScaleMuleClient, useShare, useUser, validateForm, validators };
|
package/package.json
CHANGED