ckeditor5-blazor 1.9.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/elements/editable.d.ts +3 -11
  2. package/dist/elements/editable.d.ts.map +1 -1
  3. package/dist/elements/editor/editor.d.ts.map +1 -1
  4. package/dist/elements/editor/typings.d.ts +2 -1
  5. package/dist/elements/editor/typings.d.ts.map +1 -1
  6. package/dist/elements/editor/utils/cleanup-orphan-editor-elements.d.ts +8 -0
  7. package/dist/elements/editor/utils/cleanup-orphan-editor-elements.d.ts.map +1 -0
  8. package/dist/elements/editor/utils/create-editor-in-context.d.ts +6 -1
  9. package/dist/elements/editor/utils/create-editor-in-context.d.ts.map +1 -1
  10. package/dist/elements/editor/utils/index.d.ts +1 -0
  11. package/dist/elements/editor/utils/index.d.ts.map +1 -1
  12. package/dist/elements/editor/utils/wrap-with-watchdog.d.ts +7 -16
  13. package/dist/elements/editor/utils/wrap-with-watchdog.d.ts.map +1 -1
  14. package/dist/elements/ui-part.d.ts +3 -3
  15. package/dist/elements/ui-part.d.ts.map +1 -1
  16. package/dist/index.cjs +2 -2
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.mjs +459 -394
  19. package/dist/index.mjs.map +1 -1
  20. package/dist/interop/create-editable-blazor-interop.d.ts.map +1 -1
  21. package/dist/interop/create-editor-blazor-interop.d.ts.map +1 -1
  22. package/dist/shared/are-maps-equal.d.ts +11 -0
  23. package/dist/shared/are-maps-equal.d.ts.map +1 -0
  24. package/dist/shared/async-registry.d.ts +44 -16
  25. package/dist/shared/async-registry.d.ts.map +1 -1
  26. package/dist/shared/index.d.ts +1 -0
  27. package/dist/shared/index.d.ts.map +1 -1
  28. package/package.json +3 -3
  29. package/src/elements/editable.ts +38 -58
  30. package/src/elements/editor/editor.ts +122 -101
  31. package/src/elements/editor/typings.ts +3 -1
  32. package/src/elements/editor/utils/cleanup-orphan-editor-elements.test.ts +285 -0
  33. package/src/elements/editor/utils/cleanup-orphan-editor-elements.ts +60 -0
  34. package/src/elements/editor/utils/create-editor-in-context.ts +8 -2
  35. package/src/elements/editor/utils/index.ts +1 -0
  36. package/src/elements/editor/utils/wrap-with-watchdog.test.ts +34 -14
  37. package/src/elements/editor/utils/wrap-with-watchdog.ts +15 -25
  38. package/src/elements/ui-part.test.ts +1 -1
  39. package/src/elements/ui-part.ts +12 -11
  40. package/src/interop/create-editable-blazor-interop.ts +19 -16
  41. package/src/interop/create-editor-blazor-interop.ts +15 -18
  42. package/src/shared/are-maps-equal.test.ts +56 -0
  43. package/src/shared/are-maps-equal.ts +22 -0
  44. package/src/shared/async-registry.test.ts +190 -88
  45. package/src/shared/async-registry.ts +179 -107
  46. package/src/shared/index.ts +1 -0
