oc-client-browser
Version:
1,089 lines (1,082 loc) • 35.5 kB
JavaScript
/*! OpenComponents client v2.1.8 | (c) 2015-2025 OpenComponents community | https://github.com/opencomponents/oc-client-browser/tree/master/LICENSES */
(() => {
// <define:__EXTERNALS__>
var define_EXTERNALS_default = [];
// <define:__IMPORTS__>
var define_IMPORTS_default = {};
// <define:__REGISTERED_TEMPLATES_PLACEHOLDER__>
var define_REGISTERED_TEMPLATES_PLACEHOLDER_default = { "oc-template-handlebars": { externals: [{ global: "Handlebars", url: "https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.7/handlebars.runtime.min.js" }] }, "oc-template-jade": { externals: [{ global: "jade", url: "https://cdnjs.cloudflare.com/ajax/libs/jade/1.11.0/runtime.min.js" }] }, "oc-template-es6": { externals: [] } };
// src/loader.js
var LJS = class {
loaded = /* @__PURE__ */ new Set();
errors = /* @__PURE__ */ new Set();
parse(url) {
const [path, hash] = url.split("#");
const isModule = path.startsWith("module:");
const src = path.replace(/^module:/, "");
const [fallback, id] = (hash?.split("=") || []).reduce(
(a, p) => p.startsWith("=") ? [p.slice(1), a[1]] : [a[0], p],
[]
);
return { src, isModule, fallback, id };
}
async load(...args) {
for (const arg of args) {
Array.isArray(arg) ? await Promise.all(arg.map((a) => this._load(a))) : typeof arg === "function" ? await arg() : await this._load(arg);
}
return this;
}
async _load(url) {
if (this.loaded.has(url)) return;
try {
url.endsWith(".css") ? await this.css(url) : await this.js(url);
this.loaded.add(url);
} catch (err) {
for (const fn of this.errors) {
fn(url);
}
throw err;
}
}
js(url) {
const { src, isModule, fallback } = this.parse(url);
return new Promise((resolve, reject) => {
const script = document.createElement("script");
script.type = isModule ? "module" : "text/javascript";
script.src = src;
script.onload = resolve;
script.onerror = () => fallback ? this._load(fallback).then(resolve).catch(reject) : reject();
document.head.append(script);
});
}
css(url) {
const { src } = this.parse(url);
return new Promise((resolve, reject) => {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = src;
link.onload = resolve;
link.onerror = reject;
document.head.append(link);
});
}
onError(fn) {
this.errors.add(fn);
return this;
}
};
// node_modules/@rdevis/turbo-stream/dist/turbo-stream.mjs
var HOLE = -1;
var NAN = -2;
var NEGATIVE_INFINITY = -3;
var NEGATIVE_ZERO = -4;
var NULL = -5;
var POSITIVE_INFINITY = -6;
var UNDEFINED = -7;
var TYPE_BIGINT = "B";
var TYPE_DATE = "D";
var TYPE_ERROR = "E";
var TYPE_MAP = "M";
var TYPE_NULL_OBJECT = "N";
var TYPE_PROMISE = "P";
var TYPE_REGEXP = "R";
var TYPE_SET = "S";
var TYPE_SYMBOL = "Y";
var TYPE_URL = "U";
var TYPE_PREVIOUS_RESOLVED = "Z";
var Deferred = class {
promise;
resolve;
reject;
constructor() {
this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
}
};
function createLineSplittingTransform() {
const decoder = new TextDecoder();
let leftover = "";
return new TransformStream({
transform(chunk, controller) {
const str = decoder.decode(chunk, { stream: true });
const parts = (leftover + str).split("\n");
leftover = parts.pop() || "";
for (const part of parts) {
controller.enqueue(part);
}
},
flush(controller) {
if (leftover) {
controller.enqueue(leftover);
}
}
});
}
var objectProtoNames = Object.getOwnPropertyNames(Object.prototype).sort().join("\0");
var globalObj = typeof window !== "undefined" ? window : typeof globalThis !== "undefined" ? globalThis : void 0;
function unflatten(parsed) {
const { hydrated, values } = this;
if (typeof parsed === "number")
return hydrate.call(this, parsed);
if (!Array.isArray(parsed) || !parsed.length)
throw new SyntaxError();
const startIndex = values.length;
for (const value of parsed) {
values.push(value);
}
hydrated.length = values.length;
return hydrate.call(this, startIndex);
}
function hydrate(index) {
const { hydrated, values, deferred, plugins } = this;
let result;
const stack = [
[
index,
(v) => {
result = v;
}
]
];
let postRun = [];
while (stack.length > 0) {
const [index2, set] = stack.pop();
switch (index2) {
case UNDEFINED:
set(void 0);
continue;
case NULL:
set(null);
continue;
case NAN:
set(NaN);
continue;
case POSITIVE_INFINITY:
set(Infinity);
continue;
case NEGATIVE_INFINITY:
set(-Infinity);
continue;
case NEGATIVE_ZERO:
set(-0);
continue;
}
if (hydrated[index2]) {
set(hydrated[index2]);
continue;
}
const value = values[index2];
if (!value || typeof value !== "object") {
hydrated[index2] = value;
set(value);
continue;
}
if (Array.isArray(value)) {
if (typeof value[0] === "string") {
const [type, b, c] = value;
switch (type) {
case TYPE_DATE:
set(hydrated[index2] = new Date(b));
continue;
case TYPE_URL:
set(hydrated[index2] = new URL(b));
continue;
case TYPE_BIGINT:
set(hydrated[index2] = BigInt(b));
continue;
case TYPE_REGEXP:
set(hydrated[index2] = new RegExp(b, c));
continue;
case TYPE_SYMBOL:
set(hydrated[index2] = Symbol.for(b));
continue;
case TYPE_SET:
const newSet = /* @__PURE__ */ new Set();
hydrated[index2] = newSet;
for (let i = 1; i < value.length; i++)
stack.push([
value[i],
(v) => {
newSet.add(v);
}
]);
set(newSet);
continue;
case TYPE_MAP:
const map = /* @__PURE__ */ new Map();
hydrated[index2] = map;
for (let i = 1; i < value.length; i += 2) {
const r = [];
stack.push([
value[i + 1],
(v) => {
r[1] = v;
}
]);
stack.push([
value[i],
(k) => {
r[0] = k;
}
]);
postRun.push(() => {
map.set(r[0], r[1]);
});
}
set(map);
continue;
case TYPE_NULL_OBJECT:
const obj = /* @__PURE__ */ Object.create(null);
hydrated[index2] = obj;
for (const key of Object.keys(b).reverse()) {
const r = [];
stack.push([
b[key],
(v) => {
r[1] = v;
}
]);
stack.push([
Number(key.slice(1)),
(k) => {
r[0] = k;
}
]);
postRun.push(() => {
obj[r[0]] = r[1];
});
}
set(obj);
continue;
case TYPE_PROMISE:
if (hydrated[b]) {
set(hydrated[index2] = hydrated[b]);
} else {
const d = new Deferred();
deferred[b] = d;
set(hydrated[index2] = d.promise);
}
continue;
case TYPE_ERROR:
const [, message, errorType] = value;
let error = errorType && globalObj && globalObj[errorType] ? new globalObj[errorType](message) : new Error(message);
hydrated[index2] = error;
set(error);
continue;
case TYPE_PREVIOUS_RESOLVED:
set(hydrated[index2] = hydrated[b]);
continue;
default:
if (Array.isArray(plugins)) {
const r = [];
const vals = value.slice(1);
for (let i = 0; i < vals.length; i++) {
const v = vals[i];
stack.push([
v,
(v2) => {
r[i] = v2;
}
]);
}
postRun.push(() => {
for (const plugin of plugins) {
const result2 = plugin(value[0], ...r);
if (result2) {
set(hydrated[index2] = result2.value);
return;
}
}
throw new SyntaxError();
});
continue;
}
throw new SyntaxError();
}
} else {
const array = [];
hydrated[index2] = array;
for (let i = 0; i < value.length; i++) {
const n = value[i];
if (n !== HOLE) {
stack.push([
n,
(v) => {
array[i] = v;
}
]);
}
}
set(array);
continue;
}
} else {
const object = {};
hydrated[index2] = object;
for (const key of Object.keys(value).reverse()) {
const r = [];
stack.push([
value[key],
(v) => {
r[1] = v;
}
]);
stack.push([
Number(key.slice(1)),
(k) => {
r[0] = k;
}
]);
postRun.push(() => {
object[r[0]] = r[1];
});
}
set(object);
continue;
}
}
while (postRun.length > 0) {
postRun.pop()();
}
return result;
}
async function decode(readable, options) {
const { plugins } = options ?? {};
const done = new Deferred();
const reader = readable.pipeThrough(createLineSplittingTransform()).getReader();
const decoder = {
values: [],
hydrated: [],
deferred: {},
plugins
};
const decoded = await decodeInitial.call(decoder, reader);
let donePromise = done.promise;
if (decoded.done) {
done.resolve();
} else {
donePromise = decodeDeferred.call(decoder, reader).then(done.resolve).catch((reason) => {
for (const deferred of Object.values(decoder.deferred)) {
deferred.reject(reason);
}
done.reject(reason);
});
}
return {
done: donePromise.then(() => reader.closed),
value: decoded.value
};
}
async function decodeInitial(reader) {
const read = await reader.read();
if (!read.value) {
throw new SyntaxError();
}
let line;
try {
line = JSON.parse(read.value);
} catch (reason) {
throw new SyntaxError();
}
return {
done: read.done,
value: unflatten.call(this, line)
};
}
async function decodeDeferred(reader) {
let read = await reader.read();
while (!read.done) {
if (!read.value)
continue;
const line = read.value;
switch (line[0]) {
case TYPE_PROMISE: {
const colonIndex = line.indexOf(":");
const deferredId = Number(line.slice(1, colonIndex));
const deferred = this.deferred[deferredId];
if (!deferred) {
throw new Error(`Deferred ID ${deferredId} not found in stream`);
}
const lineData = line.slice(colonIndex + 1);
let jsonLine;
try {
jsonLine = JSON.parse(lineData);
} catch (reason) {
throw new SyntaxError();
}
const value = unflatten.call(this, jsonLine);
deferred.resolve(value);
break;
}
case TYPE_ERROR: {
const colonIndex = line.indexOf(":");
const deferredId = Number(line.slice(1, colonIndex));
const deferred = this.deferred[deferredId];
if (!deferred) {
throw new Error(`Deferred ID ${deferredId} not found in stream`);
}
const lineData = line.slice(colonIndex + 1);
let jsonLine;
try {
jsonLine = JSON.parse(lineData);
} catch (reason) {
throw new SyntaxError();
}
const value = unflatten.call(this, jsonLine);
deferred.reject(value);
break;
}
default:
throw new SyntaxError();
}
read = await reader.read();
}
}
// src/oc-client.js
function createErrorFromObject(o) {
const e = new Error(o.message || o);
if (o.stack) e.stack = o.stack;
return Object.assign(e, o.originalError, o);
}
function createOc(oc2) {
if (oc2.status) {
return oc2;
}
oc2.status = "loading";
oc2.conf = oc2.conf || {};
oc2.cmd = oc2.cmd || [];
oc2.renderedComponents = oc2.renderedComponents || {};
oc2.clientVersion = "2.1.8";
let isRequired = (name, value) => {
if (!value) {
throw name + " parameter is required";
}
};
let $document = document;
let $window = window;
let noop = () => {
};
let initialised = false;
let initialising = false;
let retries = {};
let isBool = (a) => typeof a == "boolean";
let timeout = setTimeout;
let ocCmd = oc2.cmd;
let ocConf = oc2.conf;
let renderedComponents = oc2.renderedComponents;
let dataRenderedAttribute = "data-rendered";
let dataRenderingAttribute = "data-rendering";
let nonce = $document.currentScript?.nonce;
let logError = (msg) => console.log(msg);
let logInfo = (msg) => ocConf.debug && console.log(msg);
let handleFetchResponse = (response) => {
if (response.headers.get("Content-Type") !== "x-text/stream")
return response.json();
return decode(response.body).then((decoded) => decoded.value);
};
let RETRY_INTERVAL = ocConf.retryInterval || Number(5e3);
let RETRY_LIMIT = ocConf.retryLimit || Number(30);
let DISABLE_LOADER = isBool(ocConf.disableLoader) ? ocConf.disableLoader : false;
let RETRY_SEND_NUMBER = ocConf.retrySendNumber || true;
let POLLING_INTERVAL = ocConf.pollingInterval || 500;
let OC_TAG = ocConf.tag || "oc-component";
let DISABLE_LIFECYCLES = isBool(ocConf.disableLifecycles) ? ocConf.disableLifecycles : false;
let MESSAGES_ERRORS_HREF_MISSING = "Href parameter missing";
let MESSAGES_ERRORS_RETRY_FAILED = "Failed to load % component " + RETRY_LIMIT + " times. Giving up";
let MESSAGES_ERRORS_LOADING_COMPILED_VIEW = "Error getting compiled view: %";
let MESSAGES_ERRORS_RENDERING = "Error rendering component: %, error: ";
let MESSAGES_ERRORS_RETRIEVING = "Failed to retrieve the component. Retrying in " + RETRY_INTERVAL / 1e3 + " seconds...";
let MESSAGES_ERRORS_VIEW_ENGINE_NOT_SUPPORTED = 'Error loading component: view engine "%" not supported';
let MESSAGES_LOADING_COMPONENT = ocConf.loadingMessage || "";
let MESSAGES_RENDERED = "Component '%' correctly rendered";
let MESSAGES_RETRIEVING = "Unrendered component found. Trying to retrieve it...";
let interpolate = (str, value) => str.replace("%", value);
let registeredTemplates = define_REGISTERED_TEMPLATES_PLACEHOLDER_default;
let externals = define_EXTERNALS_default;
let imports = define_IMPORTS_default;
let registerTemplates = (templates, overwrite) => {
templates = Array.isArray(templates) ? templates : [templates];
templates.map((template) => {
if (overwrite || !registeredTemplates[template.type]) {
registeredTemplates[template.type] = {
externals: template.externals
};
}
});
};
if (ocConf.templates) {
registerTemplates(ocConf.templates, true);
}
let retry = (component, cb, failedRetryCb) => {
if (retries[component] == void 0) {
retries[component] = RETRY_LIMIT;
}
if (retries[component] <= 0) {
failedRetryCb();
} else {
timeout(() => {
cb(RETRY_LIMIT - retries[component] + 1);
}, RETRY_INTERVAL);
retries[component]--;
}
};
let addParametersToHref = (href, parameters) => {
return href + (~href.indexOf("?") ? "&" : "?") + new URLSearchParams(parameters);
};
let reanimateScripts = (component) => {
for (let script of Array.from(component.querySelectorAll("script"))) {
let newScript = $document.createElement("script");
newScript.textContent = script.textContent;
for (let attribute of Array.from(script.attributes)) {
newScript.setAttribute(attribute.name, attribute.value);
}
if (nonce) {
newScript.setAttribute("nonce", nonce);
}
script.parentNode?.replaceChild(newScript, script);
}
};
let getHeaders = () => {
let globalHeaders = ocConf.globalHeaders;
return {
Accept: "application/vnd.oc.unrendered+json",
"Content-Type": "application/json",
...typeof globalHeaders == "function" ? globalHeaders() : globalHeaders
};
};
oc2.addStylesToHead = (styles) => {
let style = $document.createElement("style");
style.textContent = styles;
if (nonce) {
style.setAttribute("nonce", nonce);
}
$document.head.appendChild(style);
};
let loadAfterReady = () => {
oc2.ready(oc2.renderUnloadedComponents);
};
oc2.registerTemplates = (templates) => {
registerTemplates(templates);
loadAfterReady();
return registeredTemplates;
};
oc2.require = (nameSpace, url, callback) => {
if (!callback) {
callback = url;
url = nameSpace;
nameSpace = void 0;
}
if (typeof nameSpace == "string") {
nameSpace = [nameSpace];
}
let getObj = () => {
let base = $window;
if (nameSpace == void 0) {
return void 0;
}
for (let i in nameSpace) {
base = base[nameSpace[i]];
if (!base) {
return void 0;
}
}
return base;
};
let cbGetObj = () => {
callback(getObj());
};
if (!getObj()) {
ljs.load(url, cbGetObj);
} else {
cbGetObj();
}
};
let asyncRequireForEach = (toLoad, loaded, callback) => {
if (!callback) {
callback = loaded;
loaded = [];
}
if (!toLoad.length) {
callback(loaded);
} else {
let loading = toLoad[0];
oc2.require(loading.global, loading.url, (resolved) => {
asyncRequireForEach(toLoad.slice(1), loaded.concat(resolved), callback);
});
}
};
oc2.requireSeries = asyncRequireForEach;
let processHtml = (component, data, callback) => {
let setAttribute = component.setAttribute.bind(component);
let dataName = data.name;
let dataVersion = data.version;
setAttribute("id", data.id);
setAttribute(dataRenderedAttribute, true);
setAttribute(dataRenderingAttribute, false);
setAttribute("data-version", dataVersion);
setAttribute("data-id", data.ocId);
if (typeof data.html === "string") {
component.innerHTML = data.html;
}
reanimateScripts(component);
if (data.key) {
setAttribute("data-hash", data.key);
}
if (dataName) {
setAttribute("data-name", dataName);
renderedComponents[dataName] = { version: dataVersion };
if (data.baseUrl) {
renderedComponents[dataName].baseUrl = data.baseUrl;
}
data.element = component;
oc2.events.fire("oc:rendered", { ...data, id: data.ocId });
}
callback();
};
let getData = (options, cb) => {
cb = cb || noop;
let version = options.version, baseUrl = options.baseUrl, name = options.name;
isRequired("version", version);
isRequired("baseUrl", baseUrl);
isRequired("name", name);
if (options.action) {
baseUrl = `${baseUrl}~actions/${options.action}/${options.name}/${options.version || ""}`;
}
let parameters = { ...ocConf.globalParameters, ...options.parameters };
let data = options.action ? parameters : {
components: [
{
action: options.action,
name,
version,
parameters
}
]
};
let headers = getHeaders();
fetch(baseUrl, {
method: "POST",
headers,
body: JSON.stringify(data)
}).then(handleFetchResponse).then((apiResponse) => {
if (!options.action) {
let response = apiResponse[0].response;
let err = response.error ? createErrorFromObject(response.details || response.error) : null;
cb(err, response.data, apiResponse[0]);
} else {
let err = apiResponse.error ? createErrorFromObject(apiResponse.details || apiResponse.error) : null;
cb(err, apiResponse.data);
}
}).catch(cb);
};
oc2.getData = getData;
oc2.getAction = (options) => {
return new Promise((resolve, reject) => {
let name = options.component;
getData(
{
json: true,
name,
...renderedComponents[name],
...options
},
(err, data) => {
if (err) {
reject(err);
} else {
if (data.component) {
let props = data.component.props;
delete props._staticPath;
delete props._baseUrl;
delete props._componentName;
delete props._componentVersion;
resolve(props);
} else {
resolve();
}
}
}
);
});
};
oc2.build = (options) => {
isRequired("baseUrl", options.baseUrl);
isRequired("name", options.name);
let withFinalSlash = (s) => {
if (!s) return "";
return s.match(/\/$/) ? s : s + "/";
};
let href = withFinalSlash(options.baseUrl) + withFinalSlash(options.name) + withFinalSlash(options.version);
if (options.parameters) {
href += "?";
for (let [key, value] of Object.entries(options.parameters)) {
if (/[+&=]/.test(value)) {
value = encodeURIComponent(value);
}
href += key + "=" + value + "&";
}
href = href.slice(0, -1);
}
return "<" + OC_TAG + ' href="' + href + '"></' + OC_TAG + ">";
};
oc2.ready = (callback) => {
if (initialised) {
callback();
} else if (initialising) {
ocCmd.push(callback);
} else {
initialising = true;
let done = () => {
initialised = true;
initialising = false;
oc2.events = /* @__PURE__ */ (() => {
let listeners = {};
return {
fire(key, data) {
logInfo(`OC event fired: "${key}"`);
if (listeners[key]) {
for (let cb of listeners[key]) {
cb({ type: key }, data);
}
}
},
on(key, cb) {
if (!cb) {
throw new Error("Callback is required");
}
if (!listeners[key]) {
listeners[key] = [];
}
listeners[key].push(cb);
},
off(events, handler) {
if (typeof events === "string") {
events = [events];
}
for (let event of events) {
if (listeners[event]) {
if (handler) {
listeners[event] = listeners[event].filter(
(cb) => cb !== handler
);
} else {
delete listeners[event];
}
}
}
},
reset() {
listeners = {};
}
};
})();
if (Object.keys(imports).length > 0) {
$document.head.appendChild(
Object.assign($document.createElement("script"), {
type: "importmap",
textContent: JSON.stringify({ imports })
})
);
}
callback();
oc2.events.fire("oc:ready", oc2);
oc2.status = "ready";
ocCmd.map((cmd) => {
cmd(oc2);
});
oc2.cmd = {
push: (f) => f(oc2)
};
};
oc2.requireSeries(externals, done);
}
};
const renderOc = (template, apiResponse, callback) => {
const isEsm = !!apiResponse.data?.component?.esm;
if (isEsm) {
renderEsm(apiResponse.data, callback);
} else {
oc2.render(template, apiResponse.data, callback);
}
};
const renderEsm = async (data, callback) => {
try {
const { _staticPath, _componentName, _componentVersion } = data.component.props;
window.oc._esm = window.oc._esm || {};
window.oc._esm[`${_componentName}@${_componentVersion}`] = (args) => {
return _staticPath + "public/" + args;
};
const { mount } = await import(data.component.src);
let context = {};
if (data.component.development)
context.development = data.component.development;
mount(data.element, data.component.props, context);
callback(null);
} catch (error) {
console.error("Error rendering ESM component", error);
callback(error);
}
};
oc2.render = (compiledViewInfo, model, callback) => {
oc2.ready(() => {
if (model && model.__oc_emptyResponse == true) {
return callback(null, "");
}
let type = compiledViewInfo.type;
if (true) {
if (type == "jade" || type == "handlebars") {
type = "oc-template-" + type;
}
}
let template = registeredTemplates[type];
if (template) {
oc2.require(
["oc", "components", compiledViewInfo.key],
compiledViewInfo.src,
(compiledView) => {
if (!compiledView) {
callback(
interpolate(
MESSAGES_ERRORS_LOADING_COMPILED_VIEW,
compiledViewInfo.src
)
);
} else {
asyncRequireForEach(template.externals, () => {
try {
callback(
null,
type == "oc-template-handlebars" ? $window.Handlebars.template(compiledView, [])(model) : compiledView(model)
);
} catch (e) {
callback("" + e);
}
});
}
}
);
} else {
callback(
interpolate(
MESSAGES_ERRORS_VIEW_ENGINE_NOT_SUPPORTED,
compiledViewInfo.type
)
);
}
});
};
oc2.renderNestedComponent = (component, callback) => {
oc2.ready(() => {
component = component[0] || component;
let getAttribute = component.getAttribute.bind(component);
let setAttribute = component.setAttribute.bind(component);
let dataRendering = getAttribute(dataRenderingAttribute);
let dataRendered = getAttribute(dataRenderedAttribute);
let isRendering = dataRendering == "true";
let isRendered = dataRendered == "true";
if (isRendered) {
callback();
return;
}
if (isRendering) {
timeout(() => {
oc2.renderNestedComponent(component, callback);
}, POLLING_INTERVAL);
return;
}
logInfo(MESSAGES_RETRIEVING);
setAttribute(dataRenderingAttribute, true);
if (!DISABLE_LOADER) {
component.innerHTML = '<div class="oc-loading">' + MESSAGES_LOADING_COMPONENT + "</div>";
}
oc2.renderByHref(
{
href: getAttribute("href"),
id: getAttribute("id"),
element: component
},
(err, data) => {
if (err || !data) {
setAttribute(dataRenderingAttribute, false);
setAttribute(dataRenderedAttribute, false);
setAttribute("data-failed", true);
component.innerHTML = "";
oc2.events.fire("oc:failed", {
originalError: err,
data,
component
});
logError(err);
callback();
} else {
processHtml(component, data, callback);
}
}
);
});
};
oc2.renderByHref = (hrefOrOptions, retryNumberOrCallback, callback) => {
callback = callback || retryNumberOrCallback;
let ocId = Math.floor(Math.random() * 9999999999);
let retryNumber = hrefOrOptions.retryNumber || +retryNumberOrCallback || 0;
let href = hrefOrOptions.href || hrefOrOptions;
let id = hrefOrOptions.id || ocId;
let element = hrefOrOptions.element;
oc2.ready(() => {
if (!href) {
callback(MESSAGES_ERRORS_RENDERING + MESSAGES_ERRORS_HREF_MISSING);
} else {
fetch(
addParametersToHref(href, {
...ocConf.globalParameters,
...RETRY_SEND_NUMBER ? { __oc_Retry: retryNumber } : {}
}),
{
headers: getHeaders()
}
).then(handleFetchResponse).then((apiResponse) => {
if (apiResponse.error) {
throw apiResponse;
}
let template = apiResponse.template;
apiResponse.data.id = ocId;
apiResponse.data.element = element;
renderOc(template, apiResponse, (err, html) => {
if (err) {
callback(
interpolate(MESSAGES_ERRORS_RENDERING, apiResponse.href) + err
);
} else {
logInfo(interpolate(MESSAGES_RENDERED, template.src));
callback(null, {
id,
ocId,
html,
baseUrl: apiResponse.baseUrl,
key: template.key,
version: apiResponse.version,
name: apiResponse.name
});
}
});
}).catch((err) => {
if (err && err.status == 429) {
retries[href] = 0;
}
logError(MESSAGES_ERRORS_RETRIEVING);
window.oc.events.fire("oc:error", err);
retry(
href,
(requestNumber) => {
oc2.renderByHref(
{
href,
retryNumber: requestNumber,
id,
element
},
callback
);
},
() => {
callback(interpolate(MESSAGES_ERRORS_RETRY_FAILED, href));
}
);
});
}
});
};
oc2.renderUnloadedComponents = () => {
oc2.ready(() => {
let unloadedComponents = $document.querySelectorAll(
`${OC_TAG}:not([data-rendered="true"]):not([data-failed="true"])`
);
unloadedComponents.forEach((unloadedComponent, idx) => {
oc2.renderNestedComponent(unloadedComponent, () => {
if (idx == unloadedComponents.length - 1) {
oc2.renderUnloadedComponents();
}
});
});
});
};
oc2.load = (placeholder, href, callback) => {
oc2.ready(() => {
callback = callback || noop;
if (placeholder) {
placeholder = placeholder[0] || placeholder;
placeholder.innerHTML = "<" + OC_TAG + ' href="' + href + '" />';
let newComponent = placeholder.querySelector(OC_TAG);
oc2.renderNestedComponent(newComponent, () => {
callback(newComponent);
});
}
});
};
loadAfterReady();
if (window.customElements) {
window.customElements.define(
OC_TAG,
class extends HTMLElement {
#connected = false;
#manageLifecycle = !DISABLE_LIFECYCLES;
// biome-ignore lint/complexity/noUselessConstructor: <explanation>
constructor() {
super();
}
connectedCallback() {
this.#connected = true;
if (this.getAttribute("disable-lifecycle") == "true" || this.getAttribute("disable-lifecycle") == "") {
this.#manageLifecycle = false;
} else if (this.getAttribute("disable-lifecycle") == "false") {
this.#manageLifecycle = true;
}
if (this.#manageLifecycle) {
if (this.getAttribute("loading") === "lazy") {
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
observer.disconnect();
oc2.renderNestedComponent(this, () => {
});
break;
}
}
});
observer.observe(this);
} else {
oc2.renderNestedComponent(this, () => {
});
}
}
}
disconnectedCallback() {
if (this.#connected) {
this.#connected = false;
const id = this.getAttribute("id");
if (id) {
oc2.events.fire("oc:unrendered", {
element: this,
id
});
}
const shouldUnmount = this.#manageLifecycle && this.unmount && this.getAttribute("data-rendered") == "true";
if (shouldUnmount) {
this.unmount();
this.removeAttribute("data-rendered");
}
}
}
}
);
}
return oc2;
}
// src/index.js
var oc = window.oc || {};
var ljs2 = new LJS();
window.ljs = ljs2;
window.oc = createOc(oc);
})();