@uploadcare/file-uploader
Version:
Building blocks for Uploadcare products integration
1,665 lines (1,635 loc) • 406 kB
JavaScript
/**
* @license
* MIT License
*
* Copyright (c) 2025 Uploadcare (hello@uploadcare.com). All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
// src/index.ts
import { BaseComponent as BaseComponent4, Data as Data8, UID as UID5 } from "@symbiotejs/symbiote";
// src/blocks/UploadCtxProvider/EventEmitter.ts
var DEFAULT_DEBOUNCE_TIMEOUT = 20;
var InternalEventType = Object.freeze({
INIT_SOLUTION: "init-solution",
CHANGE_CONFIG: "change-config",
ACTION_EVENT: "action-event",
ERROR_EVENT: "error-event"
});
var EventType = Object.freeze({
FILE_ADDED: "file-added",
FILE_REMOVED: "file-removed",
FILE_UPLOAD_START: "file-upload-start",
FILE_UPLOAD_PROGRESS: "file-upload-progress",
FILE_UPLOAD_SUCCESS: "file-upload-success",
FILE_UPLOAD_FAILED: "file-upload-failed",
FILE_URL_CHANGED: "file-url-changed",
MODAL_OPEN: "modal-open",
MODAL_CLOSE: "modal-close",
DONE_CLICK: "done-click",
UPLOAD_CLICK: "upload-click",
ACTIVITY_CHANGE: "activity-change",
COMMON_UPLOAD_START: "common-upload-start",
COMMON_UPLOAD_PROGRESS: "common-upload-progress",
COMMON_UPLOAD_SUCCESS: "common-upload-success",
COMMON_UPLOAD_FAILED: "common-upload-failed",
CHANGE: "change",
GROUP_CREATED: "group-created"
});
var EventEmitter = class {
_timeoutStore = /* @__PURE__ */ new Map();
_targets = /* @__PURE__ */ new Set();
_debugPrint = null;
constructor(debugPrint) {
this._debugPrint = debugPrint;
}
bindTarget(target) {
this._targets.add(target);
}
unbindTarget(target) {
this._targets.delete(target);
}
_dispatch(type, payload) {
for (const target of this._targets) {
target.dispatchEvent(
new CustomEvent(type, {
detail: payload
})
);
}
this._debugPrint?.(() => {
const copyPayload = !!payload && typeof payload === "object" ? { ...payload } : payload;
return [`event "${type}"`, copyPayload];
});
}
emit(type, payload, options = {}) {
const { debounce: debounce2 } = options;
if (typeof debounce2 !== "number" && !debounce2) {
this._dispatch(type, typeof payload === "function" ? payload() : payload);
return;
}
if (this._timeoutStore.has(type)) {
window.clearTimeout(this._timeoutStore.get(type));
}
const timeout = typeof debounce2 === "number" ? debounce2 : DEFAULT_DEBOUNCE_TIMEOUT;
const timeoutId = window.setTimeout(() => {
this._dispatch(type, typeof payload === "function" ? payload() : payload);
this._timeoutStore.delete(type);
}, timeout);
this._timeoutStore.set(type, timeoutId);
}
};
// src/utils/debounce.ts
function debounce(callback, wait) {
let timer;
const debounced = ((...args) => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => callback(...args), wait);
});
debounced.cancel = () => {
if (timer) clearTimeout(timer);
};
return debounced;
}
// src/abstract/Block.ts
import { BaseComponent, Data } from "@symbiotejs/symbiote";
// src/utils/comma-separated.ts
var deserializeCsv = (value) => {
if (!value) {
return [];
}
return value.split(",").map((item) => item.trim()).filter(Boolean);
};
var serializeCsv = (value) => {
return value.join(",");
};
// src/utils/cdn-utils.ts
var normalizeCdnOperation = (operation) => {
if (typeof operation !== "string" || !operation) {
return "";
}
let str = operation.trim();
if (str.startsWith("-/")) {
str = str.slice(2);
} else if (str.startsWith("/")) {
str = str.slice(1);
}
if (str.endsWith("/")) {
str = str.slice(0, str.length - 1);
}
return str;
};
var joinCdnOperations = (...operations) => {
return operations.filter((op) => typeof op === "string" && !!op).map((op) => normalizeCdnOperation(op)).join("/-/");
};
var createCdnUrlModifiers = (...cdnOperations) => {
const joined = joinCdnOperations(...cdnOperations);
return joined ? `-/${joined}/` : "";
};
function extractFilename(cdnUrl) {
const url = new URL(cdnUrl);
const noOrigin = url.pathname + url.search + url.hash;
const urlFilenameIdx = noOrigin.lastIndexOf("http");
const plainFilenameIdx = noOrigin.lastIndexOf("/");
let filename = "";
if (urlFilenameIdx >= 0) {
filename = noOrigin.slice(urlFilenameIdx);
} else if (plainFilenameIdx >= 0) {
filename = noOrigin.slice(plainFilenameIdx + 1);
}
return filename;
}
function extractUuid(cdnUrl) {
const url = new URL(cdnUrl);
const { pathname } = url;
const slashIndex = pathname.indexOf("/");
const secondSlashIndex = pathname.indexOf("/", slashIndex + 1);
return pathname.substring(slashIndex + 1, secondSlashIndex);
}
function extractCdnUrlModifiers(cdnUrl) {
const withoutFilename = trimFilename(cdnUrl);
const url = new URL(withoutFilename);
const operationsMarker = url.pathname.indexOf("/-/");
if (operationsMarker === -1) {
return "";
}
const operationsStr = url.pathname.substring(operationsMarker).slice(1);
return operationsStr;
}
function extractOperations(cdnUrl) {
const operationsStr = extractCdnUrlModifiers(cdnUrl);
return operationsStr.split("/-/").filter(Boolean).map((operation) => normalizeCdnOperation(operation));
}
function trimFilename(cdnUrl) {
const url = new URL(cdnUrl);
const filename = extractFilename(cdnUrl);
const filenamePathPart = isFileUrl(filename) ? splitFileUrl(filename).pathname : filename;
url.pathname = url.pathname.replace(filenamePathPart, "");
url.search = "";
url.hash = "";
return url.toString();
}
function isFileUrl(filename) {
return filename.startsWith("http");
}
function splitFileUrl(fileUrl) {
const url = new URL(fileUrl);
return {
pathname: `${url.origin}${url.pathname ?? ""}`,
search: url.search ?? "",
hash: url.hash ?? ""
};
}
var createCdnUrl = (baseCdnUrl, cdnModifiers, filename) => {
const url = new URL(trimFilename(baseCdnUrl));
const resolvedFilename = filename ?? extractFilename(baseCdnUrl);
const resolvedModifiers = cdnModifiers ?? "";
if (url.pathname.startsWith("//")) {
url.pathname = url.pathname.replace("//", "/");
}
if (resolvedFilename && isFileUrl(resolvedFilename)) {
const splitted = splitFileUrl(resolvedFilename);
url.pathname = `${url.pathname}${resolvedModifiers}${splitted.pathname || ""}`;
url.search = splitted.search;
url.hash = splitted.hash;
} else {
url.pathname = `${url.pathname}${resolvedModifiers}${resolvedFilename || ""}`;
}
return url.toString();
};
var createOriginalUrl = (cdnUrl, uuid) => {
const url = new URL(cdnUrl);
url.pathname = `${uuid}/`;
return url.toString();
};
// src/utils/stringToArray.ts
var stringToArray = (str, delimiter = ",") => {
return str.trim().split(delimiter).map((part) => part.trim()).filter((part) => part.length > 0);
};
// src/blocks/CloudImageEditor/src/lib/transformationUtils.ts
var OPERATIONS_DEFAULTS = Object.freeze({
brightness: 0,
exposure: 0,
gamma: 100,
contrast: 0,
saturation: 0,
vibrance: 0,
warmth: 0,
enhance: 0,
filter: 0,
rotate: 0,
mirror: false,
flip: false,
crop: void 0
});
var SUPPORTED_OPERATIONS_ORDERED = [
"enhance",
"brightness",
"exposure",
"gamma",
"contrast",
"saturation",
"vibrance",
"warmth",
"filter",
"mirror",
"flip",
"rotate",
"crop"
];
function transformationToStr(operation, options) {
if (typeof options === "number") {
const value = options;
return OPERATIONS_DEFAULTS[operation] !== value ? `${operation}/${value}` : "";
}
if (typeof options === "boolean") {
const value = options;
return OPERATIONS_DEFAULTS[operation] !== value ? `${operation}` : "";
}
if (operation === "filter" && options) {
const { name, amount } = options;
if (OPERATIONS_DEFAULTS.filter === amount) {
return "";
}
return `${operation}/${name}/${amount}`;
}
if (operation === "crop" && options) {
const { dimensions, coords } = options;
return `${operation}/${dimensions.join("x")}/${coords.join(",")}`;
}
return "";
}
function transformationsToOperations(transformations) {
return joinCdnOperations(
...SUPPORTED_OPERATIONS_ORDERED.filter(
(operation) => typeof transformations[operation] !== "undefined" && transformations[operation] !== null
).map((operation) => {
const options = transformations[operation];
return transformationToStr(operation, options);
}).filter((str) => !!str)
);
}
var COMMON_OPERATIONS = joinCdnOperations("format/auto", "progressive/yes");
var asNumber = ([value]) => typeof value !== "undefined" ? Number(value) : void 0;
var asBoolean = () => true;
var asFilter = ([name, amount]) => ({
name,
amount: typeof amount !== "undefined" ? Number(amount) : 100
});
var asCrop = ([dimensions, alignment]) => {
if (!/\d+x\d+/.test(dimensions) || !/\d+,\d+/.test(alignment)) {
throw new Error("Crop by aspect ratio, percentage or alignment shortcuts is not supported.");
}
return {
dimensions: stringToArray(dimensions, "x").map(Number),
coords: stringToArray(alignment).map(Number)
};
};
var OPERATION_PROCESSORS = Object.freeze({
enhance: asNumber,
brightness: asNumber,
exposure: asNumber,
gamma: asNumber,
contrast: asNumber,
saturation: asNumber,
vibrance: asNumber,
warmth: asNumber,
filter: asFilter,
mirror: asBoolean,
flip: asBoolean,
rotate: asNumber,
crop: (args) => {
const [dimensions, alignment] = args;
const { dimensions: parsedDimensions, coords } = asCrop([dimensions, alignment]);
return {
dimensions: parsedDimensions,
coords
};
}
});
function operationsToTransformations(operations) {
const transformations = {};
for (const operation of operations) {
const [name, ...args] = operation.split("/");
if (!name || !SUPPORTED_OPERATIONS_ORDERED.includes(name)) {
continue;
}
const operationName = name;
const processor = OPERATION_PROCESSORS[operationName];
try {
const value = processor(args);
transformations[operationName] = value;
} catch (err) {
console.warn(
[
`Failed to parse URL operation "${operation}". It will be ignored.`,
err instanceof Error ? `Error message: "${err.message}"` : err,
"If you need this functionality, please feel free to open an issue at https://github.com/uploadcare/blocks/issues/new"
].join("\n")
);
}
}
return transformations;
}
// src/blocks/CloudImageEditor/src/toolbar-constants.ts
var TabId = Object.freeze({
CROP: "crop",
TUNING: "tuning",
FILTERS: "filters"
});
var ALL_TABS = Object.freeze([TabId.CROP, TabId.TUNING, TabId.FILTERS]);
var ALL_COLOR_OPERATIONS = Object.freeze([
"brightness",
"exposure",
"gamma",
"contrast",
"saturation",
"vibrance",
"warmth",
"enhance"
]);
var ALL_FILTERS = Object.freeze([
"adaris",
"briaril",
"calarel",
"carris",
"cynarel",
"cyren",
"elmet",
"elonni",
"enzana",
"erydark",
"fenralan",
"ferand",
"galen",
"gavin",
"gethriel",
"iorill",
"iothari",
"iselva",
"jadis",
"lavra",
"misiara",
"namala",
"nerion",
"nethari",
"pamaya",
"sarnar",
"sedis",
"sewen",
"sorahel",
"sorlen",
"tarian",
"thellassan",
"varriel",
"varven",
"vevera",
"virkas",
"yedis",
"yllara",
"zatvel",
"zevcen"
]);
var ALL_CROP_OPERATIONS = Object.freeze(["rotate", "mirror", "flip"]);
var NUMERIC_OPERATION_DEFAULTS = OPERATIONS_DEFAULTS;
var COLOR_OPERATIONS_CONFIG = Object.freeze({
brightness: {
zero: NUMERIC_OPERATION_DEFAULTS.brightness,
range: [-100, 100],
keypointsNumber: 2
},
exposure: {
zero: NUMERIC_OPERATION_DEFAULTS.exposure,
range: [-500, 500],
keypointsNumber: 2
},
gamma: {
zero: NUMERIC_OPERATION_DEFAULTS.gamma,
range: [0, 1e3],
keypointsNumber: 2
},
contrast: {
zero: NUMERIC_OPERATION_DEFAULTS.contrast,
range: [-100, 500],
keypointsNumber: 2
},
saturation: {
zero: NUMERIC_OPERATION_DEFAULTS.saturation,
range: [-100, 500],
keypointsNumber: 1
},
vibrance: {
zero: NUMERIC_OPERATION_DEFAULTS.vibrance,
range: [-100, 500],
keypointsNumber: 1
},
warmth: {
zero: NUMERIC_OPERATION_DEFAULTS.warmth,
range: [-100, 100],
keypointsNumber: 1
},
enhance: {
zero: NUMERIC_OPERATION_DEFAULTS.enhance,
range: [0, 100],
keypointsNumber: 1
},
filter: {
zero: NUMERIC_OPERATION_DEFAULTS.filter,
range: [0, 100],
keypointsNumber: 1
}
});
// src/blocks/Config/initialConfig.ts
var DEFAULT_CDN_CNAME = "https://ucarecdn.com";
var DEFAULT_BASE_URL = "https://upload.uploadcare.com";
var DEFAULT_SOCIAL_BASE_URL = "https://social.uploadcare.com";
var DEFAULT_PREFIXED_CDN_BASE_DOMAIN = "https://ucarecd.net";
var config = {
pubkey: "",
multiple: true,
multipleMin: 0,
multipleMax: Number.MAX_SAFE_INTEGER,
confirmUpload: false,
imgOnly: false,
accept: "",
externalSourcesPreferredTypes: "",
externalSourcesEmbedCss: "",
store: "auto",
cameraMirror: false,
cameraCapture: "",
sourceList: "local, url, camera, dropbox, gdrive",
topLevelOrigin: "",
cloudImageEditorTabs: serializeCsv(ALL_TABS),
maxLocalFileSizeBytes: 0,
thumbSize: 76,
showEmptyList: false,
useLocalImageEditor: false,
useCloudImageEditor: true,
removeCopyright: false,
cropPreset: "",
imageShrink: "",
modalScrollLock: true,
modalBackdropStrokes: false,
sourceListWrap: true,
remoteTabSessionKey: "",
cdnCname: DEFAULT_CDN_CNAME,
cdnCnamePrefixed: DEFAULT_PREFIXED_CDN_BASE_DOMAIN,
baseUrl: DEFAULT_BASE_URL,
socialBaseUrl: DEFAULT_SOCIAL_BASE_URL,
secureSignature: "",
secureExpire: "",
secureDeliveryProxy: "",
retryThrottledRequestMaxTimes: 3,
retryNetworkErrorMaxTimes: 3,
multipartMinFileSize: 26214400,
multipartChunkSize: 5242880,
maxConcurrentRequests: 10,
multipartMaxConcurrentRequests: 4,
multipartMaxAttempts: 3,
checkForUrlDuplicates: false,
saveUrlForRecurrentUploads: false,
groupOutput: false,
userAgentIntegration: "",
debug: false,
metadata: null,
localeName: "en",
localeDefinitionOverride: null,
secureUploadsExpireThreshold: 10 * 60 * 1e3,
secureUploadsSignatureResolver: null,
secureDeliveryProxyUrlResolver: null,
iconHrefResolver: null,
fileValidators: [],
collectionValidators: [],
validationTimeout: 15 * 1e3,
validationConcurrency: 100,
cameraModes: "photo, video",
defaultCameraMode: null,
enableAudioRecording: true,
enableVideoRecording: null,
maxVideoRecordingDuration: null,
mediaRecorderOptions: null,
filesViewMode: "list",
gridShowFileNames: false,
cloudImageEditorAutoOpen: false,
cloudImageEditorMaskHref: null,
testMode: false,
qualityInsights: true
};
var initialConfig = Object.freeze(config);
// src/utils/getLocaleDirection.ts
var getLocaleDirection = (localeId) => {
const locale2 = new Intl.Locale(localeId);
let direction = "ltr";
const fromGetter = locale2.getTextInfo?.().direction;
if (fromGetter) {
direction = fromGetter;
} else if (locale2.textInfo?.direction) {
direction = locale2.textInfo.direction;
}
return direction;
};
// src/utils/getPluralForm.ts
var getPluralForm = (locale2, count) => {
const pluralForm = new Intl.PluralRules(locale2).select(count);
return pluralForm;
};
// src/utils/template-utils.ts
var DEFAULT_TRANSFORMER = (value) => value;
var OPEN_TOKEN = "{{";
var CLOSE_TOKEN = "}}";
var PLURAL_PREFIX = "plural:";
function applyTemplateData(template, data = {}, options = {}) {
const { openToken = OPEN_TOKEN, closeToken = CLOSE_TOKEN, transform = DEFAULT_TRANSFORMER } = options;
for (const key in data) {
const rawValue = data[key];
const value = rawValue != null ? rawValue.toString() : void 0;
const replacement = typeof value === "string" ? transform(value) : String(value);
template = template.replaceAll(openToken + key + closeToken, replacement);
}
return template;
}
function getPluralObjects(template) {
const pluralObjects = [];
let open = template.indexOf(OPEN_TOKEN);
while (open !== -1) {
const close = template.indexOf(CLOSE_TOKEN, open);
if (close === -1) {
break;
}
const variable = template.substring(open + 2, close);
if (variable.startsWith(PLURAL_PREFIX)) {
const keyValue = template.substring(open + 2, close).replace(PLURAL_PREFIX, "");
const key = keyValue.substring(0, keyValue.indexOf("("));
const count = keyValue.substring(keyValue.indexOf("(") + 1, keyValue.indexOf(")"));
pluralObjects.push({ variable, pluralKey: key, countVariable: count });
}
open = template.indexOf(OPEN_TOKEN, close);
}
return pluralObjects;
}
// src/utils/WindowHeightTracker.ts
var WINDOW_HEIGHT_TRACKER_PROPERTY = "--uploadcare-blocks-window-height";
var WindowHeightTracker = class _WindowHeightTracker {
static clientsRegistry = /* @__PURE__ */ new Set();
static flush = debounce(() => {
document.documentElement.style.setProperty(WINDOW_HEIGHT_TRACKER_PROPERTY, `${window.innerHeight}px`);
}, 100);
static registerClient(client) {
if (_WindowHeightTracker.clientsRegistry.size === 0) {
_WindowHeightTracker.attachTracker();
}
_WindowHeightTracker.clientsRegistry.add(client);
}
static unregisterClient(client) {
_WindowHeightTracker.clientsRegistry.delete(client);
if (_WindowHeightTracker.clientsRegistry.size === 0) {
_WindowHeightTracker.detachTracker();
}
}
static attachTracker() {
window.addEventListener("resize", _WindowHeightTracker.flush, { passive: true, capture: true });
_WindowHeightTracker.flush();
}
static detachTracker() {
window.removeEventListener("resize", _WindowHeightTracker.flush, { capture: true });
document.documentElement.style.removeProperty(WINDOW_HEIGHT_TRACKER_PROPERTY);
}
};
// src/utils/waitForAttribute.ts
var waitForAttribute = ({
element,
attribute,
onSuccess,
onTimeout,
timeout = 300
}) => {
const currentAttrValue = element.getAttribute(attribute);
if (currentAttrValue !== null) {
onSuccess(currentAttrValue);
return;
}
const observer = new MutationObserver((mutations) => {
const mutation = mutations[mutations.length - 1];
if (mutation) {
handleMutation(mutation);
}
});
observer.observe(element, {
attributes: true,
attributeFilter: [attribute]
});
const timeoutId = window.setTimeout(() => {
observer.disconnect();
onTimeout();
}, timeout);
const handleMutation = (mutation) => {
const attrValue = element.getAttribute(attribute);
if (mutation.type === "attributes" && mutation.attributeName === attribute && attrValue !== null) {
window.clearTimeout(timeoutId);
observer.disconnect();
onSuccess(attrValue);
}
};
};
// src/abstract/CTX.ts
import { Queue } from "@uploadcare/upload-client";
var blockCtx = () => ({});
var activityBlockCtx = (fnCtx) => ({
...blockCtx(),
"*currentActivity": null,
"*currentActivityParams": {},
"*history": [],
"*historyBack": null,
"*closeModal": () => {
fnCtx.modalManager?.close(fnCtx.$["*currentActivity"]);
fnCtx.set$({
"*currentActivity": null
});
}
});
var uploaderBlockCtx = (fnCtx) => ({
...activityBlockCtx(fnCtx),
"*commonProgress": 0,
"*uploadList": [],
"*uploadQueue": new Queue(1),
"*collectionErrors": [],
"*collectionState": null,
"*groupInfo": null,
"*uploadTrigger": /* @__PURE__ */ new Set(),
"*secureUploadsManager": null
});
var solutionBlockCtx = (fnCtx) => ({
...uploaderBlockCtx(fnCtx),
"*solution": null
});
// src/locales/file-uploader/en.js
var en_default = {
"locale-id": "en",
"social-source-lang": "en",
"upload-file": "Upload file",
"upload-files": "Upload files",
"choose-file": "Choose file",
"choose-files": "Choose files",
"drop-files-here": "Drop files here",
"select-file-source": "Select file source",
selected: "Selected",
upload: "Upload",
"add-more": "Add more",
cancel: "Cancel",
"start-from-cancel": "Cancel",
clear: "Clear",
"camera-shot": "Shot",
"upload-url": "Import",
"upload-url-placeholder": "Paste link here",
"edit-image": "Edit image",
"edit-detail": "Details",
back: "Back",
done: "Done",
ok: "Ok",
"remove-from-list": "Remove",
no: "No",
yes: "Yes",
"confirm-your-action": "Confirm your action",
"are-you-sure": "Are you sure?",
"selected-count": "{{count}} of {{total}} selected",
"select-all": "Select all",
"deselect-all": "Deselect all",
"upload-error": "Upload error",
"validation-error": "Validation error",
"no-files": "No files selected",
browse: "Browse",
"not-uploaded-yet": "Not uploaded yet...",
file__one: "file",
file__other: "files",
error__one: "error",
error__other: "errors",
"header-uploading": "Uploading {{count}} {{plural:file(count)}}",
"header-failed": "{{count}} {{plural:error(count)}}",
"header-succeed": "{{count}} {{plural:file(count)}} uploaded",
"header-total": "{{count}} {{plural:file(count)}} selected",
"src-type-local": "From device",
"src-type-from-url": "From link",
"src-type-camera": "Camera",
"src-type-mobile-video-camera": "Video",
"src-type-mobile-photo-camera": "Photo",
"src-type-draw": "Draw",
"src-type-facebook": "Facebook",
"src-type-dropbox": "Dropbox",
"src-type-gdrive": "Google Drive",
"src-type-ngdrive": "Google Drive",
"src-type-gphotos": "Google Photos",
"src-type-flickr": "Flickr",
"src-type-vk": "VK",
"src-type-evernote": "Evernote",
"src-type-box": "Box",
"src-type-onedrive": "OneDrive",
"src-type-huddle": "Huddle",
"src-type-other": "Other",
"caption-from-url": "Import from link",
"caption-camera": "Camera",
"caption-draw": "Draw",
"caption-edit-file": "Edit file",
"file-no-name": "No name...",
"toggle-fullscreen": "Toggle fullscreen",
"toggle-guides": "Toggle guides",
rotate: "Rotate",
"flip-vertical": "Flip vertical",
"flip-horizontal": "Flip horizontal",
apply: "Apply",
brightness: "Brightness",
contrast: "Contrast",
saturation: "Saturation",
exposure: "Exposure",
gamma: "Gamma",
vibrance: "Vibrance",
warmth: "Warmth",
enhance: "Enhance",
original: "Original",
resize: "Resize image",
crop: "Crop",
"select-color": "Select color",
text: "Text",
draw: "Draw",
"cancel-edit": "Cancel edit",
"tab-view": "Preview",
"tab-details": "Details",
"file-name": "Name",
"file-size": "Size",
"cdn-url": "CDN URL",
"file-size-unknown": "Unknown",
"camera-permissions-denied": "Camera access denied",
"camera-permissions-prompt": "Please allow access to the camera",
"camera-permissions-request": "Request access",
"files-count-limit-error-title": "Files count limit overflow",
"files-count-limit-error-too-few": "You\u2019ve chosen {{total}} {{plural:file(total)}}. At least {{min}} {{plural:file(min)}} required.",
"files-count-limit-error-too-many": "You\u2019ve chosen too many files. {{max}} {{plural:file(max)}} is maximum.",
"files-max-size-limit-error": "File is too big. Max file size is {{maxFileSize}}.",
"has-validation-errors": "File validation error occurred. Please, check your files before upload.",
"images-only-accepted": "Only image files are accepted.",
"file-type-not-allowed": "Uploading of these file types is not allowed.",
"some-files-were-not-uploaded": "Some files were not uploaded.",
"file-item-edit-button": "Edit",
"file-item-remove-button": "Remove",
"a11y-editor-tab-filters": "Filters",
"a11y-editor-tab-tuning": "Tuning",
"a11y-editor-tab-crop": "Crop",
"a11y-activity-header-button-close": "Close",
flip: "Flip",
mirror: "Mirror",
"a11y-cloud-editor-apply-filter": "Apply {{name}} filter",
"a11y-cloud-editor-apply-crop": "Apply {{name}} operation",
"a11y-cloud-editor-apply-tuning": "Apply {{name}} tuning",
"a11y-cloud-editor-apply-aspect-ratio": "Apply operation {{name}} {{value}}",
finished: "Finished",
failed: "Failed",
uploading: "Uploading",
idle: "Idle",
"a11y-file-item-status": "File {{fileName}} in status {{status}}",
"waiting-for": "Waiting for {{source}}",
"queued-uploading": "Queued for upload",
"queued-validation": "Queued for validation",
validation: "Validating",
"crop-to-shape": "Crop to {{value}}",
custom: "Freeform",
"freeform-crop": "Freeform crop"
};
// src/abstract/localeRegistry.ts
var localeRegistry = /* @__PURE__ */ new Map();
var localeResolvers = /* @__PURE__ */ new Map();
var defineLocaleSync = (localeName, definition) => {
if (localeRegistry.has(localeName)) {
console.log(`Locale ${localeName} is already defined. Overwriting...`);
}
localeRegistry.set(localeName, { ...en_default, ...definition });
};
var defineLocaleAsync = (localeName, definitionResolver) => {
localeResolvers.set(localeName, definitionResolver);
};
var defineLocale = (localeName, definitionOrResolver) => {
if (typeof definitionOrResolver === "function") {
defineLocaleAsync(localeName, definitionOrResolver);
} else {
defineLocaleSync(localeName, definitionOrResolver);
}
};
var resolveLocaleDefinition = async (localeName) => {
if (!localeRegistry.has(localeName)) {
if (!localeResolvers.has(localeName)) {
throw new Error(`Locale ${localeName} is not defined`);
}
const definitionResolver = localeResolvers.get(localeName);
const definition = await definitionResolver();
defineLocaleSync(localeName, definition);
}
return localeRegistry.get(localeName);
};
defineLocale("en", en_default);
// src/abstract/managers/LocaleManager.ts
var localeStateKey = (key) => `*l10n/${key}`;
var DEFAULT_LOCALE = "en";
var LocaleManager = class {
_blockInstance = null;
_localeName = "";
_callbacks = /* @__PURE__ */ new Set();
_boundBlocks = /* @__PURE__ */ new Map();
constructor(blockInstance) {
this._blockInstance = blockInstance;
for (const [key, value] of Object.entries(en_default)) {
const noTranslation = this._blockInstance.has(localeStateKey(key)) ? !this._blockInstance.$[localeStateKey(key)] : true;
this._blockInstance.add(localeStateKey(key), value, noTranslation);
}
setTimeout(() => {
blockInstance.subConfigValue("localeName", async (localeName) => {
if (!this._blockInstance || !localeName) {
return;
}
this._localeName = localeName;
const definition = await resolveLocaleDefinition(localeName);
if (localeName !== DEFAULT_LOCALE && this._localeName !== localeName) {
return;
}
const overrides = this._blockInstance.cfg.localeDefinitionOverride?.[localeName];
for (const [key, value] of Object.entries(definition)) {
const overriddenValue = overrides?.[key];
this._blockInstance.add(localeStateKey(key), overriddenValue ?? value, true);
for (const callback of this._callbacks) {
callback();
}
}
});
blockInstance.subConfigValue("localeDefinitionOverride", (localeDefinitionOverride) => {
if (!localeDefinitionOverride) {
return;
}
const definition = localeDefinitionOverride[this._localeName];
if (!definition) {
return;
}
for (const [key, value] of Object.entries(definition)) {
this._blockInstance?.add(localeStateKey(key), value, true);
for (const callback of this._callbacks) {
callback();
}
}
});
});
}
onLocaleChange(callback) {
const debouncedCb = debounce(callback, 0);
this._callbacks.add(debouncedCb);
return () => {
this._callbacks.delete(debouncedCb);
};
}
bindL10n(block, key, resolver) {
block.$[key] = resolver();
if (!this._boundBlocks.has(block)) {
this._boundBlocks.set(block, /* @__PURE__ */ new Map());
}
this._boundBlocks.get(block)?.get(key)?.();
const destroyCallback = this.onLocaleChange(() => {
block.$[key] = resolver();
});
this._boundBlocks.get(block)?.set(key, destroyCallback);
}
destroyL10nBindings(block) {
const callbacks = this._boundBlocks.get(block);
if (!callbacks) {
return;
}
for (const callback of callbacks.values()) {
callback();
}
this._boundBlocks.delete(block);
}
destroy() {
this._callbacks.clear();
}
};
// src/abstract/l10nProcessor.ts
function l10nProcessor(fr, fnCtx) {
[...fr.querySelectorAll("[l10n]")].forEach((el) => {
const key = el.getAttribute("l10n");
if (!key) {
return;
}
const list = key.split(";");
for (const item of list) {
if (item) locale(el, item, fnCtx);
}
});
}
var locale = (el, key, fnCtx) => {
let elProp = "textContent";
let useAttribute = false;
if (key.includes(":")) {
const arr = key.split(":");
if (arr.length !== 2) {
console.warn(`l10n attribute value should be in format "property:key" or "key". Found: ${key}`);
return;
}
const tuple = arr;
elProp = tuple[0];
key = tuple[1];
if (elProp.startsWith("@")) {
elProp = elProp.slice(1);
useAttribute = true;
}
}
const localCtxKey = key;
if (fnCtx.has(localCtxKey)) {
fnCtx.sub(localCtxKey, (mappedKey) => {
if (!mappedKey) {
return;
}
if (!fnCtx.l10nProcessorSubs.has(localCtxKey)) {
fnCtx.l10nProcessorSubs.set(localCtxKey, /* @__PURE__ */ new Set());
}
const keySubs = fnCtx.l10nProcessorSubs.get(localCtxKey);
keySubs?.forEach((sub2) => {
sub2.remove();
keySubs.delete(sub2);
fnCtx.allSubs.delete(sub2);
});
const nodeStateKey = localeStateKey(mappedKey).replace("*", "");
if (!fnCtx.nodeCtx.has(nodeStateKey)) {
fnCtx.nodeCtx.add(nodeStateKey, mappedKey);
}
const sub = fnCtx.nodeCtx.sub(nodeStateKey, () => {
el[elProp] = fnCtx.l10n(mappedKey);
});
keySubs?.add(sub);
fnCtx.allSubs.add(sub);
el.removeAttribute("l10n");
});
}
const stateKey = localeStateKey(key);
if (!fnCtx.has(stateKey)) {
fnCtx.add(stateKey, "");
}
fnCtx.sub(stateKey, () => {
if (useAttribute) {
el.setAttribute(elProp, fnCtx.l10n(key));
} else {
el[elProp] = fnCtx.l10n(key);
}
});
el.removeAttribute("l10n");
};
// src/abstract/managers/a11y.ts
import { focusGroupKeyUX, hiddenKeyUX, jumpKeyUX, pressKeyUX, startKeyUX } from "keyux";
var ScopedMinimalWindow = class {
_listeners = /* @__PURE__ */ new Map();
_scope = [];
addEventListener(type, listener) {
const wrappedListener = (event) => {
const target = event.target;
if (!(target instanceof Node)) {
return;
}
if (this._scope.some((el) => el === target || el.contains(target))) {
listener(event);
}
};
this._listeners.set(listener, wrappedListener);
window.addEventListener(type, wrappedListener);
}
removeEventListener(type, listener) {
const wrappedListener = this._listeners.get(listener);
if (wrappedListener) {
window.removeEventListener(type, wrappedListener);
}
this._listeners.delete(listener);
}
get CustomEvent() {
return window.CustomEvent;
}
get document() {
return window.document;
}
get navigator() {
return window.navigator;
}
registerScope(scope) {
this._scope.push(scope);
}
destroy() {
this._scope = [];
for (const wrappedListener of this._listeners.values()) {
window.removeEventListener("keydown", wrappedListener);
window.removeEventListener("keyup", wrappedListener);
}
this._listeners.clear();
}
};
var A11y = class {
_destroyKeyUX;
_scopedWindow;
constructor() {
this._scopedWindow = new ScopedMinimalWindow();
this._destroyKeyUX = startKeyUX(this._scopedWindow, [
focusGroupKeyUX(),
pressKeyUX("is-pressed"),
jumpKeyUX(),
hiddenKeyUX()
]);
}
registerBlock(scope) {
this._scopedWindow.registerScope(scope);
}
destroy() {
this._destroyKeyUX?.();
this._scopedWindow.destroy();
}
};
// src/abstract/managers/ModalManager.ts
var ModalEvents = Object.freeze({
ADD: "modal:add",
DELETE: "modal:delete",
OPEN: "modal:open",
CLOSE: "modal:close",
CLOSE_ALL: "modal:closeAll",
DESTROY: "modal:destroy"
});
var ModalManager = class {
_modals = /* @__PURE__ */ new Map();
_activeModals = /* @__PURE__ */ new Set();
_subscribers = /* @__PURE__ */ new Map();
_block;
constructor(block) {
this._block = block;
}
_debugPrint(...args) {
this._block.debugPrint("[modal-manager]", ...args);
}
/**
* Register a modal with the manager
* @param id Unique identifier for the modal
* @param modal Modal component instance
*/
registerModal(id, modal) {
this._modals.set(id, modal);
this._notify(ModalEvents.ADD, { id, modal });
}
/** Remove a modal by ID. */
deleteModal(id) {
if (!this._modals.has(id)) return false;
const modal = this._modals.get(id);
this._modals.delete(id);
this._activeModals.delete(id);
this._notify(ModalEvents.DELETE, { id, modal });
return true;
}
/** Open a modal by its ID. */
open(id) {
if (!this._modals.has(id)) {
this._debugPrint(`Modal with ID "${id}" not found`);
return false;
}
const modal = this._modals.get(id);
this._activeModals.add(id);
this._notify(ModalEvents.OPEN, { modal, id });
return true;
}
/** Close a specific modal by ID. */
close(id) {
if (!this._modals.has(id) || !this._activeModals.has(id)) {
this._debugPrint(`Modal with ID "${id}" not found or not active`);
return false;
}
const modal = this._modals.get(id);
this._activeModals.delete(id);
this._notify(ModalEvents.CLOSE, { id, modal });
return true;
}
/** Toggle a modal - open if closed, close if open. */
toggle(id) {
if (!this._modals.has(id)) {
this._debugPrint(`Modal with ID "${id}" not found`);
return false;
}
if (this._activeModals.has(id)) {
return this.close(id);
} else {
return this.open(id);
}
}
/** True if there are any active modals. */
get hasActiveModals() {
return this._activeModals.size > 0;
}
/** Close the most recently opened modal and return to the previous one. */
back() {
if (this._activeModals.size === 0) {
this._debugPrint("No active modals to go back from");
return false;
}
const lastModalId = Array.from(this._activeModals).pop();
return lastModalId ? this.close(lastModalId) : false;
}
/** Close all open modals. */
closeAll() {
const count = this._activeModals.size;
this._activeModals.clear();
this._notify(ModalEvents.CLOSE_ALL, {});
return count;
}
/**
* Subscribe to modal events
* @returns Unsubscribe function
*/
subscribe(event, callback) {
if (!this._subscribers.has(event)) {
this._subscribers.set(event, /* @__PURE__ */ new Set());
}
this._subscribers.get(event)?.add(callback);
return () => this.unsubscribe(event, callback);
}
/** Unsubscribe from modal events */
unsubscribe(event, callback) {
if (this._subscribers.has(event)) {
this._subscribers.get(event)?.delete(callback);
}
}
/** Notify all subscribers of a modal event. */
_notify(event, data) {
if (this._subscribers.has(event)) {
for (const callback of this._subscribers.get(event) ?? /* @__PURE__ */ new Set()) {
try {
callback(data);
} catch (error) {
this._block.telemetryManager.sendEventError(error, "modal subscriber");
this._debugPrint("Error in modal subscriber:", error);
}
}
}
}
/** Destroy the modal manager, clean up resources */
destroy() {
this.closeAll();
this._modals.clear();
this._subscribers.clear();
this._notify(ModalEvents.DESTROY, {});
}
};
// src/abstract/managers/TelemetryManager.ts
import { TelemetryAPIService } from "@uploadcare/quality-insights";
import { Queue as Queue2 } from "@uploadcare/upload-client";
// package.json
var version = "1.25.0";
// src/env.ts
var PACKAGE_NAME = "blocks";
var PACKAGE_VERSION = version;
// src/abstract/managers/TelemetryManager.ts
var TelemetryManager = class {
_sessionId = crypto.randomUUID();
_telemetryInstance;
_block;
_config = structuredClone(initialConfig);
_initialized = false;
_lastPayload = null;
_queue;
constructor(block) {
this._block = block;
this._telemetryInstance = new TelemetryAPIService();
this._queue = new Queue2(10);
for (const key of Object.keys(this._config)) {
this._block.subConfigValue(key, (value) => {
if (this._initialized && this._config[key] !== value) {
this.sendEvent({
eventType: InternalEventType.CHANGE_CONFIG
});
}
this._setConfig(key, value);
});
}
}
_init(type) {
if (type === InternalEventType.INIT_SOLUTION && !this._initialized) {
this._initialized = true;
}
}
_setConfig(key, value) {
if (this._config[key] === value) {
return;
}
this._config[key] = value;
}
_formattingPayload(body) {
const payload = body.payload ? { ...body.payload } : {};
if (payload.activity) {
payload.activity = void 0;
}
const result = { ...body };
if (body.eventType === InternalEventType.INIT_SOLUTION || body.eventType === InternalEventType.CHANGE_CONFIG) {
result.config = this._config;
}
return {
...result,
appVersion: PACKAGE_VERSION,
appName: PACKAGE_NAME,
sessionId: this._sessionId,
component: this._solution,
activity: this._activity,
projectPubkey: this._config.pubkey,
userAgent: navigator.userAgent,
eventType: result.eventType ?? "",
eventTimestamp: this._timestamp,
payload: {
location: this._location,
...payload
}
};
}
_excludedEvents(type) {
if (type && [
EventType.CHANGE,
EventType.COMMON_UPLOAD_PROGRESS,
EventType.FILE_ADDED,
EventType.FILE_REMOVED,
EventType.FILE_UPLOAD_START,
EventType.FILE_UPLOAD_PROGRESS,
EventType.FILE_UPLOAD_SUCCESS,
EventType.FILE_UPLOAD_FAILED
].includes(type)) {
return true;
}
return false;
}
sendEvent(body) {
const payload = this._formattingPayload({
eventType: body.eventType,
payload: body.payload,
config: body.config
});
this._init(body.eventType);
const hasExcludedEvents = this._excludedEvents(body.eventType);
if (hasExcludedEvents) {
return;
}
const hasDataSame = this._lastPayload && this._checkObj(this._lastPayload, payload);
if (hasDataSame) {
return;
}
this._queue.add(async () => {
this._lastPayload = payload;
await this._telemetryInstance.sendEvent(payload);
});
}
sendEventError(error, context = "unknown") {
this.sendEvent({
eventType: InternalEventType.ERROR_EVENT,
payload: {
metadata: {
event: "error",
text: `Error in ${context}`,
error: error.message
}
}
});
}
/**
* Method to send telemetry event for Cloud Image Editor.
*/
sendEventCloudImageEditor(e, tabId, options = {}) {
this.sendEvent({
eventType: InternalEventType.ACTION_EVENT,
payload: {
metadata: {
tabId,
node: e.currentTarget?.tagName,
event: e.type,
...options
}
}
});
}
/**
* Deeply compares two objects and returns true if they are equal, false otherwise.
*/
_checkObj(last, current) {
if (JSON.stringify(last) === JSON.stringify(current)) return true;
if (typeof last !== "object" || typeof current !== "object" || last == null || current == null) return false;
const lastKeys = Object.keys(last);
const currentKeys = Object.keys(current);
if (lastKeys.length !== currentKeys.length) return false;
for (const key of lastKeys) {
if (!Object.hasOwn(current, key)) return false;
if (!this._checkObj(last[key], current[key]))
return false;
}
return true;
}
get _timestamp() {
return Date.now();
}
get _solution() {
if (!this._block.has("*solution")) {
return null;
}
const solution = this._block.$["*solution"];
return solution ? solution.toLowerCase() : null;
}
get _activity() {
if (!this._block.has("*currentActivity")) {
return null;
}
return this._block.$["*currentActivity"] ?? null;
}
get _location() {
return location.origin;
}
};
// src/abstract/sharedConfigKey.ts
var sharedConfigKey = (key) => `*cfg/${key}`;
// src/abstract/testModeProcessor.ts
function testModeProcessor(fr, fnCtx) {
const elementsWithTestId = fr.querySelectorAll("[data-testid]");
if (elementsWithTestId.length === 0) {
return;
}
const valuesPerElement = /* @__PURE__ */ new WeakMap();
for (const el of elementsWithTestId) {
const testIdValue = el.getAttribute("data-testid");
if (testIdValue) {
valuesPerElement.set(el, testIdValue);
}
}
fnCtx.subConfigValue("testMode", (testMode) => {
if (!testMode) {
for (const el of elementsWithTestId) {
el.removeAttribute("data-testid");
}
return;
}
const testIdPrefix = fnCtx.testId;
for (const el of elementsWithTestId) {
const testIdValue = valuesPerElement.get(el);
if (!testIdValue) {
continue;
}
el.setAttribute(`data-testid`, `${testIdPrefix}--${testIdValue}`);
}
});
}
// src/abstract/Block.ts
var TAG_PREFIX = "uc-";
var Block = class extends BaseComponent {
__cfgProxy;
l10nProcessorSubs = /* @__PURE__ */ new Map();
static StateConsumerScope = null;
static styleAttrs = [];
requireCtxName = false;
activityType = null;
init$ = blockCtx();
l10n(str, variables = {}) {
if (!str) {
return "";
}
const template = this.$[localeStateKey(str)] || str;
const pluralObjects = getPluralObjects(template);
for (const pluralObject of pluralObjects) {
variables[pluralObject.variable] = this.pluralize(
pluralObject.pluralKey,
Number(variables[pluralObject.countVariable])
);
}
const result = applyTemplateData(template, variables);
return result;
}
pluralize(key, count) {
const locale2 = this.l10n("locale-id") || "en";
const pluralForm = getPluralForm(locale2, count);
return this.l10n(`${key}__${pluralForm}`);
}
bindL10n(key, resolver) {
this.localeManager?.bindL10n(this, key, resolver);
}
constructor() {
super();
this.addTemplateProcessor(
l10nProcessor
);
this.addTemplateProcessor(
testModeProcessor
);
}
emit(type, payload, options) {
const eventEmitter = this.has("*eventEmitter") ? this.$["*eventEmitter"] : void 0;
if (!eventEmitter) {
return;
}
eventEmitter.emit(type, payload, options);
this.telemetryManager.sendEvent({
eventType: type,
payload: typeof payload === "function" ? payload() : payload
});
}
hasBlockInCtx(callback) {
for (const block of this.blocksRegistry) {
if (callback(block)) {
return true;
}
}
return false;
}
setOrAddState(prop, newVal) {
this.add$(
{
[prop]: newVal
},
true
);
}
connectedCallback() {
const styleAttrs = this.constructor.styleAttrs;
styleAttrs.forEach((attr) => {
this.setAttribute(attr, "");
});
if (this.hasAttribute("retpl")) {
this.constructor["template"] = null;
this.processInnerHtml = true;
}
if (this.requireCtxName) {
waitForAttribute({
element: this,
attribute: "ctx-name",
onSuccess: () => {
super.connectedCallback();
},
onTimeout: () => {
console.error("Attribute `ctx-name` is required and it is not set.");
}
});
} else {
super.connectedCallback();
}
WindowHeightTracker.registerClient(this);
}
disconnectedCallback() {
super.disconnectedCallback();
WindowHeightTracker.unregisterClient(this);
}
initCallback() {
if (!this.has("*blocksRegistry")) {
this.add("*blocksRegistry", /* @__PURE__ */ new Set());
}
const blocksRegistry = this.$["*blocksRegistry"];
blocksRegistry.add(this);
if (!this.has("*eventEmitter")) {
this.add("*eventEmitter", new EventEmitter(this.debugPrint.bind(this)));
}
if (!this.has("*localeManager")) {
this.add("*localeManager", new LocaleManager(this));
}
if (this.cfg.qualityInsights && !this.has("*telemetryManager")) {
this.add("*telemetryManager", new TelemetryManager(this));
}
if (!this.has("*a11y")) {
this.add("*a11y", new A11y());
}
if (!this.has("*modalManager")) {
this.add("*modalManager", new ModalManager(this));
}
this.sub(localeStateKey("locale-id"), (localeId) => {
const direction = getLocaleDirection(localeId);
this.style.direction = direction === "ltr" ? "" : direction;
});
this.subConfigValue("testMode", (testMode) => {
if (!testMode || !this.testId) {
this.removeAttribute("data-testid");
return;
}
this.setAttribute("data-testid", this.testId);
});
}
get testId() {
const testId = window.customElements.getName(this.constructor);
return testId;
}
get modalManager() {
return this.has("*modalManager") ? this.$["*modalManager"] : void 0;
}
get telemetryManager() {
if (!this.cfg.qualityInsights) {
return {
sendEvent: () => {
},
sendEventCloudImageEditor: () => {
},
sendEventError: () => {
}
};
}
return this.has("*telemetryManager") && this.$["*telemetryManager"];
}
get localeManager() {
return this.has("*localeManager") ? this.$["*localeManager"] : null;
}
get a11y() {
return this.has("*a11y") ? this.$["*a11y"] : null;
}
get blocksRegistry() {
return this.$["*blocksRegistry"];
}
destroyCallback() {
super.destroyCallback();
const blocksRegistry = this.blocksRegistry;
blocksRegistry?.delete(this);
this.localeManager?.destroyL10nBindings(this);
this.l10nProcessorSubs = /* @__PURE__ */ new Map();
Data.deleteCtx(this);
if (blocksRegistry?.size === 0) {
setTimeout(() => {
this.destroyCtxCallback();
}, 0);
}
}
/**
* Called when the last block is removed from the context. Note that inheritors must run their callback before that.
*/
destroyCtxCallback() {
Data.deleteCtx(this.ctxName);
this.localeManager?.destroy();
this.modalManager?.destroy();
}
async proxyUrl(url) {
if (this.cfg.secureDeliveryProxy && this.cfg.secureDeliveryProxyUrlResolver) {
console.warn(
"Both secureDeliveryProxy and secureDeliveryProxyUrlResolver are set. The secureDeliveryProxyUrlResolver will be used."
);
}
if (this.cfg.secureDeliveryProxyUrlResolver) {
try {
return await this.cfg.secureDeliveryProxyUrlResolver(url, {
uuid: extractUuid(url),
cdnUrlModifiers: extractCdnUrlModifiers(url),
fileName: extractFilename(url)
});
} catch (err) {
console.error("Failed to resolve secure delivery proxy URL. Falling back to the default URL.", err);
this.telemetryManager.sendEventError(
err,
"secureDeliveryProxyUrlResolver. Failed to resolve secure delivery proxy URL. Falling back to the default URL."
);
return url;
}
}
if (this.cfg.secureDeliveryProxy) {
return applyTemplateData(
this.cfg.secureDeliveryProxy,
{ previewUrl: url },
{ transform: (value) => window.encodeURIComponent(value) }
);
}
return url;
}
get cfg() {
if (!this.__cfgProxy) {
const o = /* @__PURE__ */ Object.create(null);
this.__cfgProxy = new Proxy(o, {
set: (obj, key, value) => {
if (typeof key !== "string") {
return false;
}
const sharedKey = sharedConfigKey(key);
if (!this.has(sharedKey)) {
this.add(sharedKey, initialConfig[key]);
}
this.$[sharedKey] = value;
return true;
},
get: (_obj, key) => {
const sharedKey = sharedConfigKey(key);
if (!this.has(sharedKey)) {
this.add(sharedKey, initialConfig[key]);
}
return this.$[sharedConfigKey(key)];
}
});
}
return this.__cfgProxy;
}
subConfigValue(key, callback) {
const sharedKey = sharedConfigKey(key);
if (!this.has(sharedKey)) {
this.add(sharedKey, initialConfig[key]);
}
this.sub(sharedKey, callback);