package/dist/index.mjs CHANGED
@@ -1,9 +1,17 @@
1
- class E extends Error {
1
+ class k extends Error {
2
2
  constructor(t) {
3
3
  super(t), this.name = "CKEditor5BlazorError";
4
4
  }
5
5
  }
6
- class B {
6
+ function H(r, t) {
7
+ if (!r || r.size !== t.size)
8
+ return !1;
9
+ for (const [e, i] of r)
10
+ if (!t.has(e) || t.get(e) !== i)
11
+ return !1;
12
+ return !0;
13
+ }
14
+ class Y {
7
15
  /**
8
16
  * Map of registered items.
9
17
  */
@@ -20,6 +28,15 @@ class B {
20
28
  * Set of watchers that observe changes to the registry.
21
29
  */
22
30
  watchers = /* @__PURE__ */ new Set();
31
+ /**
32
+ * Batch nesting depth. When > 0, watcher notifications are deferred.
33
+ */
34
+ batchDepth = 0;
35
+ /**
36
+ * Snapshot of the last state dispatched to watchers, used for change detection.
37
+ */
38
+ lastNotifiedItems = null;
39
+ lastNotifiedErrors = null;
23
40
  /**
24
41
  * Executes a function on an item.
25
42
  * If the item is not yet registered, it will wait for it to be registered.
@@ -31,12 +48,35 @@ class B {
31
48
  */
32
49
  execute(t, e, i) {
33
50
  const a = this.items.get(t), n = this.initializationErrors.get(t);
34
- return n ? (i?.(n), Promise.reject(n)) : a ? Promise.resolve(e(a)) : new Promise((o, s) => {
51
+ return n ? (i?.(n), Promise.reject(n)) : a ? Promise.resolve(e(a)) : new Promise((o, c) => {
35
52
  const u = this.getPendingCallbacks(t);
36
- u.success.push(async (d) => {
37
- o(await e(d));
38
- }), i ? u.error.push(i) : u.error.push(s);
53
+ u.success.push(async (s) => {
54
+ o(await e(s));
55
+ }), i ? u.error.push(i) : u.error.push(c);
56
+ });
57
+ }
58
+ /**
59
+ * Reactively binds a mount/unmount lifecycle to a single registry item.
60
+ *
61
+ * @param id The ID of the item to observe.
62
+ * @param onMount Function executed when the item mounts.
63
+ * @returns A function that stops observing and immediately runs any pending cleanup.
64
+ */
65
+ mountEffect(t, e) {
66
+ let i, a, n = !1;
67
+ const o = this.watch((c) => {
68
+ const u = c.get(t);
69
+ if (u !== a && (i?.(), i = void 0, a = u, !!u))
70
+ try {
71
+ const s = e(u);
72
+ n ? (s?.(), o()) : i = s;
73
+ } catch (s) {
74
+ throw console.error(s), s;
75
+ }
39
76
  });
77
+ return () => {
78
+ n = !0, a && (o(), i?.(), i = void 0);
79
+ };
40
80
  }
41
81
  /**
42
82
  * Registers an item.
@@ -45,11 +85,13 @@ class B {
45
85
  * @param item The item instance.
46
86
  */
47
87
  register(t, e) {
48
- if (this.items.has(t))
49
- throw new Error(`Item with ID "${t}" is already registered.`);
50
- this.resetErrors(t), this.items.set(t, e);
51
- const i = this.pendingCallbacks.get(t);
52
- i && (i.success.forEach((a) => a(e)), this.pendingCallbacks.delete(t)), this.registerAsDefault(t, e), this.notifyWatchers();
88
+ this.batch(() => {
89
+ if (this.items.has(t))
90
+ throw new Error(`Item with ID "${t}" is already registered.`);
91
+ this.resetErrors(t), this.items.set(t, e);
92
+ const i = this.pendingCallbacks.get(t);
93
+ i && (i.success.forEach((a) => a(e)), this.pendingCallbacks.delete(t)), this.items.size === 1 && t !== null && this.register(null, e);
94
+ });
53
95
  }
54
96
  /**
55
97
  * Registers an error for an item.
@@ -58,9 +100,11 @@ class B {
58
100
  * @param error The error to register.
59
101
  */
60
102
  error(t, e) {
61
- this.items.delete(t), this.initializationErrors.set(t, e);
62
- const i = this.pendingCallbacks.get(t);
63
- i && (i.error.forEach((a) => a(e)), this.pendingCallbacks.delete(t)), this.initializationErrors.size === 1 && !this.items.size && this.error(null, e), this.notifyWatchers();
103
+ this.batch(() => {
104
+ this.items.delete(t), this.initializationErrors.set(t, e);
105
+ const i = this.pendingCallbacks.get(t);
106
+ i && (i.error.forEach((a) => a(e)), this.pendingCallbacks.delete(t)), this.initializationErrors.size === 1 && !this.items.size && this.error(null, e);
107
+ });
64
108
  }
65
109
  /**
66
110
  * Resets errors for an item.
@@ -75,11 +119,12 @@ class B {
75
119
  * Un-registers an item.
76
120
  *
77
121
  * @param id The ID of the item.
122
+ * @param resetPendingCallbacks If true resets pending callbacks.
78
123
  */
79
- unregister(t) {
80
- if (!this.items.has(t))
81
- throw new Error(`Item with ID "${t}" is not registered.`);
82
- t && this.items.get(null) === this.items.get(t) && this.unregister(null), this.items.delete(t), this.pendingCallbacks.delete(t), this.notifyWatchers();
124
+ unregister(t, e = !0) {
125
+ this.batch(() => {
126
+ 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);
127
+ });
83
128
  }
84
129
  /**
85
130
  * Gets all registered items.
@@ -89,6 +134,14 @@ class B {
89
134
  getItems() {
90
135
  return Array.from(this.items.values());
91
136
  }
137
+ /**
138
+ * Returns single registered item.
139
+ *
140
+ * @returns Registered item.
141
+ */
142
+ getItem(t) {
143
+ return this.items.get(t);
144
+ }
92
145
  /**
93
146
  * Checks if an item with the given ID is registered.
94
147
  *
@@ -103,23 +156,11 @@ class B {
103
156
  * If the item is not registered yet, it will wait for it to be registered.
104
157
  *
105
158
  * @param id The ID of the item.
106
- * @param timeout Optional timeout in milliseconds.
107
159
  * @returns A promise that resolves with the item instance.
108
160
  */
109
- waitFor(t, e) {
110
- return new Promise((i, a) => {
111
- let n = !1, o = null;
112
- this.execute(
113
- t,
114
- (s) => {
115
- n || (o !== null && clearTimeout(o), i(s));
116
- },
117
- (s) => {
118
- n || (o !== null && clearTimeout(o), a(s));
119
- }
120
- ), e && (o = setTimeout(() => {
121
- n = !0, a(new Error(`Timeout waiting for item with ID "${t}" to be registered.`));
122
- }, e));
161
+ waitFor(t) {
162
+ return new Promise((e, i) => {
163
+ this.execute(t, e, i);
123
164
  });
124
165
  }
125
166
  /**
@@ -128,7 +169,32 @@ class B {
128
169
  */
129
170
  async destroyAll() {
130
171
  const t = Array.from(new Set(this.items.values())).map((e) => e.destroy());
131
- this.items.clear(), this.pendingCallbacks.clear(), await Promise.all(t), this.notifyWatchers();
172
+ this.items.clear(), this.pendingCallbacks.clear(), await Promise.all(t), this.flushWatchers();
173
+ }
174
+ /**
175
+ * Destroys all registered editors and removes all watchers.
176
+ */
177
+ async reset() {
178
+ await this.destroyAll(), this.watchers.clear();
179
+ }
180
+ /**
181
+ * Executes a callback while deferring all watcher notifications.
182
+ * A single notification is fired synchronously after the callback returns,
183
+ * but only if the registry actually changed.
184
+ *
185
+ * Batches can be nested — watchers are notified only when the outermost
186
+ * batch completes.
187
+ *
188
+ * @param fn The callback to execute.
189
+ * @returns The return value of the callback.
190
+ */
191
+ batch(t) {
192
+ this.batchDepth++;
193
+ try {
194
+ return t();
195
+ } finally {
196
+ this.batchDepth--, this.batchDepth === 0 && this.flushWatchers();
197
+ }
132
198
  }
133
199
  /**
134
200
  * Registers a watcher that will be called whenever the registry changes.
@@ -151,21 +217,13 @@ class B {
151
217
  this.watchers.delete(t);
152
218
  }
153
219
  /**
154
- * Resets the registry by clearing all items, errors, and pending callbacks.
155
- */
156
- reset() {
157
- this.items.clear(), this.initializationErrors.clear(), this.pendingCallbacks.clear(), this.notifyWatchers();
158
- }
159
- /**
160
- * Notifies all watchers about changes to the registry.
220
+ * Immediately dispatches the current state to all watchers if it changed.
161
221
  */
162
- notifyWatchers() {
163
- this.watchers.forEach(
164
- (t) => t(
165
- new Map(this.items),
166
- new Map(this.initializationErrors)
167
- )
168
- );
222
+ flushWatchers() {
223
+ H(this.lastNotifiedItems, this.items) && H(this.lastNotifiedErrors, this.initializationErrors) || (this.lastNotifiedItems = new Map(this.items), this.lastNotifiedErrors = new Map(this.initializationErrors), this.watchers.forEach((t) => t(
224
+ new Map(this.items),
225
+ new Map(this.initializationErrors)
226
+ )));
169
227
  }
170
228
  /**
171
229
  * Gets or creates pending callbacks for a specific ID.
@@ -177,17 +235,8 @@ class B {
177
235
  let e = this.pendingCallbacks.get(t);
178
236
  return e || (e = { success: [], error: [] }, this.pendingCallbacks.set(t, e)), e;
179
237
  }
180
- /**
181
- * Registers an item as the default (null ID) item if it's the first one.
182
- *
183
- * @param id The ID of the item being registered.
184
- * @param item The item instance.
185
- */
186
- registerAsDefault(t, e) {
187
- this.items.size === 1 && t !== null && this.register(null, e);
188
- }
189
238
  }
190
- function R(r, t) {
239
+ function $(r, t) {
191
240
  let e = null;
192
241
  return (...i) => {
193
242
  e && clearTimeout(e), e = setTimeout(() => {
@@ -195,18 +244,18 @@ function R(r, t) {
195
244
  }, r);
196
245
  };
197
246
  }
198
- function it(r, t) {
247
+ function st(r, t) {
199
248
  const e = Object.entries(r).filter(([i, a]) => t(a, i));
200
249
  return Object.fromEntries(e);
201
250
  }
202
- function T(r) {
251
+ function N(r) {
203
252
  return Object.keys(r).length === 0 && r.constructor === Object;
204
253
  }
205
- function M(r, t) {
254
+ function W(r, t) {
206
255
  const e = Object.entries(r).map(([i, a]) => [i, t(a, i)]);
207
256
  return Object.fromEntries(e);
208
257
  }
209
- function at(r, t) {
258
+ function ct(r, t) {
210
259
  if (r === t)
211
260
  return !0;
212
261
  const e = Object.keys(r), i = Object.keys(t);
@@ -217,30 +266,30 @@ function at(r, t) {
217
266
  return !1;
218
267
  return !0;
219
268
  }
220
- function nt() {
269
+ function ut() {
221
270
  return Math.random().toString(36).substring(2);
222
271
  }
223
- function ot(r, {
272
+ function lt(r, {
224
273
  timeOutAfter: t = 500,
225
274
  retryAfter: e = 100
226
275
  } = {}) {
227
276
  return new Promise((i, a) => {
228
277
  const n = Date.now();
229
278
  let o = null;
230
- const s = setTimeout(() => {
279
+ const c = setTimeout(() => {
231
280
  a(o ?? new Error("Timeout"));
232
281
  }, t), u = async () => {
233
282
  try {
234
- const d = await r();
235
- clearTimeout(s), i(d);
236
- } catch (d) {
237
- o = d, Date.now() - n > t ? a(d) : setTimeout(u, e);
283
+ const s = await r();
284
+ clearTimeout(c), i(s);
285
+ } catch (s) {
286
+ o = s, Date.now() - n > t ? a(s) : setTimeout(u, e);
238
287
  }
239
288
  };
240
289
  u();
241
290
  });
242
291
  }
243
- function D() {
292
+ function x() {
244
293
  return new Promise((r) => {
245
294
  switch (document.readyState) {
246
295
  case "loading":
@@ -255,7 +304,7 @@ function D() {
255
304
  }
256
305
  });
257
306
  }
258
- function $(r) {
307
+ function L(r) {
259
308
  if (r.hasAttribute("data-cke-interactive"))
260
309
  return { promise: Promise.resolve(), disconnect: () => {
261
310
  } };
@@ -273,14 +322,40 @@ function $(r) {
273
322
  disconnect: () => t?.disconnect()
274
323
  };
275
324
  }
276
- function x(r) {
325
+ function D(r) {
277
326
  r.setAttribute("data-cke-interactive", "true");
278
327
  }
279
- const z = /* @__PURE__ */ Symbol.for("context-editor-watchdog");
280
- async function st({ element: r, context: t, creator: e, config: i }) {
281
- const a = nt();
328
+ function dt(r) {
329
+ const t = [
330
+ r.ui?.element,
331
+ r.ui?.view?.toolbar?.element,
332
+ r.ui?.view?.menuBarView?.element
333
+ ].filter(Boolean);
334
+ for (const n of t)
335
+ a(n);
336
+ const e = r.ui?.view?.body?._bodyCollectionContainer;
337
+ e?.isConnected && a(e);
338
+ const i = r.editing?.view;
339
+ if (i)
340
+ for (const n of i.domRoots.values())
341
+ n instanceof HTMLElement && (n.removeAttribute("contenteditable"), n.removeAttribute("role"), n.removeAttribute("aria-label"), n.removeAttribute("aria-multiline"), n.removeAttribute("spellcheck"), n.classList.remove(
342
+ "ck",
343
+ "ck-content",
344
+ "ck-editor__editable",
345
+ "ck-rounded-corners",
346
+ "ck-editor__editable_inline",
347
+ "ck-blurred",
348
+ "ck-focused"
349
+ ), a(n));
350
+ function a(n) {
351
+ n.hasAttribute("data-cke-controlled") ? n.innerHTML = "" : n.remove();
352
+ }
353
+ }
354
+ const V = /* @__PURE__ */ Symbol.for("context-editor-watchdog");
355
+ async function mt({ element: r, context: t, creator: e, config: i }) {
356
+ const a = ut();
282
357
  await t.add({
283
- creator: (u, d) => e.create(u, d),
358
+ creator: (u, s) => e.create(u, s),
284
359
  id: a,
285
360
  sourceElementOrData: r,
286
361
  type: "editor",
@@ -291,23 +366,23 @@ async function st({ element: r, context: t, creator: e, config: i }) {
291
366
  editorContextId: a,
292
367
  context: t
293
368
  };
294
- n[z] = o;
295
- const s = t.destroy.bind(t);
296
- return t.destroy = async () => (o.state = "unavailable", s()), {
369
+ n[V] = o;
370
+ const c = t.destroy.bind(t);
371
+ return t.destroy = async () => (o.state = "unavailable", c()), {
297
372
  ...o,
298
373
  editor: n
299
374
  };
300
375
  }
301
- function ct(r) {
302
- return z in r ? r[z] : null;
376
+ function ht(r) {
377
+ return V in r ? r[V] : null;
303
378
  }
304
- function J(r) {
379
+ function X(r) {
305
380
  return Array.from(r.model.document.getRoots()).reduce((t, e) => (e.rootName === "$graveyard" || (t[e.rootName] = r.getData({ rootName: e.rootName })), t), /* @__PURE__ */ Object.create({}));
306
381
  }
307
- function P(r) {
382
+ function O(r) {
308
383
  return ["inline", "classic", "balloon", "decoupled"].includes(r);
309
384
  }
310
- async function U(r) {
385
+ async function J(r) {
311
386
  const t = await import("ckeditor5"), i = {
312
387
  inline: t.InlineEditor,
313
388
  balloon: t.BalloonEditor,
@@ -316,11 +391,11 @@ async function U(r) {
316
391
  multiroot: t.MultiRootEditor
317
392
  }[r];
318
393
  if (!i)
319
- throw new E(`Unsupported editor type: ${r}`);
394
+ throw new k(`Unsupported editor type: ${r}`);
320
395
  return i;
321
396
  }
322
- class W {
323
- static the = new W();
397
+ class F {
398
+ static the = new F();
324
399
  /**
325
400
  * Map of registered custom plugins.
326
401
  */
@@ -339,7 +414,7 @@ class W {
339
414
  */
340
415
  register(t, e) {
341
416
  if (this.plugins.has(t))
342
- throw new E(`Plugin with name "${t}" is already registered.`);
417
+ throw new k(`Plugin with name "${t}" is already registered.`);
343
418
  return this.plugins.set(t, e), this.unregister.bind(this, t);
344
419
  }
345
420
  /**
@@ -350,7 +425,7 @@ class W {
350
425
  */
351
426
  unregister(t) {
352
427
  if (!this.plugins.has(t))
353
- throw new E(`Plugin with name "${t}" is not registered.`);
428
+ throw new k(`Plugin with name "${t}" is not registered.`);
354
429
  this.plugins.delete(t);
355
430
  }
356
431
  /**
@@ -379,20 +454,20 @@ class W {
379
454
  return this.plugins.has(t);
380
455
  }
381
456
  }
382
- async function H(r) {
457
+ async function Q(r) {
383
458
  const t = await import("ckeditor5");
384
459
  let e = null;
385
460
  const i = r.map(async (a) => {
386
- if (ut(a)) {
387
- const { name: u, path: d } = a.$import, l = await import(
461
+ if (ft(a)) {
462
+ const { name: u, path: s } = a.$import, l = await import(
388
463
  /* @vite-ignore */
389
- d
390
- ), w = (Object.prototype.hasOwnProperty.call(l, u) ? l[u] : void 0) ?? (Object.prototype.hasOwnProperty.call(l, "default") ? l.default : void 0);
391
- if (!w)
392
- throw new E(`Plugin "${u}" not found in module "${d}".`);
393
- return w;
464
+ s
465
+ ), p = (Object.prototype.hasOwnProperty.call(l, u) ? l[u] : void 0) ?? (Object.prototype.hasOwnProperty.call(l, "default") ? l.default : void 0);
466
+ if (!p)
467
+ throw new k(`Plugin "${u}" not found in module "${s}".`);
468
+ return p;
394
469
  }
395
- const n = await W.the.get(a);
470
+ const n = await F.the.get(a);
396
471
  if (n)
397
472
  return n;
398
473
  const { [a]: o } = t;
@@ -402,40 +477,40 @@ async function H(r) {
402
477
  try {
403
478
  e = await import("ckeditor5-premium-features");
404
479
  } catch (u) {
405
- throw console.error(`Failed to load premium package: ${u}`), new E(`Plugin "${a}" not found in base package and failed to load premium package.`);
480
+ throw console.error(`Failed to load premium package: ${u}`), new k(`Plugin "${a}" not found in base package and failed to load premium package.`);
406
481
  }
407
- const { [a]: s } = e || {};
408
- if (s)
409
- return s;
410
- throw new E(`Plugin "${a}" not found in base or premium packages.`);
482
+ const { [a]: c } = e || {};
483
+ if (c)
484
+ return c;
485
+ throw new k(`Plugin "${a}" not found in base or premium packages.`);
411
486
  });
412
487
  return {
413
488
  loadedPlugins: await Promise.all(i),
414
489
  hasPremium: !!e
415
490
  };
416
491
  }
417
- function ut(r) {
492
+ function ft(r) {
418
493
  return typeof r == "object" && r !== null && "$import" in r;
419
494
  }
420
- async function K(r, t) {
495
+ async function Z(r, t) {
421
496
  const e = [r.ui, r.content];
422
497
  return await Promise.all(
423
498
  [
424
- j("ckeditor5", e),
499
+ K("ckeditor5", e),
425
500
  /* v8 ignore next -- @preserve */
426
- t && j("ckeditor5-premium-features", e)
501
+ t && K("ckeditor5-premium-features", e)
427
502
  ].filter((a) => !!a)
428
503
  ).then((a) => a.flat());
429
504
  }
430
- async function j(r, t) {
505
+ async function K(r, t) {
431
506
  return await Promise.all(
432
507
  t.filter((e) => e !== "en").map(async (e) => {
433
- const i = await lt(r, e);
508
+ const i = await pt(r, e);
434
509
  return i?.default ?? i;
435
510
  }).filter(Boolean)
436
511
  );
437
512
  }
438
- async function lt(r, t) {
513
+ async function pt(r, t) {
439
514
  try {
440
515
  if (r === "ckeditor5")
441
516
  switch (t) {
@@ -735,28 +810,28 @@ async function lt(r, t) {
735
810
  return console.error(`Failed to load translation for ${r}/${t}:`, e), null;
736
811
  }
737
812
  }
738
- function G(r) {
739
- return M(r, (t) => ({
813
+ function tt(r) {
814
+ return W(r, (t) => ({
740
815
  dictionary: t
741
816
  }));
742
817
  }
743
- function F() {
818
+ function _() {
744
819
  return Array.from(document.querySelectorAll("cke5-editor")).map((r) => r.getAttribute("data-cke-editor-id")).filter((r) => r !== null);
745
820
  }
746
- function Y(r) {
747
- const t = X(r);
748
- return M(t, ({ element: e }) => e);
821
+ function et(r) {
822
+ const t = rt(r);
823
+ return W(t, ({ element: e }) => e);
749
824
  }
750
- function _(r) {
751
- const t = X(r), e = M(t, ({ content: i }) => i);
752
- return it(e, (i) => typeof i == "string");
825
+ function G(r) {
826
+ const t = rt(r), e = W(t, ({ content: i }) => i);
827
+ return st(e, (i) => typeof i == "string");
753
828
  }
754
- function X(r) {
755
- const t = Array.from(document.querySelectorAll(`cke5-editable[data-cke-editor-id="${r}"]`)).reduce((o, s) => {
756
- const u = s.getAttribute("data-cke-root-name"), d = s.getAttribute("data-cke-content");
829
+ function rt(r) {
830
+ const t = Array.from(document.querySelectorAll(`cke5-editable[data-cke-editor-id="${r}"]`)).reduce((o, c) => {
831
+ const u = c.getAttribute("data-cke-root-name"), s = c.getAttribute("data-cke-content");
757
832
  return o[u] = {
758
- element: s.querySelector("[data-cke-editable-content]"),
759
- content: d
833
+ element: c.querySelector("[data-cke-editable-content]"),
834
+ content: s
760
835
  }, o;
761
836
  }, /* @__PURE__ */ Object.create({})), e = document.querySelector(`cke5-editor[data-cke-editor-id="${r}"]`);
762
837
  if (!e)
@@ -776,11 +851,11 @@ function X(r) {
776
851
  }
777
852
  } : t;
778
853
  }
779
- function O(r) {
854
+ function S(r) {
780
855
  if (!r || typeof r != "object")
781
856
  return r;
782
857
  if (Array.isArray(r))
783
- return r.map((i) => O(i));
858
+ return r.map((i) => S(i));
784
859
  const t = r;
785
860
  if (t.$element && typeof t.$element == "string") {
786
861
  const i = document.querySelector(t.$element);
@@ -788,57 +863,55 @@ function O(r) {
788
863
  }
789
864
  const e = /* @__PURE__ */ Object.create(null);
790
865
  for (const [i, a] of Object.entries(r))
791
- e[i] = O(a);
866
+ e[i] = S(a);
792
867
  return e;
793
868
  }
794
- function S(r, t, e) {
869
+ function M(r, t, e) {
795
870
  if (!e || typeof e != "object")
796
871
  return e;
797
872
  if (Array.isArray(e))
798
- return e.map((n) => S(r, t, n));
873
+ return e.map((n) => M(r, t, n));
799
874
  const i = e;
800
875
  if (i.$translation && typeof i.$translation == "string") {
801
- const n = i.$translation, o = dt(r, n, t);
876
+ const n = i.$translation, o = wt(r, n, t);
802
877
  return o === void 0 && console.warn(`Translation not found for key: ${n}`), o !== void 0 ? o : null;
803
878
  }
804
879
  const a = /* @__PURE__ */ Object.create(null);
805
880
  for (const [n, o] of Object.entries(e))
806
- a[n] = S(r, t, o);
881
+ a[n] = M(r, t, o);
807
882
  return a;
808
883
  }
809
- function dt(r, t, e) {
884
+ function wt(r, t, e) {
810
885
  for (const i of r) {
811
886
  const a = i[e];
812
887
  if (a?.dictionary && t in a.dictionary)
813
888
  return a.dictionary[t];
814
889
  }
815
890
  }
816
- function mt(r, t) {
891
+ function gt(r, t) {
817
892
  const { editing: e } = r;
818
893
  e.view.change((i) => {
819
894
  i.setStyle("height", `${t}px`, e.view.document.getRoot());
820
895
  });
821
896
  }
822
- const V = /* @__PURE__ */ Symbol.for("elixir-editor-watchdog");
823
- async function ht(r) {
824
- const { EditorWatchdog: t } = await import("ckeditor5"), e = new t(r);
825
- return e.setCreator(async (...i) => {
826
- const a = await r.create(...i);
827
- return a[V] = e, a;
828
- }), {
829
- watchdog: e,
830
- Constructor: {
831
- create: async (...i) => (await e.create(...i), e.editor)
832
- }
833
- };
897
+ const z = /* @__PURE__ */ Symbol.for("elixir-editor-watchdog");
898
+ async function bt(r, t) {
899
+ const { EditorWatchdog: e } = await import("ckeditor5"), i = new e(null, t ?? {
900
+ crashNumberLimit: 10,
901
+ minimumNonErrorTimePeriod: 5e3
902
+ });
903
+ return i.setCreator(async () => {
904
+ const a = await r();
905
+ return a[z] = i, a;
906
+ }), i;
834
907
  }
835
- function pt(r) {
836
- return V in r ? r[V] : null;
908
+ function yt(r) {
909
+ return z in r ? r[z] : null;
837
910
  }
838
- class v extends B {
839
- static the = new v();
911
+ class C extends Y {
912
+ static the = new C();
840
913
  }
841
- class wt extends HTMLElement {
914
+ class Et extends HTMLElement {
842
915
  /**
843
916
  * The promise that resolves to the context instance.
844
917
  */
@@ -851,35 +924,35 @@ class wt extends HTMLElement {
851
924
  * Mounts the context component.
852
925
  */
853
926
  async connectedCallback() {
854
- await D(), this.interactiveWait = $(this), await this.interactiveWait.promise, await this.initializeContext();
927
+ await x(), this.interactiveWait = L(this), await this.interactiveWait.promise, await this.initializeContext();
855
928
  }
856
929
  /**
857
930
  * Initializes the context component.
858
931
  */
859
932
  async initializeContext() {
860
- const t = this.getAttribute("data-cke-context-id"), e = JSON.parse(this.getAttribute("data-cke-language")), i = JSON.parse(this.getAttribute("data-cke-context")), { customTranslations: a, watchdogConfig: n, config: { plugins: o, ...s } } = i, { loadedPlugins: u, hasPremium: d } = await H(o ?? []), l = [
861
- ...await K(e, d),
862
- G(a || {})
863
- ].filter((y) => !T(y));
933
+ const t = this.getAttribute("data-cke-context-id"), e = JSON.parse(this.getAttribute("data-cke-language")), i = JSON.parse(this.getAttribute("data-cke-context")), { customTranslations: a, watchdogConfig: n, config: { plugins: o, ...c } } = i, { loadedPlugins: u, hasPremium: s } = await Q(o ?? []), l = [
934
+ ...await Z(e, s),
935
+ tt(a || {})
936
+ ].filter((w) => !N(w));
864
937
  this.contextPromise = (async () => {
865
- const { ContextWatchdog: y, Context: b } = await import("ckeditor5"), f = new y(b, {
938
+ const { ContextWatchdog: w, Context: y } = await import("ckeditor5"), E = new w(y, {
866
939
  crashNumberLimit: 10,
867
940
  ...n
868
941
  });
869
- let p = O(s);
870
- return p = S([...l].reverse(), e.ui, p), await f.create({
871
- ...p,
942
+ let h = S(c);
943
+ return h = M([...l].reverse(), e.ui, h), await E.create({
944
+ ...h,
872
945
  language: e,
873
946
  plugins: u,
874
947
  ...l.length && {
875
948
  translations: l
876
949
  }
877
- }), f.on("itemError", (...A) => {
878
- console.error("Context item error:", ...A);
879
- }), f;
950
+ }), E.on("itemError", (...v) => {
951
+ console.error("Context item error:", ...v);
952
+ }), E;
880
953
  })();
881
- const w = await this.contextPromise;
882
- this.isConnected && v.the.register(t, w);
954
+ const p = await this.contextPromise;
955
+ this.isConnected && C.the.register(t, p);
883
956
  }
884
957
  /**
885
958
  * Destroys the context component. Unmounts root from the editor.
@@ -891,60 +964,51 @@ class wt extends HTMLElement {
891
964
  try {
892
965
  await (await this.contextPromise)?.destroy();
893
966
  } finally {
894
- this.contextPromise = null, t && v.the.hasItem(t) && v.the.unregister(t);
967
+ this.contextPromise = null, t && C.the.hasItem(t) && C.the.unregister(t);
895
968
  }
896
969
  }
897
970
  }
898
- class h extends B {
899
- static the = new h();
971
+ class m extends Y {
972
+ static the = new m();
900
973
  }
901
- class ft extends HTMLElement {
974
+ class kt extends HTMLElement {
902
975
  /**
903
- * The promise that resolves when the editable is mounted.
976
+ * Stops observing the editor registry and immediately runs any pending cleanup.
904
977
  */
905
- editorPromise = null;
978
+ unmountEffect = null;
906
979
  /**
907
980
  * Wait result for the interactive attribute.
908
981
  */
909
982
  interactiveWait;
910
- /**
911
- * Callbacks to be invoked before the editable is destroyed.
912
- */
913
- beforeDestroyCallbacks = [];
914
- /**
915
- * Registers a callback to be called before the editable is destroyed.
916
- */
917
- onBeforeDestroy(t) {
918
- this.beforeDestroyCallbacks.push(t);
919
- }
920
983
  /**
921
984
  * Mounts the editable component.
922
985
  */
923
986
  async connectedCallback() {
924
- await D(), this.interactiveWait = $(this), await this.interactiveWait.promise, await this.initializeEditable();
987
+ await x(), this.interactiveWait = L(this), await this.interactiveWait.promise, await this.initializeEditable();
925
988
  }
926
989
  /**
927
990
  * Initializes the editable instance.
928
991
  */
929
992
  async initializeEditable() {
930
- this.hasAttribute("data-cke-editor-id") || this.setAttribute("data-cke-editor-id", F()[0]);
993
+ this.hasAttribute("data-cke-editor-id") || this.setAttribute("data-cke-editor-id", _()[0]);
931
994
  const t = this.getAttribute("data-cke-editor-id"), e = this.getAttribute("data-cke-root-name"), i = JSON.parse(this.getAttribute("data-cke-root-attributes") || "{}"), a = this.getAttribute("data-cke-content"), n = Number.parseInt(this.getAttribute("data-cke-save-debounce-ms"), 10);
932
995
  if (!t || !e)
933
- throw new E("Editor ID or Root Name is missing.");
934
- this.style.display = "block", this.editorPromise = h.the.execute(t, async (o) => {
996
+ throw new k("Editor ID or Root Name is missing.");
997
+ this.style.display = "block", this.unmountEffect = m.the.mountEffect(t, (o) => {
935
998
  if (!this.isConnected)
936
- return null;
937
- const { ui: s, editing: u, model: d } = o, c = this.querySelector("input"), l = d.document.getRoot(e);
999
+ return;
1000
+ const { ui: c, editing: u, model: s } = o, d = this.querySelector("input"), l = s.document.getRoot(e);
938
1001
  if (l?.isAttached()) {
939
1002
  if (a !== null) {
940
- const p = o.getData({ rootName: e });
941
- p && p !== a && o.setData({
1003
+ const h = o.getData({ rootName: e });
1004
+ h && h !== a && o.setData({
942
1005
  [e]: a
943
1006
  });
944
1007
  }
945
- return T(i) || o.model.change((p) => {
946
- p.setAttributes(i, l);
947
- }), o;
1008
+ N(i) || o.model.change((h) => {
1009
+ h.setAttributes(i, l);
1010
+ });
1011
+ return;
948
1012
  }
949
1013
  o.addRoot(e, {
950
1014
  isUndoable: !1,
@@ -953,46 +1017,41 @@ class ft extends HTMLElement {
953
1017
  data: a
954
1018
  }
955
1019
  });
956
- const w = this.querySelector("[data-cke-editable-content]"), y = s.view.createEditable(e, w);
957
- s.addEditable(y), u.view.forceRender();
958
- const b = () => {
959
- if (!d.document.getRoot(e)?.isAttached())
1020
+ const p = this.querySelector("[data-cke-editable-content]"), w = c.view.createEditable(e, p);
1021
+ c.addEditable(w), u.view.forceRender();
1022
+ const y = () => {
1023
+ if (!s.document.getRoot(e)?.isAttached())
960
1024
  return;
961
- const p = o.getData({ rootName: e });
962
- c && (c.value = p, c.dispatchEvent(new Event("input"))), this.dispatchEvent(new CustomEvent("change", {
1025
+ const h = o.getData({ rootName: e });
1026
+ d && (d.value = h, d.dispatchEvent(new Event("input"))), this.dispatchEvent(new CustomEvent("change", {
963
1027
  detail: {
964
- value: p
1028
+ value: h
965
1029
  }
966
1030
  }));
967
- }, f = R(n, b);
968
- return o.model.document.on("change:data", f), this.onBeforeDestroy(() => o.model.document.off("change:data", f)), b(), o;
1031
+ }, E = $(n, y);
1032
+ return o.model.document.on("change:data", E), y(), () => {
1033
+ if (o.model.document.off("change:data", E), o.state !== "destroyed" && e) {
1034
+ const h = o.model.document.getRoot(e);
1035
+ if (h && "detachEditable" in o) {
1036
+ try {
1037
+ o.ui.view.editables[e] && o.detachEditable(h);
1038
+ } catch (v) {
1039
+ console.error("Unable unmount editable from root:", v);
1040
+ }
1041
+ h.isAttached() && o.detachRoot(e, !1);
1042
+ }
1043
+ }
1044
+ };
969
1045
  });
970
1046
  }
971
1047
  /**
972
1048
  * Destroys the editable component. Unmounts root from the editor.
973
1049
  */
974
- async disconnectedCallback() {
975
- this.interactiveWait?.disconnect();
976
- const t = this.getAttribute("data-cke-root-name");
977
- this.style.display = "none";
978
- const e = await this.editorPromise;
979
- this.editorPromise = null;
980
- for (const i of this.beforeDestroyCallbacks)
981
- i();
982
- if (this.beforeDestroyCallbacks = [], e && e.state !== "destroyed" && t) {
983
- const i = e.model.document.getRoot(t);
984
- if (i && "detachEditable" in e) {
985
- try {
986
- e.ui.view.editables[t] && e.detachEditable(i);
987
- } catch (a) {
988
- console.error("Unable unmount editable from root:", a);
989
- }
990
- i.isAttached() && e.detachRoot(t, !1);
991
- }
992
- }
1050
+ disconnectedCallback() {
1051
+ this.interactiveWait?.disconnect(), this.style.display = "none", this.unmountEffect?.(), this.unmountEffect = null;
993
1052
  }
994
1053
  }
995
- async function gt({
1054
+ async function vt({
996
1055
  saveDebounceMs: r,
997
1056
  editorId: t,
998
1057
  targetElement: e
@@ -1009,7 +1068,7 @@ async function gt({
1009
1068
  * Initializes the plugin.
1010
1069
  */
1011
1070
  afterInit() {
1012
- const { editor: n } = this, o = R(r, this.dispatch);
1071
+ const { editor: n } = this, o = $(r, this.dispatch);
1013
1072
  n.model.document.on("change:data", o), n.once("ready", this.dispatch);
1014
1073
  }
1015
1074
  /**
@@ -1018,25 +1077,25 @@ async function gt({
1018
1077
  dispatch = () => {
1019
1078
  const { editor: n } = this;
1020
1079
  e.dispatchEvent(
1021
- new g({
1080
+ new b({
1022
1081
  editorId: t,
1023
1082
  editor: n,
1024
- roots: J(n)
1083
+ roots: X(n)
1025
1084
  })
1026
1085
  );
1027
1086
  };
1028
1087
  };
1029
1088
  }
1030
- class g extends CustomEvent {
1089
+ class b extends CustomEvent {
1031
1090
  static EVENT_NAME = "ckeditor5:change:data";
1032
1091
  constructor(t) {
1033
- super(g.EVENT_NAME, {
1092
+ super(b.EVENT_NAME, {
1034
1093
  detail: t,
1035
1094
  bubbles: !0
1036
1095
  });
1037
1096
  }
1038
1097
  }
1039
- async function yt(r) {
1098
+ async function At(r) {
1040
1099
  const { Plugin: t } = await import("ckeditor5");
1041
1100
  return class extends t {
1042
1101
  /**
@@ -1058,7 +1117,7 @@ async function yt(r) {
1058
1117
  */
1059
1118
  afterInit() {
1060
1119
  const { editor: i } = this, n = i.sourceElement.id.replace(/_editor$/, "");
1061
- this.input = document.getElementById(`${n}_input`), this.input && (i.model.document.on("change:data", R(r, () => this.sync())), i.once("ready", this.sync), this.form = this.input.closest("form"), this.form?.addEventListener("submit", this.sync));
1120
+ this.input = document.getElementById(`${n}_input`), this.input && (i.model.document.on("change:data", $(r, () => this.sync())), i.once("ready", this.sync), this.form = this.input.closest("form"), this.form?.addEventListener("submit", this.sync));
1062
1121
  }
1063
1122
  /**
1064
1123
  * Synchronizes the editor's content with the input field.
@@ -1077,7 +1136,7 @@ async function yt(r) {
1077
1136
  }
1078
1137
  };
1079
1138
  }
1080
- class bt extends HTMLElement {
1139
+ class Ct extends HTMLElement {
1081
1140
  /**
1082
1141
  * The promise that resolves to the editor instance.
1083
1142
  */
@@ -1090,22 +1149,22 @@ class bt extends HTMLElement {
1090
1149
  * Mounts the editor component.
1091
1150
  */
1092
1151
  async connectedCallback() {
1093
- await D(), this.interactiveWait = $(this), U("classic"), await this.interactiveWait.promise, await this.initializeEditor();
1152
+ await x(), this.interactiveWait = L(this), J("classic"), await this.interactiveWait.promise, await this.initializeEditor();
1094
1153
  }
1095
1154
  /**
1096
1155
  * Initializes the editor instance.
1097
1156
  */
1098
1157
  async initializeEditor() {
1099
1158
  const t = this.getAttribute("data-cke-editor-id");
1100
- h.the.resetErrors(t);
1159
+ m.the.resetErrors(t);
1101
1160
  try {
1102
1161
  this.style.display = "block", this.editorPromise = this.createEditor();
1103
1162
  const e = await this.editorPromise;
1104
- this.isConnected && (h.the.register(t, e), e.once("destroy", () => {
1105
- h.the.hasItem(t) && h.the.unregister(t);
1163
+ this.isConnected && (m.the.register(t, e), e.once("destroy", () => {
1164
+ m.the.hasItem(t) && m.the.unregister(t);
1106
1165
  }));
1107
1166
  } catch (e) {
1108
- console.error(`Error initializing CKEditor5 instance with ID "${t}":`, e), this.editorPromise = null, h.the.error(t, e);
1167
+ console.error(`Error initializing CKEditor5 instance with ID "${t}":`, e), this.editorPromise = null, m.the.error(t, e);
1109
1168
  }
1110
1169
  }
1111
1170
  /**
@@ -1118,7 +1177,7 @@ class bt extends HTMLElement {
1118
1177
  const t = await this.editorPromise;
1119
1178
  if (!t)
1120
1179
  return;
1121
- const e = ct(t), i = pt(t);
1180
+ const e = ht(t), i = yt(t);
1122
1181
  e ? e.state !== "unavailable" && await e.context.remove(e.editorContextId) : i ? await i.destroy() : await t.destroy();
1123
1182
  } finally {
1124
1183
  this.editorPromise = null;
@@ -1128,82 +1187,88 @@ class bt extends HTMLElement {
1128
1187
  * Creates the CKEditor instance.
1129
1188
  */
1130
1189
  async createEditor() {
1131
- const t = this.getAttribute("data-cke-editor-id"), e = JSON.parse(this.getAttribute("data-cke-preset")), i = this.getAttribute("data-cke-context-id"), a = JSON.parse(this.getAttribute("data-cke-root-attributes") || "{}"), n = this.getAttribute("data-cke-editable-height") ? Number.parseInt(this.getAttribute("data-cke-editable-height"), 10) : null, o = Number.parseInt(this.getAttribute("data-cke-save-debounce-ms"), 10), s = JSON.parse(this.getAttribute("data-cke-language")), u = this.hasAttribute("data-cke-watchdog"), d = JSON.parse(this.getAttribute("data-cke-content")), {
1132
- customTranslations: c,
1190
+ const t = this.getAttribute("data-cke-editor-id"), e = JSON.parse(this.getAttribute("data-cke-preset")), i = this.getAttribute("data-cke-context-id"), a = JSON.parse(this.getAttribute("data-cke-root-attributes") || "{}"), n = this.getAttribute("data-cke-editable-height") ? Number.parseInt(this.getAttribute("data-cke-editable-height"), 10) : null, o = Number.parseInt(this.getAttribute("data-cke-save-debounce-ms"), 10), c = JSON.parse(this.getAttribute("data-cke-language")), u = this.hasAttribute("data-cke-watchdog"), s = JSON.parse(this.getAttribute("data-cke-content")), {
1191
+ customTranslations: d,
1133
1192
  editorType: l,
1134
- licenseKey: w,
1135
- config: { plugins: y, ...b }
1136
- } = e;
1137
- let f = await U(l);
1138
- const p = await (i ? v.the.waitFor(i) : null);
1139
- if (u && !p) {
1140
- const m = await ht(f);
1141
- ({ Constructor: f } = m), m.watchdog.on("restart", () => {
1142
- const k = m.watchdog.editor;
1143
- this.editorPromise = Promise.resolve(k), h.the.register(t, k);
1144
- });
1145
- }
1146
- const { loadedPlugins: A, hasPremium: rt } = await H(y);
1147
- A.push(
1148
- await gt({
1149
- saveDebounceMs: o,
1150
- editorId: t,
1151
- targetElement: this
1152
- })
1153
- ), P(l) && A.push(
1154
- await yt(o)
1155
- );
1156
- const N = [
1157
- ...await K(s, rt),
1158
- G(c || {})
1159
- ].filter((m) => !T(m));
1160
- let C = {
1161
- ...d,
1162
- ..._(t)
1193
+ licenseKey: p,
1194
+ watchdogConfig: w,
1195
+ config: { plugins: y, ...E }
1196
+ } = e, h = await J(l), v = await (i ? C.the.waitFor(i) : null), q = async () => {
1197
+ const { loadedPlugins: g, hasPremium: T } = await Q(y);
1198
+ g.push(
1199
+ await vt({
1200
+ saveDebounceMs: o,
1201
+ editorId: t,
1202
+ targetElement: this
1203
+ })
1204
+ ), O(l) && g.push(
1205
+ await At(o)
1206
+ );
1207
+ const A = [
1208
+ ...await Z(c, T),
1209
+ tt(d || {})
1210
+ ].filter((f) => !N(f));
1211
+ let I = {
1212
+ ...s,
1213
+ ...G(t)
1214
+ };
1215
+ O(l) && (I = I.main || "");
1216
+ const P = await (async () => {
1217
+ let f = et(t);
1218
+ if (!f.main) {
1219
+ const B = O(l) ? ["main"] : Object.keys(I);
1220
+ it(f, B) || (f = await It(t, B), I = {
1221
+ ...s,
1222
+ ...G(t)
1223
+ });
1224
+ }
1225
+ O(l) && "main" in f && (f = f.main);
1226
+ let R = S(E);
1227
+ R = M([...A].reverse(), c.ui, R);
1228
+ const j = {
1229
+ ...R,
1230
+ initialData: I,
1231
+ licenseKey: p,
1232
+ plugins: g,
1233
+ language: c,
1234
+ ...A.length && {
1235
+ translations: A
1236
+ }
1237
+ };
1238
+ return !v || !(f instanceof HTMLElement) ? h.create(f, j) : (await mt({
1239
+ context: v,
1240
+ element: f,
1241
+ creator: h,
1242
+ config: j
1243
+ })).editor;
1244
+ })();
1245
+ return N(a) || P.model.change((f) => {
1246
+ f.setAttributes(a, P.model.document.getRoot());
1247
+ }), O(l) && n && gt(P, n), P;
1163
1248
  };
1164
- P(l) && (C = C.main || "");
1165
- const I = await (async () => {
1166
- let m = Y(t);
1167
- if (!m.main) {
1168
- const L = P(l) ? ["main"] : Object.keys(C);
1169
- Q(m, L) || (m = await Et(t, L), C = {
1170
- ...d,
1171
- ..._(t)
1172
- });
1173
- }
1174
- P(l) && "main" in m && (m = m.main);
1175
- let k = O(b);
1176
- k = S([...N].reverse(), s.ui, k);
1177
- const q = {
1178
- ...k,
1179
- initialData: C,
1180
- licenseKey: w,
1181
- plugins: A,
1182
- language: s,
1183
- ...N.length && {
1184
- translations: N
1249
+ if (u && !v) {
1250
+ const g = await bt(q, w);
1251
+ return g.on("error", (T, { causesRestart: U }) => {
1252
+ if (U) {
1253
+ const A = m.the.getItem(t);
1254
+ A && (dt(A), m.the.unregister(t));
1185
1255
  }
1186
- };
1187
- return !p || !(m instanceof HTMLElement) ? f.create(m, q) : (await st({
1188
- context: p,
1189
- element: m,
1190
- creator: f,
1191
- config: q
1192
- })).editor;
1193
- })();
1194
- return T(a) || I.model.change((m) => {
1195
- m.setAttributes(a, I.model.document.getRoot());
1196
- }), P(l) && n && mt(I, n), I;
1256
+ }), g.on("restart", () => {
1257
+ const T = g.editor;
1258
+ m.the.register(t, T);
1259
+ }), await g.create({}), g.editor;
1260
+ }
1261
+ return q();
1197
1262
  }
1198
1263
  }
1199
- function Q(r, t) {
1264
+ function it(r, t) {
1200
1265
  return t.every((e) => r[e]);
1201
1266
  }
1202
- async function Et(r, t) {
1203
- return ot(
1267
+ async function It(r, t) {
1268
+ return lt(
1204
1269
  () => {
1205
- const e = Y(r);
1206
- if (!Q(e, t))
1270
+ const e = et(r);
1271
+ if (!it(e, t))
1207
1272
  throw new Error(
1208
1273
  `It looks like not all required root elements are present yet.
1209
1274
  * If you want to wait for them, ensure they are registered before editor initialization.
@@ -1215,34 +1280,36 @@ Missing roots: ${t.filter((i) => !e[i]).join(", ")}.`
1215
1280
  { timeOutAfter: 2e3, retryAfter: 100 }
1216
1281
  );
1217
1282
  }
1218
- class kt extends HTMLElement {
1283
+ class Ot extends HTMLElement {
1219
1284
  /**
1220
- * The promise that resolves when the UI part is mounted.
1285
+ * Stops observing the editor registry and immediately runs any pending cleanup.
1221
1286
  */
1222
- mountedPromise = null;
1287
+ unmountEffect = null;
1223
1288
  /**
1224
1289
  * Mounts the UI part component.
1225
1290
  */
1226
1291
  async connectedCallback() {
1227
- await D();
1228
- const t = this.getAttribute("data-cke-editor-id") || F()[0], e = this.getAttribute("data-cke-name");
1229
- !t || !e || (this.style.display = "block", this.mountedPromise = h.the.execute(t, (i) => {
1292
+ await x();
1293
+ const t = this.getAttribute("data-cke-editor-id") || _()[0], e = this.getAttribute("data-cke-name");
1294
+ !t || !e || (this.style.display = "block", this.unmountEffect = m.the.mountEffect(t, (i) => {
1230
1295
  if (!this.isConnected)
1231
1296
  return;
1232
- const { ui: a } = i, n = vt(e), o = a.view[n];
1297
+ const { ui: a } = i, n = Tt(e), o = a.view[n];
1233
1298
  if (!o)
1234
- throw new E(`Unknown UI part name: "${e}". Supported names are "toolbar" and "menubar".`);
1235
- this.appendChild(o.element);
1299
+ throw new k(`Unknown UI part name: "${e}". Supported names are "toolbar" and "menubar".`);
1300
+ return this.appendChild(o.element), () => {
1301
+ this.innerHTML = "";
1302
+ };
1236
1303
  }));
1237
1304
  }
1238
1305
  /**
1239
1306
  * Destroys the UI part component. Unmounts UI parts from the editor.
1240
1307
  */
1241
- async disconnectedCallback() {
1242
- this.style.display = "none", await this.mountedPromise, this.mountedPromise = null, this.innerHTML = "";
1308
+ disconnectedCallback() {
1309
+ this.style.display = "none", this.unmountEffect?.(), this.unmountEffect = null;
1243
1310
  }
1244
1311
  }
1245
- function vt(r) {
1312
+ function Tt(r) {
1246
1313
  switch (r) {
1247
1314
  case "toolbar":
1248
1315
  return "toolbar";
@@ -1253,23 +1320,23 @@ function vt(r) {
1253
1320
  return null;
1254
1321
  }
1255
1322
  }
1256
- const At = {
1257
- "cke5-editor": bt,
1258
- "cke5-context": wt,
1259
- "cke5-ui-part": kt,
1260
- "cke5-editable": ft
1323
+ const Pt = {
1324
+ "cke5-editor": Ct,
1325
+ "cke5-context": Et,
1326
+ "cke5-ui-part": Ot,
1327
+ "cke5-editable": kt
1261
1328
  };
1262
- function Ct() {
1263
- for (const [r, t] of Object.entries(At))
1329
+ function Nt() {
1330
+ for (const [r, t] of Object.entries(Pt))
1264
1331
  window.customElements.get(r) || window.customElements.define(r, t);
1265
1332
  }
1266
- function xt(r) {
1267
- return x(r), {
1333
+ function Vt(r) {
1334
+ return D(r), {
1268
1335
  unmount() {
1269
1336
  }
1270
1337
  };
1271
1338
  }
1272
- function Z(r, t) {
1339
+ function at(r, t) {
1273
1340
  const e = {
1274
1341
  /** Value received from Blazor while the editor was focused, pending application on blur. */
1275
1342
  pendingValue: null,
@@ -1277,8 +1344,8 @@ function Z(r, t) {
1277
1344
  lastSyncedValue: null
1278
1345
  }, i = () => {
1279
1346
  e.pendingValue = null;
1280
- }, a = (n, o, s) => {
1281
- if (s || e.pendingValue === null)
1347
+ }, a = (n, o, c) => {
1348
+ if (c || e.pendingValue === null)
1282
1349
  return;
1283
1350
  const u = t.getCurrentValue();
1284
1351
  t.isEqual(u, e.pendingValue) || t.applyValue(e.pendingValue), e.pendingValue = null;
@@ -1315,7 +1382,7 @@ function Z(r, t) {
1315
1382
  }
1316
1383
  };
1317
1384
  }
1318
- function tt() {
1385
+ function nt() {
1319
1386
  return {
1320
1387
  unmount() {
1321
1388
  },
@@ -1326,7 +1393,7 @@ function tt() {
1326
1393
  }
1327
1394
  };
1328
1395
  }
1329
- function et(r, t) {
1396
+ function ot(r, t) {
1330
1397
  const e = /* @__PURE__ */ new Set();
1331
1398
  return (i) => {
1332
1399
  r.model.enqueueChange({ isUndoable: !1 }, (a) => {
@@ -1334,89 +1401,87 @@ function et(r, t) {
1334
1401
  if (n) {
1335
1402
  for (const o of e)
1336
1403
  i && o in i || (a.removeAttribute(o, n), e.delete(o));
1337
- for (const [o, s] of Object.entries(i ?? {}))
1338
- a.setAttribute(o, s, n), e.add(o);
1404
+ for (const [o, c] of Object.entries(i ?? {}))
1405
+ a.setAttribute(o, c, n), e.add(o);
1339
1406
  }
1340
1407
  });
1341
1408
  };
1342
1409
  }
1343
- function Nt(r, t) {
1344
- const e = r.getAttribute("data-cke-editor-id") ?? F()[0], i = r.getAttribute("data-cke-root-name") ?? "main";
1345
- let a = !1, n = null, o = tt(), s = null;
1346
- const u = (c) => {
1347
- if (!(c instanceof g) || c.detail.editorId !== e)
1410
+ function zt(r, t) {
1411
+ const e = r.getAttribute("data-cke-editor-id") ?? _()[0], i = r.getAttribute("data-cke-root-name") ?? "main";
1412
+ let a = !1, n = null, o = null, c = nt(), u = null;
1413
+ const s = (d) => {
1414
+ if (!(d instanceof b) || d.detail.editorId !== e)
1348
1415
  return;
1349
- const l = c.detail.roots[i];
1350
- l !== void 0 && o.shouldNotify(l) && t.invokeMethodAsync("OnChangeEditableData", n, l);
1416
+ const l = d.detail.roots[i];
1417
+ l !== void 0 && c.shouldNotify(l) && t.invokeMethodAsync("OnChangeEditableData", o, l);
1351
1418
  };
1352
- return (async () => {
1353
- const c = await h.the.waitFor(e);
1354
- n = DotNet.createJSObjectReference(c), o = Z(c, {
1355
- getCurrentValue: () => c.getData({ rootName: i }) ?? "",
1356
- applyValue: (l) => c.setData({ [i]: l }),
1357
- isEqual: (l, w) => l === w
1358
- }), s = et(c, i);
1359
- })(), document.body.addEventListener(g.EVENT_NAME, u), x(r), {
1419
+ return n = m.the.mountEffect(e, (d) => (o = globalThis.DotNet.createJSObjectReference(d), c = at(d, {
1420
+ getCurrentValue: () => d.getData({ rootName: i }) ?? "",
1421
+ applyValue: (l) => d.setData({ [i]: l }),
1422
+ isEqual: (l, p) => l === p
1423
+ }), u = ot(d, i), () => {
1424
+ c.unmount(), o && (globalThis.DotNet?.disposeJSObjectReference(o), o = null), u = null;
1425
+ })), document.body.addEventListener(b.EVENT_NAME, s), D(r), {
1360
1426
  /**
1361
1427
  * Cleans up all event listeners when the Blazor component is disposed.
1362
1428
  */
1363
1429
  unmount() {
1364
- a || (document.body.removeEventListener(g.EVENT_NAME, u), o.unmount(), n && (DotNet.disposeJSObjectReference(n), n = null), s = null, a = !0);
1430
+ a || (document.body.removeEventListener(b.EVENT_NAME, s), n?.(), n = null, a = !0);
1365
1431
  },
1366
1432
  /**
1367
1433
  * Updates this editable root's data from Blazor.
1368
1434
  * If the editor is focused, the update is deferred until blur to avoid interrupting the user.
1369
1435
  */
1370
- setValue: async (c) => {
1371
- a || (await h.the.waitFor(e), o.setValue(c));
1436
+ setValue: async (d) => {
1437
+ a || (await m.the.waitFor(e), c.setValue(d));
1372
1438
  },
1373
1439
  /**
1374
1440
  * Updates the root attributes on the editor. This is useful when the Blazor component
1375
1441
  * re-renders with new root attributes.
1376
1442
  */
1377
- setRootAttributes: async (c) => {
1378
- a || (await h.the.waitFor(e), s?.(c));
1443
+ setRootAttributes: async (d) => {
1444
+ a || (await m.the.waitFor(e), u?.(d));
1379
1445
  }
1380
1446
  };
1381
1447
  }
1382
- function zt(r, t) {
1448
+ function $t(r, t) {
1383
1449
  const e = r.getAttribute("data-cke-editor-id");
1384
- let i = !1, a = null, n = tt(), o = null, s = null;
1385
- const u = (c) => {
1386
- !(c instanceof g) || c.detail.editorId !== e || n.shouldNotify(c.detail.roots) && t.invokeMethodAsync("OnChangeEditorData", s, c.detail.roots);
1450
+ let i = !1, a = null, n = nt(), o = null, c = null;
1451
+ const u = (s) => {
1452
+ !(s instanceof b) || s.detail.editorId !== e || n.shouldNotify(s.detail.roots) && t.invokeMethodAsync("OnChangeEditorData", c, s.detail.roots);
1387
1453
  };
1388
- return (async () => {
1389
- const c = await h.the.waitFor(e);
1390
- s = globalThis.DotNet.createJSObjectReference(c), n = Z(c, {
1391
- getCurrentValue: () => J(c),
1392
- applyValue: (w) => c.setData(w),
1393
- isEqual: at
1394
- }), o = et(c, "main");
1395
- const l = (w, y, b) => {
1396
- const f = b ? "OnEditorFocus" : "OnEditorBlur";
1397
- t.invokeMethodAsync(f, s);
1454
+ return a = m.the.mountEffect(e, (s) => {
1455
+ c = globalThis.DotNet.createJSObjectReference(s), n = at(s, {
1456
+ getCurrentValue: () => X(s),
1457
+ applyValue: (l) => s.setData(l),
1458
+ isEqual: ct
1459
+ }), o = ot(s, "main");
1460
+ const d = (l, p, w) => {
1461
+ const y = w ? "OnEditorFocus" : "OnEditorBlur";
1462
+ t.invokeMethodAsync(y, c);
1398
1463
  };
1399
- c.ui.focusTracker.on("change:isFocused", l), t.invokeMethodAsync("OnEditorReady", s), a = () => {
1400
- c.ui.focusTracker.off("change:isFocused", l);
1464
+ return s.ui.focusTracker.on("change:isFocused", d), t.invokeMethodAsync("OnEditorReady", c), () => {
1465
+ s.ui.focusTracker.off("change:isFocused", d), n.unmount(), c && (globalThis.DotNet?.disposeJSObjectReference(c), c = null), o = null;
1401
1466
  };
1402
- })(), document.body.addEventListener(g.EVENT_NAME, u), Ct(), x(r), {
1467
+ }), document.body.addEventListener(b.EVENT_NAME, u), Nt(), D(r), {
1403
1468
  /**
1404
1469
  * Updates the editor data from Blazor. If the editor is focused, the update is deferred until blur to avoid interrupting the user.
1405
1470
  */
1406
- setValue: async (c) => {
1407
- i || (await h.the.waitFor(e), n.setValue(c));
1471
+ setValue: async (s) => {
1472
+ i || (await m.the.waitFor(e), n.setValue(s));
1408
1473
  },
1409
1474
  /**
1410
1475
  * Updates the root attributes on the editor instance.
1411
1476
  */
1412
- setRootAttributes: async (c) => {
1413
- i || (await h.the.waitFor(e), o?.(c));
1477
+ setRootAttributes: async (s) => {
1478
+ i || (await m.the.waitFor(e), o?.(s));
1414
1479
  },
1415
1480
  /**
1416
1481
  * Cleans up all event listeners when the Blazor component is disposed.
1417
1482
  */
1418
1483
  unmount() {
1419
- i || (document.body.removeEventListener(g.EVENT_NAME, u), n.unmount(), a?.(), s && (globalThis.DotNet.disposeJSObjectReference(s), s = null), o = null, i = !0);
1484
+ i || (document.body.removeEventListener(b.EVENT_NAME, u), a?.(), a = null, i = !0);
1420
1485
  },
1421
1486
  /**
1422
1487
  * Installs the custom image upload adapter that delegates uploads to Blazor.
@@ -1426,12 +1491,12 @@ function zt(r, t) {
1426
1491
  attachImageUploadAdapter: async () => {
1427
1492
  if (i)
1428
1493
  return;
1429
- const c = await h.the.waitFor(e);
1430
- Pt(c, t);
1494
+ const s = await m.the.waitFor(e);
1495
+ St(s, t);
1431
1496
  }
1432
1497
  };
1433
1498
  }
1434
- function Pt(r, t) {
1499
+ function St(r, t) {
1435
1500
  if (!r.plugins.has("FileRepository"))
1436
1501
  return;
1437
1502
  const e = r.plugins.get("FileRepository");
@@ -1442,16 +1507,16 @@ function Pt(r, t) {
1442
1507
  const n = await i.file;
1443
1508
  if (a)
1444
1509
  throw new Error("Upload aborted.");
1445
- const o = await It(n), s = await t.invokeMethodAsync("OnEditorImageUpload", {
1510
+ const o = await Mt(n), c = await t.invokeMethodAsync("OnEditorImageUpload", {
1446
1511
  fileName: n.name,
1447
1512
  mimeType: n.type,
1448
1513
  payload: o
1449
1514
  });
1450
- if (!s)
1515
+ if (!c)
1451
1516
  throw new Error(
1452
1517
  "OnImageUpload handler returned null. Make sure the OnImageUpload parameter is set on the <CKE5Editor> component."
1453
1518
  );
1454
- return { default: s };
1519
+ return { default: c };
1455
1520
  },
1456
1521
  abort() {
1457
1522
  a = !0;
@@ -1459,7 +1524,7 @@ function Pt(r, t) {
1459
1524
  };
1460
1525
  };
1461
1526
  }
1462
- function It(r) {
1527
+ function Mt(r) {
1463
1528
  return new Promise((t, e) => {
1464
1529
  const i = new FileReader();
1465
1530
  i.onload = () => {
@@ -1468,25 +1533,25 @@ function It(r) {
1468
1533
  }, i.onerror = () => e(i.error), i.readAsDataURL(r);
1469
1534
  });
1470
1535
  }
1471
- function Vt(r) {
1472
- return x(r), {
1536
+ function Wt(r) {
1537
+ return D(r), {
1473
1538
  unmount() {
1474
1539
  }
1475
1540
  };
1476
1541
  }
1477
1542
  export {
1478
- E as CKEditor5BlazorError,
1479
- g as CKEditor5ChangeDataEvent,
1480
- v as ContextsRegistry,
1481
- W as CustomEditorPluginsRegistry,
1482
- ft as EditableComponentElement,
1483
- bt as EditorComponentElement,
1484
- h as EditorsRegistry,
1485
- kt as UIPartComponentElement,
1486
- xt as createContextBlazorInterop,
1487
- Nt as createEditableBlazorInterop,
1488
- zt as createEditorBlazorInterop,
1489
- Vt as createUIPartBlazorInterop,
1490
- Ct as ensureEditorElementsRegistered
1543
+ k as CKEditor5BlazorError,
1544
+ b as CKEditor5ChangeDataEvent,
1545
+ C as ContextsRegistry,
1546
+ F as CustomEditorPluginsRegistry,
1547
+ kt as EditableComponentElement,
1548
+ Ct as EditorComponentElement,
1549
+ m as EditorsRegistry,
1550
+ Ot as UIPartComponentElement,
1551
+ Vt as createContextBlazorInterop,
1552
+ zt as createEditableBlazorInterop,
1553
+ $t as createEditorBlazorInterop,
1554
+ Wt as createUIPartBlazorInterop,
1555
+ Nt as ensureEditorElementsRegistered
1491
1556
  };
1492
1557
  //# sourceMappingURL=index.mjs.map