Current section

Files

Jump to
ckeditor5_phoenix dist index.mjs
Raw

dist/index.mjs

function j(r, t) {
if (!r || r.size !== t.size)
return !1;
for (const [e, a] of r)
if (!t.has(e) || t.get(e) !== a)
return !1;
return !0;
}
class W {
/**
* Map of registered items.
*/
items = /* @__PURE__ */ new Map();
/**
* Map of initialization errors for items that failed to register.
*/
initializationErrors = /* @__PURE__ */ new Map();
/**
* Map of pending callbacks waiting for items to be registered or fail.
*/
pendingCallbacks = /* @__PURE__ */ new Map();
/**
* Set of watchers that observe changes to the registry.
*/
watchers = /* @__PURE__ */ new Set();
/**
* Batch nesting depth. When > 0, watcher notifications are deferred.
*/
batchDepth = 0;
/**
* Snapshot of the last state dispatched to watchers, used for change detection.
*/
lastNotifiedItems = null;
lastNotifiedErrors = null;
/**
* Executes a function on an item.
* If the item is not yet registered, it will wait for it to be registered.
*
* @param id The ID of the item.
* @param onSuccess The function to execute.
* @param onError Optional error callback.
* @returns A promise that resolves with the result of the function.
*/
execute(t, e, a) {
const n = this.items.get(t), i = this.initializationErrors.get(t);
return i ? (a?.(i), Promise.reject(i)) : n ? Promise.resolve(e(n)) : new Promise((s, c) => {
const o = this.getPendingCallbacks(t);
o.success.push(async (u) => {
s(await e(u));
}), a ? o.error.push(a) : o.error.push(c);
});
}
/**
* Reactively binds a mount/unmount lifecycle to a single registry item.
*
* @param id The ID of the item to observe.
* @param onMount Function executed when the item mounts.
* @returns A function that stops observing and immediately runs any pending cleanup.
*/
mountEffect(t, e) {
let a, n, i = !1;
const s = this.watch((c) => {
const o = c.get(t);
if (o !== n && (a?.(), a = void 0, n = o, !!o))
try {
const u = e(o);
i ? (u?.(), s()) : a = u;
} catch (u) {
throw console.error(u), u;
}
});
return () => {
i = !0, n && (s(), a?.(), a = void 0);
};
}
/**
* Registers an item.
*
* @param id The ID of the item.
* @param item The item instance.
*/
register(t, e) {
this.batch(() => {
if (this.items.has(t))
throw new Error(`Item with ID "${t}" is already registered.`);
this.resetErrors(t), this.items.set(t, e);
const a = this.pendingCallbacks.get(t);
a && (a.success.forEach((n) => n(e)), this.pendingCallbacks.delete(t)), this.items.size === 1 && t !== null && this.register(null, e);
});
}
/**
* Registers an error for an item.
*
* @param id The ID of the item.
* @param error The error to register.
*/
error(t, e) {
this.batch(() => {
this.items.delete(t), this.initializationErrors.set(t, e);
const a = this.pendingCallbacks.get(t);
a && (a.error.forEach((n) => n(e)), this.pendingCallbacks.delete(t)), this.initializationErrors.size === 1 && !this.items.size && this.error(null, e);
});
}
/**
* Resets errors for an item.
*
* @param id The ID of the item.
*/
resetErrors(t) {
const { initializationErrors: e } = this;
e.has(null) && e.get(null) === e.get(t) && e.delete(null), e.delete(t);
}
/**
* Un-registers an item.
*
* @param id The ID of the item.
* @param resetPendingCallbacks If true resets pending callbacks.
*/
unregister(t, e = !0) {
this.batch(() => {
t && this.items.get(null) === this.items.get(t) && this.unregister(null, !1), this.items.delete(t), e && this.pendingCallbacks.delete(t), this.resetErrors(t);
});
}
/**
* Gets all registered items.
*
* @returns An array of all registered items.
*/
getItems() {
return Array.from(this.items.values());
}
/**
* Returns single registered item.
*
* @returns Registered item.
*/
getItem(t) {
return this.items.get(t);
}
/**
* Checks if an item with the given ID is registered.
*
* @param id The ID of the item.
* @returns `true` if the item is registered, `false` otherwise.
*/
hasItem(t) {
return this.items.has(t);
}
/**
* Gets a promise that resolves with the item instance for the given ID.
* If the item is not registered yet, it will wait for it to be registered.
*
* @param id The ID of the item.
* @returns A promise that resolves with the item instance.
*/
waitFor(t) {
return new Promise((e, a) => {
this.execute(t, e, a);
});
}
/**
* Destroys all registered items and clears the registry.
* This will call the `destroy` method on each item.
*/
async destroyAll() {
const t = Array.from(new Set(this.items.values())).map((e) => e.destroy());
this.items.clear(), this.pendingCallbacks.clear(), await Promise.all(t), this.flushWatchers();
}
/**
* Destroys all registered editors and removes all watchers.
*/
async reset() {
await this.destroyAll(), this.watchers.clear();
}
/**
* Executes a callback while deferring all watcher notifications.
* A single notification is fired synchronously after the callback returns,
* but only if the registry actually changed.
*
* Batches can be nested — watchers are notified only when the outermost
* batch completes.
*
* @param fn The callback to execute.
* @returns The return value of the callback.
*/
batch(t) {
this.batchDepth++;
try {
return t();
} finally {
this.batchDepth--, this.batchDepth === 0 && this.flushWatchers();
}
}
/**
* Registers a watcher that will be called whenever the registry changes.
*
* @param watcher The watcher function to register.
* @returns A function to unregister the watcher.
*/
watch(t) {
return this.watchers.add(t), t(
new Map(this.items),
new Map(this.initializationErrors)
), this.unwatch.bind(this, t);
}
/**
* Un-registers a watcher.
*
* @param watcher The watcher function to unregister.
*/
unwatch(t) {
this.watchers.delete(t);
}
/**
* Immediately dispatches the current state to all watchers if it changed.
*/
flushWatchers() {
j(this.lastNotifiedItems, this.items) && j(this.lastNotifiedErrors, this.initializationErrors) || (this.lastNotifiedItems = new Map(this.items), this.lastNotifiedErrors = new Map(this.initializationErrors), this.watchers.forEach((t) => t(
new Map(this.items),
new Map(this.initializationErrors)
)));
}
/**
* Gets or creates pending callbacks for a specific ID.
*
* @param id The ID of the item.
* @returns The pending callbacks structure.
*/
getPendingCallbacks(t) {
let e = this.pendingCallbacks.get(t);
return e || (e = { success: [], error: [] }, this.pendingCallbacks.set(t, e)), e;
}
}
function Z(r) {
return r.replace(/[-_\s]+(.)?/g, (t, e) => e ? e.toUpperCase() : "").replace(/^./, (t) => t.toLowerCase());
}
function A(r, t) {
let e = null;
return (...a) => {
e && clearTimeout(e), e = setTimeout(() => {
t(...a);
}, r);
};
}
function tt(r) {
if (Object.prototype.toString.call(r) !== "[object Object]")
return !1;
const t = Object.getPrototypeOf(r);
return t === Object.prototype || t === null;
}
function P(r) {
if (Array.isArray(r))
return r.map(P);
if (tt(r)) {
const t = /* @__PURE__ */ Object.create(null);
for (const [e, a] of Object.entries(r))
t[Z(e)] = P(a);
return t;
}
return r;
}
function et() {
const r = document.querySelector('meta[name="csrf-token"]');
if (r)
return r.getAttribute("content");
const t = document.cookie.match(/(?:^|; )_csrf_token=([^;]*)/);
return t ? decodeURIComponent(t[1]) : null;
}
class x {
/**
* The current state of the hook.
*/
state = "mounting";
/**
* The DOM element the hook is attached to.
* It includes an `instance` property to hold the hook instance.
*/
el;
/**
* Callbacks to run before the hook is destroyed.
*/
_beforeDestroyCallbacks = [];
/**
* Registers a callback to be called before the hook is destroyed.
* Callbacks are called in LIFO order (last registered, first called).
*/
onBeforeDestroy(t) {
this._beforeDestroyCallbacks.push(t);
}
/**
* Pushes an event from the client to the LiveView server process.
* @param _event The name of the event.
* @param _payload The data to send with the event.
* @param _callback An optional function to be called with the server's reply.
*/
pushEvent;
/**
* Pushes an event to another hook on the page.
* @param _selector The CSS selector of the target element with the hook.
* @param _event The name of the event.
* @param _payload The data to send with the event.
* @param _callback An optional function to be called with the reply.
*/
pushEventTo;
/**
* Registers a handler for an event pushed from the server.
* @param _event The name of the event to handle.
* @param _callback The function to execute when the event is received.
*/
handleEvent;
/**
* Called when the hook has been mounted to the DOM.
* This is the ideal place for initialization code.
*/
mounted() {
}
/**
* Called when the element has been removed from the DOM.
* Perfect for cleanup tasks.
*/
destroyed() {
}
/**
* Called when the element has been updated by a LiveView patch.
*/
updated() {
}
/**
* Checks if the hook is in the process of being destroyed.
*/
isBeingDestroyed() {
return this.state === "destroyed" || this.state === "destroying";
}
/**
* Runs all registered before-destroy callbacks and clears the list.
* Called internally by makeHook before destroyed().
*/
_runBeforeDestroyCallbacks() {
for (const t of this._beforeDestroyCallbacks.reverse())
t();
this._beforeDestroyCallbacks = [];
}
}
function D(r) {
return {
/**
* The mounted lifecycle callback for the LiveView hook object.
* It creates an instance of the user-defined hook class and sets up the necessary properties and methods.
*/
async mounted() {
const t = new r();
this.el.instance = t, t.el = this.el, t.pushEvent = (a, n, i) => this.pushEvent?.(a, n, i), t.pushEventTo = (a, n, i, s) => this.pushEventTo?.(a, n, i, s), t.handleEvent = (a, n) => this.handleEvent?.(a, n), t.state = "mounting";
const e = await t.mounted?.();
return t.state = "mounted", e;
},
/**
* The beforeUpdate lifecycle callback that delegates to the hook instance.
*/
beforeUpdate() {
this.el.instance.beforeUpdate?.();
},
/**
* The destroyed lifecycle callback that delegates to the hook instance.
*/
async destroyed() {
const { instance: t } = this.el;
t.state = "destroying", t._runBeforeDestroyCallbacks(), await t.destroyed?.(), t.state = "destroyed";
},
/**
* The disconnected lifecycle callback that delegates to the hook instance.
*/
disconnected() {
this.el.instance.disconnected?.();
},
/**
* The reconnected lifecycle callback that delegates to the hook instance.
*/
reconnected() {
this.el.instance.reconnected?.();
},
/**
* The updated lifecycle callback that delegates to the hook instance.
*/
updated() {
return this.el.instance.updated?.();
}
};
}
function L(r) {
return Object.keys(r).length === 0 && r.constructor === Object;
}
function rt(r) {
return r == null;
}
function at(r, t) {
const e = Object.entries(r).map(([a, n]) => [a, t(n, a)]);
return Object.fromEntries(e);
}
function H(r) {
if (r === null)
return null;
const t = Number.parseInt(r, 10);
return Number.isNaN(t) ? null : t;
}
function nt(r) {
return r == null || r.trim() === "" ? null : JSON.parse(r);
}
function it(r, t) {
if (r === t)
return !0;
const e = Object.keys(r), a = Object.keys(t);
if (e.length !== a.length)
return !1;
for (const n of e)
if (r[n] !== t[n] || !Object.prototype.hasOwnProperty.call(t, n))
return !1;
return !0;
}
function ot() {
return Math.random().toString(36).substring(2);
}
function st(r, {
timeOutAfter: t = 500,
retryAfter: e = 100
} = {}) {
return new Promise((a, n) => {
const i = Date.now();
let s = null;
const c = setTimeout(() => {
n(s ?? new Error("Timeout"));
}, t), o = async () => {
try {
const u = await r();
clearTimeout(c), a(u);
} catch (u) {
s = u, Date.now() - i > t ? n(u) : setTimeout(o, e);
}
};
o();
});
}
function ct(r, t, e) {
const a = !r.editorName || r.editorName === "ClassicEditor", n = /* @__PURE__ */ new Set([
...Object.keys(t),
...Object.keys(e.roots ?? {})
]), i = Array.from(n).reduce((c, o) => ({
...c,
[o]: {
/* v8 ignore next 1 */
...e.roots?.[o],
...o === "main" ? e.root : {},
/* v8 ignore start */
...o in t ? {
initialData: t[o].initialValue,
modelElement: t[o].modelElement || "$root",
...!a && {
element: t[o].content
}
} : {}
/* v8 ignore end */
}
}), { ...e.roots || {} }), s = {
...e,
roots: i,
...a && {
attachTo: t.main?.content
}
};
return delete s.root, s;
}
function ut(r) {
const t = [
r.ui?.element,
r.ui?.view?.toolbar?.element,
r.ui?.view?.menuBarView?.element
].filter(Boolean);
for (const i of t)
n(i);
const e = r.ui?.view?.body?._bodyCollectionContainer;
e?.isConnected && n(e);
const a = r.editing?.view;
if (a)
for (const i of a.domRoots.values())
i instanceof HTMLElement && (i.removeAttribute("contenteditable"), i.removeAttribute("role"), i.removeAttribute("aria-label"), i.removeAttribute("aria-multiline"), i.removeAttribute("spellcheck"), i.classList.remove(
"ck",
"ck-content",
"ck-editor__editable",
"ck-rounded-corners",
"ck-editor__editable_inline",
"ck-blurred",
"ck-focused"
), n(i));
function n(i) {
i.hasAttribute("data-cke-controlled") ? i.innerHTML = "" : i.remove();
}
}
const R = /* @__PURE__ */ Symbol.for("context-editor-watchdog");
async function lt({ context: r, creator: t, config: e }) {
const a = ot();
await r.add({
creator: t.create.bind(t),
id: a,
type: "editor",
config: e
});
const n = r.getItem(a), i = {
state: "available",
editorContextId: a,
context: r
};
n[R] = i;
const s = r.destroy.bind(r);
return r.destroy = async () => (i.state = "unavailable", s()), {
...i,
editor: n
};
}
function dt(r) {
return R in r ? r[R] : null;
}
function q(r) {
return "addEditable" in r.ui;
}
function N(r) {
return ["inline", "classic", "balloon", "decoupled"].includes(r);
}
async function mt(r) {
const t = await import("ckeditor5"), a = {
inline: t.InlineEditor,
balloon: t.BalloonEditor,
classic: t.ClassicEditor,
decoupled: t.DecoupledEditor,
multiroot: t.MultiRootEditor
}[r];
if (!a)
throw new Error(`Unsupported editor type: ${r}`);
return a;
}
class U {
static the = new U();
/**
* Map of registered custom plugins.
*/
plugins = /* @__PURE__ */ new Map();
/**
* Private constructor to enforce singleton pattern.
*/
constructor() {
}
/**
* Registers a custom plugin for the CKEditor.
*
* @param name The name of the plugin.
* @param reader The plugin reader function that returns the plugin constructor.
* @returns A function to unregister the plugin.
*/
register(t, e) {
if (this.plugins.has(t))
throw new Error(`Plugin with name "${t}" is already registered.`);
return this.plugins.set(t, e), this.unregister.bind(this, t);
}
/**
* Removes a custom plugin by its name.
*
* @param name The name of the plugin to unregister.
* @throws Will throw an error if the plugin is not registered.
*/
unregister(t) {
if (!this.plugins.has(t))
throw new Error(`Plugin with name "${t}" is not registered.`);
this.plugins.delete(t);
}
/**
* Removes all custom editor plugins.
* This is useful for cleanup in tests or when reloading plugins.
*/
unregisterAll() {
this.plugins.clear();
}
/**
* Retrieves a custom plugin by its name.
*
* @param name The name of the plugin.
* @returns The plugin constructor or undefined if not found.
*/
async get(t) {
return this.plugins.get(t)?.();
}
/**
* Checks if a plugin with the given name is registered.
*
* @param name The name of the plugin.
* @returns `true` if the plugin is registered, `false` otherwise.
*/
has(t) {
return this.plugins.has(t);
}
}
async function K(r) {
const t = await import("ckeditor5");
let e = null;
const a = r.map(async (n) => {
const i = await U.the.get(n);
if (i)
return i;
const { [n]: s } = t;
if (s)
return s;
if (!e)
try {
e = await import("ckeditor5-premium-features");
} catch (o) {
console.error(`Failed to load premium package: ${o}`);
}
const { [n]: c } = e || {};
if (c)
return c;
throw new Error(`Plugin "${n}" not found in base or premium packages.`);
});
return {
loadedPlugins: await Promise.all(a),
hasPremium: !!e
};
}
async function Y(r, t) {
const e = [r.ui, r.content];
return await Promise.all(
[
B("ckeditor5", e),
/* v8 ignore next */
t && B("ckeditor5-premium-features", e)
].filter((n) => !!n)
).then((n) => n.flat());
}
async function B(r, t) {
return await Promise.all(
t.filter((e) => e !== "en").map(async (e) => {
const a = await ht(r, e);
return a?.default ?? a;
}).filter(Boolean)
);
}
async function ht(r, t) {
try {
if (r === "ckeditor5")
switch (t) {
case "af":
return await import("ckeditor5/translations/af.js");
case "ar":
return await import("ckeditor5/translations/ar.js");
case "ast":
return await import("ckeditor5/translations/ast.js");
case "az":
return await import("ckeditor5/translations/az.js");
case "bg":
return await import("ckeditor5/translations/bg.js");
case "bn":
return await import("ckeditor5/translations/bn.js");
case "bs":
return await import("ckeditor5/translations/bs.js");
case "ca":
return await import("ckeditor5/translations/ca.js");
case "cs":
return await import("ckeditor5/translations/cs.js");
case "da":
return await import("ckeditor5/translations/da.js");
case "de":
return await import("ckeditor5/translations/de.js");
case "de-ch":
return await import("ckeditor5/translations/de-ch.js");
case "el":
return await import("ckeditor5/translations/el.js");
case "en":
return await import("ckeditor5/translations/en.js");
case "en-au":
return await import("ckeditor5/translations/en-au.js");
case "en-gb":
return await import("ckeditor5/translations/en-gb.js");
case "eo":
return await import("ckeditor5/translations/eo.js");
case "es":
return await import("ckeditor5/translations/es.js");
case "es-co":
return await import("ckeditor5/translations/es-co.js");
case "et":
return await import("ckeditor5/translations/et.js");
case "eu":
return await import("ckeditor5/translations/eu.js");
case "fa":
return await import("ckeditor5/translations/fa.js");
case "fi":
return await import("ckeditor5/translations/fi.js");
case "fr":
return await import("ckeditor5/translations/fr.js");
case "gl":
return await import("ckeditor5/translations/gl.js");
case "gu":
return await import("ckeditor5/translations/gu.js");
case "he":
return await import("ckeditor5/translations/he.js");
case "hi":
return await import("ckeditor5/translations/hi.js");
case "hr":
return await import("ckeditor5/translations/hr.js");
case "hu":
return await import("ckeditor5/translations/hu.js");
case "hy":
return await import("ckeditor5/translations/hy.js");
case "id":
return await import("ckeditor5/translations/id.js");
case "it":
return await import("ckeditor5/translations/it.js");
case "ja":
return await import("ckeditor5/translations/ja.js");
case "jv":
return await import("ckeditor5/translations/jv.js");
case "kk":
return await import("ckeditor5/translations/kk.js");
case "km":
return await import("ckeditor5/translations/km.js");
case "kn":
return await import("ckeditor5/translations/kn.js");
case "ko":
return await import("ckeditor5/translations/ko.js");
case "ku":
return await import("ckeditor5/translations/ku.js");
case "lt":
return await import("ckeditor5/translations/lt.js");
case "lv":
return await import("ckeditor5/translations/lv.js");
case "ms":
return await import("ckeditor5/translations/ms.js");
case "nb":
return await import("ckeditor5/translations/nb.js");
case "ne":
return await import("ckeditor5/translations/ne.js");
case "nl":
return await import("ckeditor5/translations/nl.js");
case "no":
return await import("ckeditor5/translations/no.js");
case "oc":
return await import("ckeditor5/translations/oc.js");
case "pl":
return await import("ckeditor5/translations/pl.js");
case "pt":
return await import("ckeditor5/translations/pt.js");
case "pt-br":
return await import("ckeditor5/translations/pt-br.js");
case "ro":
return await import("ckeditor5/translations/ro.js");
case "ru":
return await import("ckeditor5/translations/ru.js");
case "si":
return await import("ckeditor5/translations/si.js");
case "sk":
return await import("ckeditor5/translations/sk.js");
case "sl":
return await import("ckeditor5/translations/sl.js");
case "sq":
return await import("ckeditor5/translations/sq.js");
case "sr":
return await import("ckeditor5/translations/sr.js");
case "sr-latn":
return await import("ckeditor5/translations/sr-latn.js");
case "sv":
return await import("ckeditor5/translations/sv.js");
case "th":
return await import("ckeditor5/translations/th.js");
case "tk":
return await import("ckeditor5/translations/tk.js");
case "tr":
return await import("ckeditor5/translations/tr.js");
case "tt":
return await import("ckeditor5/translations/tt.js");
case "ug":
return await import("ckeditor5/translations/ug.js");
case "uk":
return await import("ckeditor5/translations/uk.js");
case "ur":
return await import("ckeditor5/translations/ur.js");
case "uz":
return await import("ckeditor5/translations/uz.js");
case "vi":
return await import("ckeditor5/translations/vi.js");
case "zh":
return await import("ckeditor5/translations/zh.js");
case "zh-cn":
return await import("ckeditor5/translations/zh-cn.js");
default:
return console.warn(`Language ${t} not found in ckeditor5 translations`), null;
}
else
switch (t) {
case "af":
return await import("ckeditor5-premium-features/translations/af.js");
case "ar":
return await import("ckeditor5-premium-features/translations/ar.js");
case "ast":
return await import("ckeditor5-premium-features/translations/ast.js");
case "az":
return await import("ckeditor5-premium-features/translations/az.js");
case "bg":
return await import("ckeditor5-premium-features/translations/bg.js");
case "bn":
return await import("ckeditor5-premium-features/translations/bn.js");
case "bs":
return await import("ckeditor5-premium-features/translations/bs.js");
case "ca":
return await import("ckeditor5-premium-features/translations/ca.js");
case "cs":
return await import("ckeditor5-premium-features/translations/cs.js");
case "da":
return await import("ckeditor5-premium-features/translations/da.js");
case "de":
return await import("ckeditor5-premium-features/translations/de.js");
case "de-ch":
return await import("ckeditor5-premium-features/translations/de-ch.js");
case "el":
return await import("ckeditor5-premium-features/translations/el.js");
case "en":
return await import("ckeditor5-premium-features/translations/en.js");
case "en-au":
return await import("ckeditor5-premium-features/translations/en-au.js");
case "en-gb":
return await import("ckeditor5-premium-features/translations/en-gb.js");
case "eo":
return await import("ckeditor5-premium-features/translations/eo.js");
case "es":
return await import("ckeditor5-premium-features/translations/es.js");
case "es-co":
return await import("ckeditor5-premium-features/translations/es-co.js");
case "et":
return await import("ckeditor5-premium-features/translations/et.js");
case "eu":
return await import("ckeditor5-premium-features/translations/eu.js");
case "fa":
return await import("ckeditor5-premium-features/translations/fa.js");
case "fi":
return await import("ckeditor5-premium-features/translations/fi.js");
case "fr":
return await import("ckeditor5-premium-features/translations/fr.js");
case "gl":
return await import("ckeditor5-premium-features/translations/gl.js");
case "gu":
return await import("ckeditor5-premium-features/translations/gu.js");
case "he":
return await import("ckeditor5-premium-features/translations/he.js");
case "hi":
return await import("ckeditor5-premium-features/translations/hi.js");
case "hr":
return await import("ckeditor5-premium-features/translations/hr.js");
case "hu":
return await import("ckeditor5-premium-features/translations/hu.js");
case "hy":
return await import("ckeditor5-premium-features/translations/hy.js");
case "id":
return await import("ckeditor5-premium-features/translations/id.js");
case "it":
return await import("ckeditor5-premium-features/translations/it.js");
case "ja":
return await import("ckeditor5-premium-features/translations/ja.js");
case "jv":
return await import("ckeditor5-premium-features/translations/jv.js");
case "kk":
return await import("ckeditor5-premium-features/translations/kk.js");
case "km":
return await import("ckeditor5-premium-features/translations/km.js");
case "kn":
return await import("ckeditor5-premium-features/translations/kn.js");
case "ko":
return await import("ckeditor5-premium-features/translations/ko.js");
case "ku":
return await import("ckeditor5-premium-features/translations/ku.js");
case "lt":
return await import("ckeditor5-premium-features/translations/lt.js");
case "lv":
return await import("ckeditor5-premium-features/translations/lv.js");
case "ms":
return await import("ckeditor5-premium-features/translations/ms.js");
case "nb":
return await import("ckeditor5-premium-features/translations/nb.js");
case "ne":
return await import("ckeditor5-premium-features/translations/ne.js");
case "nl":
return await import("ckeditor5-premium-features/translations/nl.js");
case "no":
return await import("ckeditor5-premium-features/translations/no.js");
case "oc":
return await import("ckeditor5-premium-features/translations/oc.js");
case "pl":
return await import("ckeditor5-premium-features/translations/pl.js");
case "pt":
return await import("ckeditor5-premium-features/translations/pt.js");
case "pt-br":
return await import("ckeditor5-premium-features/translations/pt-br.js");
case "ro":
return await import("ckeditor5-premium-features/translations/ro.js");
case "ru":
return await import("ckeditor5-premium-features/translations/ru.js");
case "si":
return await import("ckeditor5-premium-features/translations/si.js");
case "sk":
return await import("ckeditor5-premium-features/translations/sk.js");
case "sl":
return await import("ckeditor5-premium-features/translations/sl.js");
case "sq":
return await import("ckeditor5-premium-features/translations/sq.js");
case "sr":
return await import("ckeditor5-premium-features/translations/sr.js");
case "sr-latn":
return await import("ckeditor5-premium-features/translations/sr-latn.js");
case "sv":
return await import("ckeditor5-premium-features/translations/sv.js");
case "th":
return await import("ckeditor5-premium-features/translations/th.js");
case "tk":
return await import("ckeditor5-premium-features/translations/tk.js");
case "tr":
return await import("ckeditor5-premium-features/translations/tr.js");
case "tt":
return await import("ckeditor5-premium-features/translations/tt.js");
case "ug":
return await import("ckeditor5-premium-features/translations/ug.js");
case "uk":
return await import("ckeditor5-premium-features/translations/uk.js");
case "ur":
return await import("ckeditor5-premium-features/translations/ur.js");
case "uz":
return await import("ckeditor5-premium-features/translations/uz.js");
case "vi":
return await import("ckeditor5-premium-features/translations/vi.js");
case "zh":
return await import("ckeditor5-premium-features/translations/zh.js");
case "zh-cn":
return await import("ckeditor5-premium-features/translations/zh-cn.js");
default:
return console.warn(`Language ${t} not found in premium translations`), await import("ckeditor5-premium-features/translations/en.js");
}
} catch (e) {
return console.error(`Failed to load translation for ${r}/${t}:`, e), null;
}
}
function J(r) {
return at(r, (t) => ({
dictionary: t
}));
}
function G(r) {
const t = document.querySelectorAll(
[
`[data-cke-editor-id="${r}"][data-cke-editable-root-name]`,
"[data-cke-editable-root-name]:not([data-cke-editor-id])"
].join(", ")
), e = Array.from(t).reduce((c, o) => {
const u = o.getAttribute("data-cke-editable-root-name"), d = o.getAttribute("data-cke-editable-root-model-element-name") || null, l = o.getAttribute("data-cke-editable-initial-value") || "", p = o.querySelector("[data-cke-editable-content]");
return !u || !p ? c : {
...c,
[u]: {
content: p,
initialValue: l,
modelElement: d
}
};
}, /* @__PURE__ */ Object.create(null)), a = document.querySelector(`[phx-hook="CKEditor5"][id="${r}"]`);
if (!a)
return e;
const n = a.getAttribute("data-cke-root-model-element-name"), i = a.getAttribute("data-cke-initial-value") || "";
if (e.main)
return {
...e,
main: {
...e.main,
modelElement: e.main.modelElement || n,
initialValue: e.main.initialValue || i
}
};
const s = a.querySelector(`#${r}_editor `);
return s ? {
...e,
main: {
content: s,
initialValue: i,
modelElement: a.getAttribute("data-cke-root-model-element-name") || "$root"
}
} : e;
}
const F = ["inline", "classic", "balloon", "decoupled", "multiroot"];
function pt(r) {
const t = r.getAttribute("data-cke-preset");
if (!t)
throw new Error('CKEditor5 hook requires a "cke-preset" attribute on the element.');
const { type: e, config: a, license: n, watchdog: i, ...s } = JSON.parse(t);
if (!e || !a || !n)
throw new Error('CKEditor5 hook configuration must include "editor", "config", and "license" properties.');
if (!F.includes(e))
throw new Error(`Invalid editor type: ${e}. Must be one of: ${F.join(", ")}.`);
return {
type: e,
license: n,
watchdog: i,
config: P(a),
customTranslations: s.customTranslations || s.custom_translations
};
}
function T(r) {
if (!r || typeof r != "object")
return r;
if (Array.isArray(r))
return r.map((a) => T(a));
const t = r;
if (t.$element && typeof t.$element == "string") {
const a = document.querySelector(t.$element);
return a || console.warn(`Element not found for selector: ${t.$element}`), a || null;
}
const e = /* @__PURE__ */ Object.create(null);
for (const [a, n] of Object.entries(r))
e[a] = T(n);
return e;
}
function I(r, t, e) {
if (!e || typeof e != "object")
return e;
if (Array.isArray(e))
return e.map((i) => I(r, t, i));
const a = e;
if (a.$translation && typeof a.$translation == "string") {
const i = a.$translation, s = ft(r, i, t);
return s === void 0 && console.warn(`Translation not found for key: ${i}`), s !== void 0 ? s : null;
}
const n = /* @__PURE__ */ Object.create(null);
for (const [i, s] of Object.entries(e))
n[i] = I(r, t, s);
return n;
}
function ft(r, t, e) {
for (const a of r) {
const n = a[e];
if (n?.dictionary && t in n.dictionary)
return n.dictionary[t];
}
}
function wt(r, t) {
const { editing: e } = r;
e.view.change((a) => {
a.setStyle("height", `${t}px`, e.view.document.getRoot());
});
}
const V = /* @__PURE__ */ Symbol.for("elixir-editor-watchdog");
async function gt(r, t) {
const { EditorWatchdog: e } = await import("ckeditor5"), a = new e(null, t ?? {
crashNumberLimit: 10,
minimumNonErrorTimePeriod: 5e3
});
return a.setCreator(async () => {
const n = await r();
return n[V] = a, n;
}), a;
}
function bt(r) {
return V in r ? r[V] : null;
}
class b extends W {
static the = new b();
}
function yt(r) {
const t = r.getAttribute("data-cke-context");
if (!t)
throw new Error('CKEditor5 hook requires a "data-cke-context" attribute on the element.');
const { config: e, ...a } = JSON.parse(t);
return {
config: P(e),
customTranslations: a.customTranslations || a.custom_translations,
watchdogConfig: a.watchdogConfig || a.watchdog_config
};
}
class kt extends x {
/**
* The promise that resolves to the context instance.
*/
contextPromise = null;
/**
* Attributes for the context instance.
*/
get attrs() {
const t = (a) => this.el.getAttribute(a) || null, e = {
id: this.el.id,
config: yt(this.el),
language: {
ui: t("data-cke-language") || "en",
content: t("data-cke-content-language") || "en"
}
};
return Object.defineProperty(this, "attrs", {
value: e,
writable: !1,
configurable: !1,
enumerable: !0
}), e;
}
/**
* Mounts the context component.
*/
async mounted() {
const { id: t, language: e } = this.attrs, { customTranslations: a, watchdogConfig: n, config: { plugins: i, ...s } } = this.attrs.config, { loadedPlugins: c, hasPremium: o } = await K(i ?? []), d = [
...await Y(e, o),
J(a?.dictionary || {})
].filter((m) => !L(m));
let l = T(s);
l = I([...d].reverse(), e.ui, l), this.contextPromise = (async () => {
const { ContextWatchdog: m, Context: k } = await import("ckeditor5"), g = new m(k, {
crashNumberLimit: 10,
...n
});
return await g.create({
...l,
language: e,
plugins: c,
...d.length && {
translations: d
}
}), g.on("itemError", (...E) => {
console.error("Context item error:", ...E);
}), g;
})();
const p = await this.contextPromise;
this.isBeingDestroyed() || b.the.register(t, p);
}
/**
* Destroys the context component. Unmounts root from the editor.
*/
async destroyed() {
const { id: t } = this.attrs;
this.el.style.display = "none";
try {
await (await this.contextPromise)?.destroy();
} finally {
this.contextPromise = null, b.the.hasItem(t) && b.the.unregister(t);
}
}
}
function Et(r) {
return r.hasAttribute("data-cke-context");
}
function vt(r) {
let t = r;
for (; t; ) {
if (Et(t))
return t;
t = t.parentElement;
}
return null;
}
async function Ct(r) {
const t = vt(r);
return t ? b.the.waitFor(t.id) : null;
}
const At = D(kt);
function Pt(r, t) {
const e = /* @__PURE__ */ new Set();
return (a) => {
let n = !1;
return r.model.enqueueChange({ isUndoable: !1 }, (i) => {
const s = r.model.document.getRoot(t);
if (s) {
for (const c of e)
a && c in a || (i.removeAttribute(c, s), e.delete(c), n = !0);
for (const [c, o] of Object.entries(a ?? {}))
i.setAttribute(c, o, s), e.add(c), n = !0;
}
}), n;
};
}
async function Tt() {
const { Plugin: r, FileRepository: t } = await import("ckeditor5");
return class extends r {
/**
* The name of the plugin.
*/
static get pluginName() {
return "PhoenixUploadAdapter";
}
static get requires() {
return [t];
}
/**
* Initializes the plugin.
*/
init() {
const { editor: a } = this, { plugins: n, config: i } = a, s = i.get("phoenixUpload.url");
if (!s || n.has("SimpleUploadAdapter") || n.has("Base64UploadAdapter") || n.has("CKFinderUploadAdapter"))
return;
const c = n.get(t);
c.createUploadAdapter = (o) => new It(o, s);
}
};
}
class It {
loader;
uploadUrl;
abortController = null;
constructor(t, e) {
this.loader = t, this.uploadUrl = e;
}
/**
* Starts the upload process.
*/
async upload() {
const t = await this.loader.file;
this.abortController = new AbortController();
const e = new FormData();
e.append("file", t), t.size && (this.loader.uploadTotal = t.size, this.loader.uploaded = 0);
const a = {}, n = et();
n && (a["X-CSRF-Token"] = n);
try {
const i = await fetch(this.uploadUrl, {
method: "POST",
headers: a,
body: e,
signal: this.abortController.signal
});
if (!i.ok) {
let c = "Couldn't upload file!";
try {
const o = await i.json();
o?.error?.message && (c = o.error.message);
} catch {
}
throw new Error(c);
}
return this.loader.uploaded = this.loader.uploadTotal, {
default: (await i.json()).url
};
} catch (i) {
throw i.name === "AbortError" ? i : i.message || "Couldn't upload file!";
}
}
/**
* Aborts the upload process.
*/
/* v8 ignore next 4 */
abort() {
this.abortController?.abort(), this.abortController = null;
}
}
async function xt({
editorId: r,
saveDebounceMs: t
}) {
const { Plugin: e } = await import("ckeditor5");
return class extends e {
/**
* The input element to synchronize with.
*/
input = null;
/**
* The form element reference for cleanup.
*/
form = null;
/**
* The name of the plugin.
*/
static get pluginName() {
return "SyncEditorWithInput";
}
/**
* Initializes the plugin.
*/
afterInit() {
const { editor: n } = this;
this.input = document.getElementById(`${r}_input`), this.input && (n.model.document.on("change:data", A(t, () => this.sync())), n.once("ready", this.sync), this.form = this.input.closest("form"), this.form?.addEventListener("submit", this.sync));
}
/**
* Synchronizes the editor's content with the input field.
*/
sync = () => {
const n = this.editor.getData();
this.input.value = n, this.input.dispatchEvent(new Event("input", { bubbles: !0 }));
};
/**
* Destroys the plugin.
*/
destroy() {
this.form && this.form.removeEventListener("submit", this.sync), this.input = null, this.form = null;
}
};
}
const $ = /* @__PURE__ */ Symbol("suppress-phoenix-sync");
async function Dt(r) {
const { Plugin: t } = await import("ckeditor5"), { editorId: e, saveDebounceMs: a, events: n, pushEvent: i, handleEvent: s } = r;
return class extends t {
/**
* The name of the plugin.
*/
static get pluginName() {
return "SyncEditorWithPhoenix";
}
/**
* Initializes the plugin.
*/
init() {
const { editor: o } = this;
n.change && this.setupTypingContentPush(), n.blur && this.setupEventPush("blur"), n.focus && this.setupEventPush("focus"), n.ready && this.editor.once("ready", () => {
i("ckeditor5:ready", {
editorId: e,
data: S(o)
});
}), s("ckeditor5:set-data", ({ editorId: u, data: d }) => {
(rt(u) || u === e) && o.setData(d);
});
}
/**
* Setups the content push event for the editor.
*/
setupTypingContentPush() {
const { editor: o } = this;
let u = null, d = !1;
const l = () => {
if (d)
return;
const m = S(o);
(!u || !it(u, m)) && (i(
"ckeditor5:change",
{
editorId: e,
data: m
}
), u = m);
}, p = A(a, l);
o.model.document.on("change:data", A(10, (m) => {
if (Ot(m)) {
u = null;
return;
}
o.ui.focusTracker.isFocused ? p() : l();
})), o.once("ready", l), o.once("destroy", () => {
d = !0;
});
}
/**
* Setups the event push for the editor.
*/
setupEventPush(o) {
const { editor: u } = this, d = () => {
const { isFocused: l } = u.ui.focusTracker;
(l ? "focus" : "blur") === o && i(
`ckeditor5:${o}`,
{
editorId: e,
data: S(u)
}
);
};
u.ui.focusTracker.on("change:isFocused", d);
}
};
}
function S(r) {
return r.model.document.getRootNames().reduce((e, a) => (e[a] = r.getData({ rootName: a }), e), /* @__PURE__ */ Object.create(null));
}
function Ot(r) {
const t = r[$];
return delete r[$], !!t;
}
function Nt(r) {
let t = !1;
const e = (a) => {
t || (a[$] = !0);
};
return r.model.document.once("change:data", e, { priority: "highest" }), () => {
t = !0, r.model.document.off("change:data", e);
};
}
class X {
/**
* The DOM element being observed for attribute changes.
*/
el;
/**
* The name of the specific root in a multi-root editor setup.
*/
rootName;
/**
* The name of the HTML attribute storing the value.
*/
valueAttrName;
/**
* The name of the HTML attribute storing the root attributes.
*/
rootAttrsAttrName;
/**
* A flag indicating whether the sentinel has been destroyed, used to prevent operations after cleanup.
*/
isDestroyed = !1;
/**
* Cleanup callbacks to be executed when the sentinel is destroyed.
*/
cleanupCallbacks = [];
/**
* The editor instance.
*/
editor;
/**
* When the editor is focused and the value attribute changes, we want to wait until it blurs to
* avoid disrupting the user while typing. This variable holds the pending value that should be applied
* once the editor blurs. It is set to null when there is no pending value or when the user makes changes in the editor,
* indicating that the pending value should be discarded.
*/
pendingValue = null;
/**
* Cache the previous value to avoid reacting to attribute changes that don't actually change the value.
* This can happen when the parent LiveView re-renders and sets the same value again, which would otherwise cause an
* unnecessary update in the editor.
*/
previousValue = null;
/**
* Updater created once the editor is ready. Tracks which root attributes
* were applied by this sentinel so it can clean them up independently of
* other consumers.
*/
attrsUpdater = null;
/**
* When the hook is mounted, we will wait for the editor to be registered and then set the initial value of the root.
* Accepts an options object to configure element, identifiers, and custom attribute names.
*/
constructor({
el: t,
editor: e,
rootName: a,
valueAttrName: n = "data-cke-value",
rootAttrsAttrName: i = "data-cke-root-attrs"
}) {
this.el = t, this.editor = e, this.rootName = a, this.valueAttrName = n, this.rootAttrsAttrName = i;
const { value: s } = this.attrs;
this.previousValue = s, this.setupSyncHandlers(e, this.rootName);
}
/**
* Helper to read and parse attributes from the element.
* It uses dynamically provided attribute names.
*/
get attrs() {
return {
rootAttributes: nt(this.el.getAttribute(this.rootAttrsAttrName)),
value: this.el.getAttribute(this.valueAttrName)
};
}
/**
* When the value attribute changes, we want to update the editor root value.
* However, if the editor is focused, we want to wait until it blurs to avoid disrupting the user while typing.
*/
async updated() {
const { editor: t } = this, { value: e, rootAttributes: a } = this.attrs;
if (!t || t.state === "destroyed" || this.isDestroyed)
return;
let n = () => {
};
t.model.enqueueChange({ isUndoable: !1 }, () => {
let i = this.attrsUpdater?.(a);
e !== this.previousValue && (this.previousValue = e, t.ui.focusTracker.isFocused ? this.pendingValue = e : (this.setRootValue(t, this.rootName, e), i = !0)), i && (n = Nt(t));
}), n();
}
/**
* Sets up focus-aware sync handlers on the editor.
* Registers cleanup via onBeforeDestroy.
*/
setupSyncHandlers(t, e) {
this.attrsUpdater = Pt(t, e), this.attrsUpdater(this.attrs.rootAttributes);
const a = () => {
this.pendingValue = null;
}, n = () => {
!t.ui.focusTracker.isFocused && this.pendingValue !== null && (this.setRootValue(t, e, this.pendingValue), this.pendingValue = null);
};
t.model.document.on("change:data", a), t.ui.focusTracker.on("change:isFocused", n), this.cleanupCallbacks.push(() => {
t.model.document.off("change:data", a), t.ui.focusTracker.off("change:isFocused", n);
});
}
/**
* Sets the value of a specific root in the editor.
*/
setRootValue(t, e, a) {
t.getData({ rootName: e }) !== a && t.setData({ [e]: a });
}
/**
* Disconnects the observer and cleans up editor event listeners.
* This should be called manually when the element is removed from the DOM.
*/
destroy() {
this.isDestroyed = !0, this.cleanupCallbacks.forEach((t) => t()), this.cleanupCallbacks = [];
}
}
class h extends W {
static the = new h();
}
class St extends x {
/**
* The sentinel instance responsible for tracking and updating root values and attributes
* for single-root editors.
*/
sentinel = null;
/**
* Attributes for the editor instance.
*/
get attrs() {
const { el: t } = this, e = t.getAttribute.bind(t), a = t.hasAttribute.bind(t), n = {
editorId: e("id"),
contextId: e("data-cke-context-id"),
preset: pt(t),
editableHeight: H(e("data-cke-editable-height")),
watchdog: a("data-cke-watchdog"),
events: {
change: a("data-cke-change-event"),
blur: a("data-cke-blur-event"),
focus: a("data-cke-focus-event"),
ready: a("data-cke-ready-event")
},
saveDebounceMs: H(e("data-cke-save-debounce-ms")) ?? 400,
language: {
ui: e("data-cke-language") || "en",
content: e("data-cke-content-language") || "en"
}
};
return Object.defineProperty(this, "attrs", {
value: n,
writable: !1,
configurable: !1,
enumerable: !0
}), n;
}
/**
* Mounts the editor component.
*/
async mounted() {
const { editorId: t } = this.attrs;
h.the.resetErrors(t);
try {
const e = await this.createEditor();
if (this.isBeingDestroyed())
return;
const a = h.the.mountEffect(t, (n) => (n.once("destroy", () => {
h.the.unregister(t, !1);
}, { priority: "highest" }), this.sentinel = new X({
editor: n,
el: this.el,
rootName: "main",
valueAttrName: "data-cke-initial-value",
rootAttrsAttrName: "data-cke-root-attrs"
}), () => {
this.sentinel?.destroy(), this.sentinel = null;
}));
this.onBeforeDestroy(async () => {
h.the.unregister(t), a();
const n = dt(e), i = bt(e);
n ? n.state !== "unavailable" && await n.context.remove(n.editorContextId) : i ? await i.destroy() : await e.destroy();
}), h.the.register(t, e);
} catch (e) {
console.error(e), h.the.error(t, e);
}
return this;
}
/**
* Watch attributes changes and sync value if something changed.
*/
async updated() {
this.sentinel?.updated();
}
/**
* Destroys editor component.
*/
async destroyed() {
this.el.style.display = "none";
}
/**
* Creates the CKEditor instance.
*/
async createEditor() {
const {
preset: t,
editorId: e,
contextId: a,
editableHeight: n,
events: i,
saveDebounceMs: s,
language: c,
watchdog: o
} = this.attrs, { customTranslations: u, type: d, license: l, config: { plugins: p, ...m } } = t, k = await mt(d), g = await (a ? b.the.waitFor(a) : Ct(this.el)), E = async () => {
const { loadedPlugins: f, hasPremium: v } = await K(p);
N(d) && f.push(
await xt({
editorId: e,
saveDebounceMs: s
})
), f.push(
...await Promise.all([
Dt(
{
editorId: e,
saveDebounceMs: s,
events: i,
pushEvent: this.pushEvent.bind(this),
handleEvent: this.handleEvent.bind(this)
}
),
Tt()
])
);
const y = [
...await Y(c, v),
J(u?.dictionary || {})
].filter((z) => !L(z));
let C = G(e);
const O = Object.keys(C);
N(d) && O.push("main"), Q(C, O) || (C = await Rt(e, O));
let w = {
...m,
licenseKey: l.key,
plugins: f,
language: c,
...y.length && {
translations: y
}
};
w = T(w), w = I([...y].reverse(), c.ui, w), w = ct(k, C, w);
const _ = await (async () => g ? (await lt({
context: g,
creator: k,
config: w
})).editor : k.create(w))();
return N(d) && n && wt(_, n), _;
};
if (o && !g) {
const f = await gt(E, t.watchdog);
return f.on("error", (v, { causesRestart: M }) => {
if (M) {
const y = h.the.getItem(e);
y && (ut(y), h.the.unregister(e));
}
}), f.on("restart", () => {
const v = f.editor;
h.the.register(e, v);
}), await f.create({}), f.editor;
}
return E();
}
}
function Q(r, t) {
return t.every((e) => r[e]);
}
async function Rt(r, t) {
return st(
() => {
const e = G(r);
if (!Q(e, t))
throw new Error(
`It looks like not all required root elements are present yet.
* If you want to wait for them, ensure they are registered before editor initialization.
* If you want lazy initialize roots, consider removing root values from the \`initialData\` config and assign initial data in editable components.
Missing roots: ${t.filter((a) => !e[a]).join(", ")}.`
);
return e;
},
{ timeOutAfter: 2e3, retryAfter: 100 }
);
}
const Vt = D(St);
class $t extends x {
/**
* The sentinel instance responsible for tracking and updating root values and attributes.
*/
sentinel = null;
/**
* Attributes for the editable instance.
*/
get attrs() {
const t = {
editableId: this.el.getAttribute("id"),
editorId: this.el.getAttribute("data-cke-editor-id") || null,
rootName: this.el.getAttribute("data-cke-editable-root-name"),
modelElement: this.el.getAttribute("data-cke-editable-root-model-element-name") || null,
initialValue: this.el.getAttribute("data-cke-editable-initial-value") || ""
};
return Object.defineProperty(this, "attrs", {
value: t,
writable: !1,
configurable: !1,
enumerable: !0
}), t;
}
/**
* Mounts the editable component.
*/
mounted() {
const { editableId: t, editorId: e, rootName: a, initialValue: n, modelElement: i } = this.attrs, s = h.the.mountEffect(e, (c) => {
const o = this.el.querySelector("[data-cke-editable-content]");
if (this.isBeingDestroyed())
return;
const u = this.el.querySelector(`#${t}_input`);
if (q(c) && !c.model.document.getRoot(a)) {
const { ui: l, editing: p } = c;
c.addRoot(a, {
isUndoable: !1,
initialData: n,
modelElement: i || "$root"
});
const m = l.view.createEditable(a, o);
l.addEditable(m), p.view.forceRender();
}
this.sentinel = new X({
el: this.el,
editor: c,
rootName: a,
valueAttrName: "data-cke-editable-initial-value",
rootAttrsAttrName: "data-cke-editable-root-attrs"
});
const d = u ? Mt(u, c, a) : null;
return () => {
if (d?.(), this.sentinel?.destroy(), this.sentinel = null, c.state !== "destroyed") {
const l = c.model.document.getRoot(a);
l && q(c) && (c.ui.view.editables[a] && c.detachEditable(l), l.isAttached() && c.detachRoot(a, !1));
}
};
});
this.onBeforeDestroy(() => {
this.el.style.display = "none", s();
});
}
/**
* Watch attributes changes and sync value if something changed.
*/
async updated() {
this.sentinel?.updated();
}
}
const Ut = D($t);
function Mt(r, t, e) {
const a = () => {
r.value = t.getData({ rootName: e });
}, n = A(200, a);
return t.model.document.on("change:data", n), a(), () => {
t.model.document.off("change:data", n);
};
}
class _t extends x {
/**
* Attributes for the editable instance.
*/
get attrs() {
const t = {
editorId: this.el.getAttribute("data-cke-editor-id") || null,
name: this.el.getAttribute("data-cke-ui-part-name")
};
return Object.defineProperty(this, "attrs", {
value: t,
writable: !1,
configurable: !1,
enumerable: !0
}), t;
}
/**
* Mounts the UI part component.
*/
mounted() {
const { editorId: t, name: e } = this.attrs, a = h.the.mountEffect(t, (n) => {
if (this.isBeingDestroyed())
return;
const { ui: i } = n, s = zt(e), c = i.view[s];
if (!c) {
console.error(`Unknown UI part name: "${e}". Supported names are "toolbar" and "menubar".`);
return;
}
return this.el.appendChild(c.element), () => {
this.el.innerHTML = "";
};
});
this.onBeforeDestroy(() => {
this.el.style.display = "none", a();
});
}
}
function zt(r) {
switch (r) {
case "toolbar":
return "toolbar";
case "menubar":
return "menuBarView";
default:
return null;
}
}
const jt = D(_t), Ft = {
CKEditor5: Vt,
CKEditable: Ut,
CKUIPart: jt,
CKContext: At
};
export {
b as ContextsRegistry,
U as CustomEditorPluginsRegistry,
h as EditorsRegistry,
Ft as Hooks,
dt as unwrapEditorContext,
bt as unwrapEditorWatchdog
};
//# sourceMappingURL=index.mjs.map