{"version":3,"file":"index.cjs","sources":["../src/shared/async-registry.ts","../src/shared/camel-case.ts","../src/shared/debounce.ts","../src/shared/is-plain-object.ts","../src/shared/deep-camel-case-keys.ts","../src/shared/filter-object-values.ts","../src/shared/get-csrf-token.ts","../src/shared/hook.ts","../src/shared/is-empty-object.ts","../src/shared/is-nil.ts","../src/shared/map-object-values.ts","../src/shared/parse-int-if-not-null.ts","../src/shared/parse-json-if-present.ts","../src/shared/shallow-equal.ts","../src/shared/uid.ts","../src/shared/wait-for.ts","../src/hooks/editor/utils/create-editor-in-context.ts","../src/hooks/editor/utils/is-single-root-editor.ts","../src/hooks/editor/utils/load-editor-constructor.ts","../src/hooks/editor/custom-editor-plugins.ts","../src/hooks/editor/utils/load-editor-plugins.ts","../src/hooks/editor/utils/load-editor-translations.ts","../src/hooks/editor/utils/normalize-custom-translations.ts","../src/hooks/editor/utils/query-all-editor-editables.ts","../src/hooks/editor/typings.ts","../src/hooks/editor/utils/read-preset-or-throw.ts","../src/hooks/editor/utils/resolve-editor-config-elements-references.ts","../src/hooks/editor/utils/resolve-editor-config-translations.ts","../src/hooks/editor/utils/set-editor-editable-height.ts","../src/hooks/editor/utils/wrap-with-watchdog.ts","../src/hooks/context/contexts-registry.ts","../src/hooks/context/utils/read-context-config-or-throw.ts","../src/hooks/context/context.ts","../src/hooks/editor/editors-registry.ts","../src/hooks/editable.ts","../src/hooks/editor/plugins/phoenix-upload-adapter.ts","../src/hooks/editor/plugins/sync-editor-with-input.ts","../src/hooks/editor/plugins/sync-editor-with-phoenix.ts","../src/hooks/editor/editor.ts","../src/hooks/root-value-sentinel/root-attributes-updater.ts","../src/hooks/root-value-sentinel/root-value-sentinel.ts","../src/hooks/ui-part.ts","../src/hooks/index.ts"],"sourcesContent":["/**\n * Generic async registry for objects with an async destroy method.\n * Provides a way to register, unregister, and execute callbacks on objects by ID.\n */\nexport class AsyncRegistry<T extends Destructible> {\n  /**\n   * Map of registered items.\n   */\n  private readonly items = new Map<RegistryId | null, T>();\n\n  /**\n   * Map of initialization errors for items that failed to register.\n   */\n  private readonly initializationErrors = new Map<RegistryId | null, any>();\n\n  /**\n   * Map of pending callbacks waiting for items to be registered or fail.\n   */\n  private readonly pendingCallbacks = new Map<RegistryId | null, PendingCallbacks<T>>();\n\n  /**\n   * Set of watchers that observe changes to the registry.\n   */\n  private readonly watchers = new Set<RegistryWatcher<T>>();\n\n  /**\n   * Executes a function on an item.\n   * If the item is not yet registered, it will wait for it to be registered.\n   *\n   * @param id The ID of the item.\n   * @param onSuccess The function to execute.\n   * @param onError Optional error callback.\n   * @returns A promise that resolves with the result of the function.\n   */\n  execute<R, E extends T = T>(\n    id: RegistryId | null,\n    onSuccess: (item: E) => R,\n    onError?: (error: any) => void,\n  ): Promise<Awaited<R>> {\n    const item = this.items.get(id);\n    const error = this.initializationErrors.get(id);\n\n    // If error exists and callback provided, invoke it immediately.\n    if (error) {\n      onError?.(error);\n      return Promise.reject(error);\n    }\n\n    // If item exists, invoke callback immediately (synchronously via Promise.resolve).\n    if (item) {\n      return Promise.resolve(onSuccess(item as E));\n    }\n\n    // Item not ready yet - queue the callbacks.\n    return new Promise((resolve, reject) => {\n      const pending = this.getPendingCallbacks(id);\n\n      pending.success.push(async (item: T) => {\n        resolve(await onSuccess(item as E));\n      });\n\n      if (onError) {\n        pending.error.push(onError);\n      }\n      else {\n        pending.error.push(reject);\n      }\n    });\n  }\n\n  /**\n   * Registers an item.\n   *\n   * @param id The ID of the item.\n   * @param item The item instance.\n   */\n  register(id: RegistryId | null, item: T): void {\n    if (this.items.has(id)) {\n      throw new Error(`Item with ID \"${id}\" is already registered.`);\n    }\n\n    this.resetErrors(id);\n    this.items.set(id, item);\n\n    // Execute all pending callbacks for this item (synchronously).\n    const pending = this.pendingCallbacks.get(id);\n\n    if (pending) {\n      pending.success.forEach(callback => callback(item));\n      this.pendingCallbacks.delete(id);\n    }\n\n    // Register the first item as the default item (null ID).\n    this.registerAsDefault(id, item);\n    this.notifyWatchers();\n  }\n\n  /**\n   * Registers an error for an item.\n   *\n   * @param id The ID of the item.\n   * @param error The error to register.\n   */\n  error(id: RegistryId | null, error: any): void {\n    this.items.delete(id);\n    this.initializationErrors.set(id, error);\n\n    // Execute all pending error callbacks for this item.\n    const pending = this.pendingCallbacks.get(id);\n\n    if (pending) {\n      pending.error.forEach(callback => callback(error));\n      this.pendingCallbacks.delete(id);\n    }\n\n    // Set as default error if this is the first error and no items exist.\n    if (this.initializationErrors.size === 1 && !this.items.size) {\n      this.error(null, error);\n    }\n\n    // Notify watchers about the error state.\n    this.notifyWatchers();\n  }\n\n  /**\n   * Resets errors for an item.\n   *\n   * @param id The ID of the item.\n   */\n  resetErrors(id: RegistryId | null): void {\n    const { initializationErrors } = this;\n\n    // Clear default error if it's the same as the specific error.\n    if (initializationErrors.has(null) && initializationErrors.get(null) === initializationErrors.get(id)) {\n      initializationErrors.delete(null);\n    }\n\n    initializationErrors.delete(id);\n  }\n\n  /**\n   * Un-registers an item.\n   *\n   * @param id The ID of the item.\n   */\n  unregister(id: RegistryId | null): void {\n    if (!this.items.has(id)) {\n      throw new Error(`Item with ID \"${id}\" is not registered.`);\n    }\n\n    // If unregistering the default item, clear it.\n    if (id && this.items.get(null) === this.items.get(id)) {\n      this.unregister(null);\n    }\n\n    this.items.delete(id);\n    this.pendingCallbacks.delete(id);\n\n    this.notifyWatchers();\n  }\n\n  /**\n   * Gets all registered items.\n   *\n   * @returns An array of all registered items.\n   */\n  getItems(): T[] {\n    return Array.from(this.items.values());\n  }\n\n  /**\n   * Checks if an item with the given ID is registered.\n   *\n   * @param id The ID of the item.\n   * @returns `true` if the item is registered, `false` otherwise.\n   */\n  hasItem(id: RegistryId | null): boolean {\n    return this.items.has(id);\n  }\n\n  /**\n   * Gets a promise that resolves with the item instance for the given ID.\n   * If the item is not registered yet, it will wait for it to be registered.\n   *\n   * @param id The ID of the item.\n   * @returns A promise that resolves with the item instance.\n   */\n  waitFor<E extends T = T>(id: RegistryId | null): Promise<E> {\n    return new Promise<E>((resolve, reject) => {\n      void this.execute(id, resolve as (value: E) => void, reject);\n    });\n  }\n\n  /**\n   * Destroys all registered items and clears the registry.\n   * This will call the `destroy` method on each item.\n   */\n  async destroyAll() {\n    const promises = (\n      Array\n        .from(new Set(this.items.values()))\n        .map(item => item.destroy())\n    );\n\n    this.items.clear();\n    this.pendingCallbacks.clear();\n\n    await Promise.all(promises);\n\n    this.notifyWatchers();\n  }\n\n  /**\n   * Registers a watcher that will be called whenever the registry changes.\n   *\n   * @param watcher The watcher function to register.\n   * @returns A function to unregister the watcher.\n   */\n  watch(watcher: RegistryWatcher<T>): () => void {\n    this.watchers.add(watcher);\n\n    // Call the watcher immediately with the current state.\n    watcher(\n      new Map(this.items),\n      new Map(this.initializationErrors),\n    );\n\n    return this.unwatch.bind(this, watcher);\n  }\n\n  /**\n   * Un-registers a watcher.\n   *\n   * @param watcher The watcher function to unregister.\n   */\n  unwatch(watcher: RegistryWatcher<T>): void {\n    this.watchers.delete(watcher);\n  }\n\n  /**\n   * Notifies all watchers about changes to the registry.\n   */\n  private notifyWatchers(): void {\n    this.watchers.forEach(\n      watcher => watcher(\n        new Map(this.items),\n        new Map(this.initializationErrors),\n      ),\n    );\n  }\n\n  /**\n   * Gets or creates pending callbacks for a specific ID.\n   *\n   * @param id The ID of the item.\n   * @returns The pending callbacks structure.\n   */\n  private getPendingCallbacks(id: RegistryId | null): PendingCallbacks<T> {\n    let pending = this.pendingCallbacks.get(id);\n\n    if (!pending) {\n      pending = { success: [], error: [] };\n      this.pendingCallbacks.set(id, pending);\n    }\n\n    return pending;\n  }\n\n  /**\n   * Registers an item as the default (null ID) item if it's the first one.\n   *\n   * @param id The ID of the item being registered.\n   * @param item The item instance.\n   */\n  private registerAsDefault(id: RegistryId | null, item: T): void {\n    if (this.items.size === 1 && id !== null) {\n      this.register(null, item);\n    }\n  }\n}\n\n/**\n * Interface for objects that can be destroyed.\n */\nexport type Destructible = {\n  destroy: () => Promise<any>;\n};\n\n/**\n * Identifier of the registry item.\n */\ntype RegistryId = string;\n\n/**\n * Structure holding pending success and error callbacks for an item.\n */\ntype PendingCallbacks<T> = {\n  success: Array<(item: T) => void>;\n  error: Array<(error: Error) => void>;\n};\n\n/**\n * Callback type for watching registry changes.\n */\ntype RegistryWatcher<T> = (\n  items: Map<RegistryId | null, T>,\n  errors: Map<RegistryId | null, Error>,\n) => void;\n","/**\n * Converts a string to camelCase.\n *\n * @param str The string to convert\n * @returns The camelCased string\n */\nexport function camelCase(str: string): string {\n  return str\n    .replace(/[-_\\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))\n    .replace(/^./, m => m.toLowerCase());\n}\n","export function debounce<T extends (...args: any[]) => any>(\n  delay: number,\n  callback: T,\n): (...args: Parameters<T>) => void {\n  let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n  return (...args: Parameters<T>): void => {\n    if (timeoutId) {\n      clearTimeout(timeoutId);\n    }\n\n    timeoutId = setTimeout(() => {\n      callback(...args);\n    }, delay);\n  };\n}\n","/**\n * Utility to check if a value is a plain object (not an array, not null, not a class instance).\n *\n * @param value The value to check.\n * @returns True if the value is a plain object, false otherwise.\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n  if (Object.prototype.toString.call(value) !== '[object Object]') {\n    return false;\n  }\n\n  const proto = Object.getPrototypeOf(value);\n\n  return proto === Object.prototype || proto === null;\n}\n","import { camelCase } from './camel-case';\nimport { isPlainObject } from './is-plain-object';\n\n/**\n * Recursively converts all keys of a plain object or array to camelCase.\n * Skips class instances and leaves them untouched.\n *\n * @param input The object or array to process\n */\nexport function deepCamelCaseKeys<T>(input: T): T {\n  if (Array.isArray(input)) {\n    return input.map(deepCamelCaseKeys) as unknown as T;\n  }\n\n  if (isPlainObject(input)) {\n    const result: Record<string, unknown> = Object.create(null);\n\n    for (const [key, value] of Object.entries(input)) {\n      result[camelCase(key)] = deepCamelCaseKeys(value);\n    }\n\n    return result as T;\n  }\n\n  return input;\n}\n","/**\n * Filters the values of an object based on a provided filter function.\n *\n * @param obj The object to filter.\n * @param filter The filter function that determines whether a value should be included.\n * @returns A new object containing only the key-value pairs that passed the filter.\n */\nexport function filterObjectValues<T>(\n  obj: Record<string, T>,\n  filter: (value: T, key: string) => boolean,\n): Record<string, T> {\n  const filteredEntries = Object\n    .entries(obj)\n    .filter(([key, value]) => filter(value, key));\n\n  return Object.fromEntries(filteredEntries);\n}\n","/**\n * Retrieves the CSRF token from the meta tag or cookie.\n *\n * @returns The CSRF token or null if not found.\n */\nexport function getCsrfToken(): string | null {\n  // Try to get from meta tag (Phoenix default).\n  const metaTag = document.querySelector('meta[name=\"csrf-token\"]');\n\n  if (metaTag) {\n    return metaTag.getAttribute('content');\n  }\n\n  // Try to get from cookie.\n  const match = document.cookie.match(/(?:^|; )_csrf_token=([^;]*)/);\n\n  return match ? decodeURIComponent(match[1]!) : null;\n}\n","import type { Hook } from 'phoenix_live_view';\n\nimport type { RequiredBy } from '../types';\n\n/**\n * An abstract class that provides a class-based API for creating Phoenix LiveView hooks.\n *\n * This class defines the structure and lifecycle methods of a hook, which can be extended\n * to implement custom client-side behavior that integrates with LiveView.\n */\nexport abstract class ClassHook {\n  /**\n   * The current state of the hook.\n   */\n  state: ClassHookState = 'mounting';\n\n  /**\n   * The DOM element the hook is attached to.\n   * It includes an `instance` property to hold the hook instance.\n   */\n  el: HTMLElement & { instance: Hook; };\n\n  /**\n   * Callbacks to run before the hook is destroyed.\n   */\n  private _beforeDestroyCallbacks: Array<() => void> = [];\n\n  /**\n   * Registers a callback to be called before the hook is destroyed.\n   * Callbacks are called in LIFO order (last registered, first called).\n   */\n  onBeforeDestroy(callback: () => void): void {\n    this._beforeDestroyCallbacks.push(callback);\n  }\n\n  /**\n   * Pushes an event from the client to the LiveView server process.\n   * @param _event The name of the event.\n   * @param _payload The data to send with the event.\n   * @param _callback An optional function to be called with the server's reply.\n   */\n  pushEvent!: (\n    _event: string,\n    _payload: any,\n    _callback?: (reply: any, ref: number) => void,\n  ) => void;\n\n  /**\n   * Pushes an event to another hook on the page.\n   * @param _selector The CSS selector of the target element with the hook.\n   * @param _event The name of the event.\n   * @param _payload The data to send with the event.\n   * @param _callback An optional function to be called with the reply.\n   */\n  pushEventTo!: (\n    _selector: string,\n    _event: string,\n    _payload: any,\n    _callback?: (reply: any, ref: number) => void,\n  ) => void;\n\n  /**\n   * Registers a handler for an event pushed from the server.\n   * @param _event The name of the event to handle.\n   * @param _callback The function to execute when the event is received.\n   */\n  handleEvent!: (\n    _event: string,\n    _callback: (payload: any) => void,\n  ) => void;\n\n  /**\n   * Called when the hook has been mounted to the DOM.\n   * This is the ideal place for initialization code.\n   */\n  mounted(): any {}\n\n  /**\n   * Called when the element has been removed from the DOM.\n   * Perfect for cleanup tasks.\n   */\n  destroyed(): any {}\n\n  /**\n   * Called when the element has been updated by a LiveView patch.\n   */\n  updated(): any {}\n\n  /**\n   * Called before the element is updated by a LiveView patch.\n   */\n  beforeUpdate?(): void;\n\n  /**\n   * Called when the client has disconnected from the server.\n   */\n  disconnected?(): void;\n\n  /**\n   * Called when the client has reconnected to the server.\n   */\n  reconnected?(): void;\n\n  /**\n   * Checks if the hook is in the process of being destroyed.\n   */\n  isBeingDestroyed(): boolean {\n    return this.state === 'destroyed' || this.state === 'destroying';\n  }\n\n  /**\n   * Runs all registered before-destroy callbacks and clears the list.\n   * Called internally by makeHook before destroyed().\n   */\n  _runBeforeDestroyCallbacks(): void {\n    for (const cb of this._beforeDestroyCallbacks.reverse()) {\n      cb();\n    }\n\n    this._beforeDestroyCallbacks = [];\n  }\n}\n\n/**\n * A type that represents the state of a class-based hook.\n */\nexport type ClassHookState = 'mounting' | 'mounted' | 'destroying' | 'destroyed';\n\n/**\n * A factory function that adapts a class-based hook to the object-based API expected by Phoenix LiveView.\n *\n * @param constructor The constructor of the class that extends the `Hook` abstract class.\n */\nexport function makeHook(constructor: new () => ClassHook): RequiredBy<Hook<any>, 'mounted' | 'destroyed'> {\n  return {\n    /**\n     * The mounted lifecycle callback for the LiveView hook object.\n     * It creates an instance of the user-defined hook class and sets up the necessary properties and methods.\n     */\n    async mounted(this: any) {\n      const instance = new constructor();\n\n      this.el.instance = instance;\n\n      instance.el = this.el;\n\n      instance.pushEvent = (event, payload, callback) => this.pushEvent?.(event, payload, callback);\n      instance.pushEventTo = (selector, event, payload, callback) => this.pushEventTo?.(selector, event, payload, callback);\n      instance.handleEvent = (event, callback) => this.handleEvent?.(event, callback);\n\n      instance.state = 'mounting';\n      const result = await instance.mounted?.();\n      instance.state = 'mounted';\n\n      return result;\n    },\n\n    /**\n     * The beforeUpdate lifecycle callback that delegates to the hook instance.\n     */\n    beforeUpdate(this: any) {\n      this.el.instance.beforeUpdate?.();\n    },\n\n    /**\n     * The destroyed lifecycle callback that delegates to the hook instance.\n     */\n    async destroyed(this: any) {\n      const { instance } = this.el;\n\n      instance.state = 'destroying';\n      instance._runBeforeDestroyCallbacks();\n      await instance.destroyed?.();\n      instance.state = 'destroyed';\n    },\n\n    /**\n     * The disconnected lifecycle callback that delegates to the hook instance.\n     */\n    disconnected(this: any) {\n      this.el.instance.disconnected?.();\n    },\n\n    /**\n     * The reconnected lifecycle callback that delegates to the hook instance.\n     */\n    reconnected(this: any) {\n      this.el.instance.reconnected?.();\n    },\n\n    /**\n     * The updated lifecycle callback that delegates to the hook instance.\n     */\n    updated(this: any) {\n      this.el.instance.updated?.();\n    },\n  };\n}\n","export function isEmptyObject(obj: Record<string, unknown>): boolean {\n  return Object.keys(obj).length === 0 && obj.constructor === Object;\n}\n","export function isNil(value: any): value is null | undefined {\n  return value === null || value === undefined;\n}\n","/**\n * Maps the values of an object using a provided mapper function.\n *\n * @param obj The object whose values will be mapped.\n * @param mapper A function that takes a value and its key, and returns a new value.\n * @template T The type of the original values in the object.\n * @template U The type of the new values in the object.\n * @returns A new object with the same keys as the original, but with values transformed by\n */\nexport function mapObjectValues<T, U>(\n  obj: Record<string, T>,\n  mapper: (value: T, key: string) => U,\n): Record<string, U> {\n  const mappedEntries = Object\n    .entries(obj)\n    .map(([key, value]) => [key, mapper(value, key)] as const);\n\n  return Object.fromEntries(mappedEntries);\n}\n","export function parseIntIfNotNull(value: string | null): number | null {\n  if (value === null) {\n    return null;\n  }\n\n  const parsed = Number.parseInt(value, 10);\n\n  return Number.isNaN(parsed) ? null : parsed;\n}\n","/**\n * Parses a JSON string if it is provided.\n *\n * Returns `null` when the input is `null`, `undefined` or an empty string.\n * Otherwise it parses the string using `JSON.parse` and returns the parsed value.\n *\n * @throws SyntaxError when the input is not valid JSON.\n */\nexport function parseJsonIfPresent<T = unknown>(json: string | null | undefined): T | null {\n  if (json == null || json.trim() === '') {\n    return null;\n  }\n\n  return JSON.parse(json) as T;\n}\n","/**\n * Performs a shallow comparison of two objects.\n *\n * @param objA - The first object to compare.\n * @param objB - The second object to compare.\n * @returns True if the objects are shallowly equal, false otherwise.\n */\nexport function shallowEqual<T extends Record<string, unknown>>(\n  objA: T,\n  objB: T,\n): boolean {\n  if (objA === objB) {\n    return true;\n  }\n\n  const keysA = Object.keys(objA);\n  const keysB = Object.keys(objB);\n\n  if (keysA.length !== keysB.length) {\n    return false;\n  }\n\n  for (const key of keysA) {\n    if (objA[key] !== objB[key] || !Object.prototype.hasOwnProperty.call(objB, key)) {\n      return false;\n    }\n  }\n\n  return true;\n}\n","/**\n * Generates a unique identifier string\n *\n * @returns Random string that can be used as unique identifier\n */\nexport function uid() {\n  return Math.random().toString(36).substring(2);\n}\n","import type { CanBePromise } from '../types';\n\n/**\n * Waits for the provided callback to succeed. The callback is executed multiple times until it succeeds or the timeout is reached.\n * It's executed immediately and then with a delay defined by the `retry` option.\n *\n * @param callback The callback to execute.\n * @param config Configuration for the function.\n * @param config.timeOutAfter The maximum time to wait for the callback to succeed, in milliseconds. Default is 500ms.\n * @param config.retryAfter The time to wait between retries, in milliseconds. Default is 100ms.\n * @returns A promise that resolves when the callback succeeds.\n */\nexport function waitFor<R>(\n  callback: () => CanBePromise<R>,\n  {\n    timeOutAfter = 500,\n    retryAfter = 100,\n  }: WaitForConfig = {},\n): Promise<R> {\n  return new Promise<R>((resolve, reject) => {\n    const startTime = Date.now();\n    let lastError: Error | null = null;\n\n    const timeoutTimerId = setTimeout(() => {\n      reject(lastError ?? new Error('Timeout'));\n    }, timeOutAfter);\n\n    const tick = async () => {\n      try {\n        const result = await callback();\n        clearTimeout(timeoutTimerId);\n        resolve(result);\n      }\n      catch (err: any) {\n        lastError = err;\n\n        if (Date.now() - startTime > timeOutAfter) {\n          reject(err);\n        }\n        else {\n          setTimeout(tick, retryAfter);\n        }\n      }\n    };\n\n    void tick();\n  });\n}\n\n/**\n * Configuration for the `waitFor` function.\n */\nexport type WaitForConfig = {\n  timeOutAfter?: number;\n  retryAfter?: number;\n};\n","import type { Context, ContextWatchdog, Editor, EditorConfig } from 'ckeditor5';\n\nimport type { EditorCreator } from './wrap-with-watchdog';\n\nimport { uid } from '../../../shared';\n\n/**\n * Symbol used to store the context watchdog on the editor instance.\n * Internal use only.\n */\nconst CONTEXT_EDITOR_WATCHDOG_SYMBOL = Symbol.for('context-editor-watchdog');\n\n/**\n * Creates a CKEditor 5 editor instance within a given context watchdog.\n *\n * @param params Parameters for editor creation.\n * @param params.element The DOM element or data for the editor.\n * @param params.context The context watchdog instance.\n * @param params.creator The editor creator utility.\n * @param params.config The editor configuration object.\n * @returns The created editor instance.\n */\nexport async function createEditorInContext({ element, context, creator, config }: Attrs) {\n  const editorContextId = uid();\n\n  await context.add({\n    creator: (_element, _config) => creator.create(_element, _config),\n    id: editorContextId,\n    sourceElementOrData: element,\n    type: 'editor',\n    config,\n  });\n\n  const editor = context.getItem(editorContextId) as Editor;\n  const contextDescriptor: EditorContextDescriptor = {\n    state: 'available',\n    editorContextId,\n    context,\n  };\n\n  (editor as any)[CONTEXT_EDITOR_WATCHDOG_SYMBOL] = contextDescriptor;\n\n  // Destroying of context is async. There can be situation when the destroy of the context\n  // and the destroy of the editor is called in parallel. It often happens during unmounting of\n  // phoenix hooks. Let's make sure that descriptor informs other components, that context is being\n  // destroyed.\n  const originalDestroy = context.destroy.bind(context);\n  context.destroy = async () => {\n    contextDescriptor.state = 'unavailable';\n    return originalDestroy();\n  };\n\n  return {\n    ...contextDescriptor,\n    editor,\n  };\n}\n\n/**\n * Retrieves the context watchdog from an editor instance, if available.\n *\n * @param editor The editor instance.\n * @returns The context watchdog or null if not found.\n */\nexport function unwrapEditorContext(editor: Editor): EditorContextDescriptor | null {\n  if (CONTEXT_EDITOR_WATCHDOG_SYMBOL in editor) {\n    return (editor as any)[CONTEXT_EDITOR_WATCHDOG_SYMBOL];\n  }\n\n  return null;\n}\n\n/**\n * Parameters for creating an editor in a context.\n */\ntype Attrs = {\n  context: ContextWatchdog<Context>;\n  creator: EditorCreator;\n  element: HTMLElement;\n  config: EditorConfig;\n};\n\n/**\n * Descriptor for an editor context.\n */\ntype EditorContextDescriptor = {\n  state: 'available' | 'unavailable';\n  editorContextId: string;\n  context: ContextWatchdog<Context>;\n};\n","import type { EditorType } from '../typings';\n\n/**\n * Checks if the given editor type is one of the single editing-like editors.\n *\n * @param editorType - The type of the editor to check.\n * @returns `true` if the editor type is 'inline', 'classic', or 'balloon', otherwise `false`.\n */\nexport function isSingleRootEditor(editorType: EditorType): boolean {\n  return ['inline', 'classic', 'balloon', 'decoupled'].includes(editorType);\n}\n","import type { EditorType } from '../typings';\n\n/**\n * Returns the constructor for the specified CKEditor5 editor type.\n *\n * @param type - The type of the editor to load.\n * @returns A promise that resolves to the editor constructor.\n */\nexport async function loadEditorConstructor(type: EditorType) {\n  const PKG = await import('ckeditor5');\n\n  const editorMap = {\n    inline: PKG.InlineEditor,\n    balloon: PKG.BalloonEditor,\n    classic: PKG.ClassicEditor,\n    decoupled: PKG.DecoupledEditor,\n    multiroot: PKG.MultiRootEditor,\n  } as const;\n\n  const EditorConstructor = editorMap[type];\n\n  if (!EditorConstructor) {\n    throw new Error(`Unsupported editor type: ${type}`);\n  }\n\n  return EditorConstructor;\n}\n","import type { PluginConstructor } from 'ckeditor5';\n\nimport type { CanBePromise } from '../../types';\n\ntype PluginReader = () => CanBePromise<PluginConstructor>;\n\n/**\n * Registry for custom CKEditor plugins.\n * Allows registration and retrieval of custom plugins that can be used alongside built-in plugins.\n */\nexport class CustomEditorPluginsRegistry {\n  static readonly the = new CustomEditorPluginsRegistry();\n\n  /**\n   * Map of registered custom plugins.\n   */\n  private readonly plugins = new Map<string, PluginReader>();\n\n  /**\n   * Private constructor to enforce singleton pattern.\n   */\n  private constructor() {}\n\n  /**\n   * Registers a custom plugin for the CKEditor.\n   *\n   * @param name The name of the plugin.\n   * @param reader The plugin reader function that returns the plugin constructor.\n   * @returns A function to unregister the plugin.\n   */\n  register(name: string, reader: PluginReader): () => void {\n    if (this.plugins.has(name)) {\n      throw new Error(`Plugin with name \"${name}\" is already registered.`);\n    }\n\n    this.plugins.set(name, reader);\n\n    return this.unregister.bind(this, name);\n  }\n\n  /**\n   * Removes a custom plugin by its name.\n   *\n   * @param name The name of the plugin to unregister.\n   * @throws Will throw an error if the plugin is not registered.\n   */\n  unregister(name: string): void {\n    if (!this.plugins.has(name)) {\n      throw new Error(`Plugin with name \"${name}\" is not registered.`);\n    }\n\n    this.plugins.delete(name);\n  }\n\n  /**\n   * Removes all custom editor plugins.\n   * This is useful for cleanup in tests or when reloading plugins.\n   */\n  unregisterAll(): void {\n    this.plugins.clear();\n  }\n\n  /**\n   * Retrieves a custom plugin by its name.\n   *\n   * @param name The name of the plugin.\n   * @returns The plugin constructor or undefined if not found.\n   */\n  async get(name: string): Promise<PluginConstructor | undefined> {\n    const reader = this.plugins.get(name);\n\n    return reader?.();\n  }\n\n  /**\n   * Checks if a plugin with the given name is registered.\n   *\n   * @param name The name of the plugin.\n   * @returns `true` if the plugin is registered, `false` otherwise.\n   */\n  has(name: string): boolean {\n    return this.plugins.has(name);\n  }\n}\n","import type { PluginConstructor } from 'ckeditor5';\n\nimport type { EditorPlugin } from '../typings';\n\nimport { CustomEditorPluginsRegistry } from '../custom-editor-plugins';\n\n/**\n * Loads CKEditor plugins from base and premium packages.\n * First tries to load from the base 'ckeditor5' package, then falls back to 'ckeditor5-premium-features'.\n *\n * @param plugins - Array of plugin names to load\n * @returns Promise that resolves to an array of loaded Plugin instances\n * @throws Error if a plugin is not found in either package\n */\nexport async function loadEditorPlugins(plugins: EditorPlugin[]): Promise<LoadedPlugins> {\n  const basePackage = await import('ckeditor5');\n  let premiumPackage: Record<string, any> | null = null;\n\n  const loaders = plugins.map(async (plugin) => {\n    // Let's first try to load the plugin from the base package.\n    // Coverage is disabled due to Vitest issues with mocking dynamic imports.\n\n    // Try custom plugins before checking packages.\n    const customPlugin = await CustomEditorPluginsRegistry.the.get(plugin);\n\n    if (customPlugin) {\n      return customPlugin;\n    }\n\n    // If not found, try to load from the base package.\n    const { [plugin]: basePkgImport } = basePackage as Record<string, unknown>;\n\n    if (basePkgImport) {\n      return basePkgImport as PluginConstructor;\n    }\n\n    // Plugin not found in base package, try premium package.\n    if (!premiumPackage) {\n      try {\n        premiumPackage = await import('ckeditor5-premium-features');\n        /* v8 ignore next 6 */\n      }\n      catch (error) {\n        console.error(`Failed to load premium package: ${error}`);\n      }\n    }\n\n    /* v8 ignore next */\n    const { [plugin]: premiumPkgImport } = premiumPackage || {};\n\n    if (premiumPkgImport) {\n      return premiumPkgImport as PluginConstructor;\n    }\n\n    // Plugin not found in either package, throw an error.\n    throw new Error(`Plugin \"${plugin}\" not found in base or premium packages.`);\n  });\n\n  return {\n    loadedPlugins: await Promise.all(loaders),\n    hasPremium: !!premiumPackage,\n  };\n}\n\n/**\n * Type representing the loaded plugins and whether premium features are available.\n */\ntype LoadedPlugins = {\n  loadedPlugins: PluginConstructor<any>[];\n  hasPremium: boolean;\n};\n","/**\n * Loads all required translations for the editor based on the language configuration.\n *\n * @param language - The language configuration object containing UI and content language codes.\n * @param language.ui - The UI language code.\n * @param language.content - The content language code.\n * @param hasPremium - Whether premium features are enabled and premium translations should be loaded.\n * @returns A promise that resolves to an array of loaded translation objects.\n */\nexport async function loadAllEditorTranslations(\n  language: { ui: string; content: string; },\n  hasPremium: boolean,\n) {\n  const translations = [language.ui, language.content];\n  const loadedTranslations = await Promise.all(\n    [\n      loadEditorPkgTranslations('ckeditor5', translations),\n      /* v8 ignore next */\n      hasPremium && loadEditorPkgTranslations('ckeditor5-premium-features', translations),\n    ].filter(pkg => !!pkg),\n  )\n    .then(translations => translations.flat());\n\n  return loadedTranslations;\n}\n\n/**\n * Loads the editor translations for the given languages.\n *\n * Make sure this function is properly compiled and bundled in self hosted environments!\n *\n * @param pkg - The package to load translations from ('ckeditor5' or 'ckeditor5-premium-features').\n * @param translations - The list of language codes to load translations for.\n * @returns A promise that resolves to an array of loaded translation packs.\n */\nasync function loadEditorPkgTranslations(\n  pkg: EditorPkgName,\n  translations: string[],\n) {\n  /* v8 ignore next */\n  return await Promise.all(\n    translations\n      .filter(lang => lang !== 'en') // 'en' is the default language, no need to load it.\n      .map(async (lang) => {\n        const pack = await loadEditorTranslation(pkg, lang);\n\n        /* v8 ignore next */\n        return pack?.default ?? pack;\n      })\n      .filter(Boolean),\n  );\n}\n\n/**\n * Type representing the package name for CKEditor 5.\n */\ntype EditorPkgName = 'ckeditor5' | 'ckeditor5-premium-features';\n\n/**\n * Load translation for CKEditor 5\n * @param pkg - Package type: 'ckeditor5' or 'premium'\n * @param lang - Language code (e.g., 'pl', 'en', 'de')\n * @returns Translation object or null if failed\n */\nasync function loadEditorTranslation(pkg: EditorPkgName, lang: string): Promise<any> {\n  try {\n    /* v8 ignore next 2 */\n    if (pkg === 'ckeditor5') {\n      /* v8 ignore next 79 */\n      switch (lang) {\n        case 'af': return await import('ckeditor5/translations/af.js');\n        case 'ar': return await import('ckeditor5/translations/ar.js');\n        case 'ast': return await import('ckeditor5/translations/ast.js');\n        case 'az': return await import('ckeditor5/translations/az.js');\n        case 'bg': return await import('ckeditor5/translations/bg.js');\n        case 'bn': return await import('ckeditor5/translations/bn.js');\n        case 'bs': return await import('ckeditor5/translations/bs.js');\n        case 'ca': return await import('ckeditor5/translations/ca.js');\n        case 'cs': return await import('ckeditor5/translations/cs.js');\n        case 'da': return await import('ckeditor5/translations/da.js');\n        case 'de': return await import('ckeditor5/translations/de.js');\n        case 'de-ch': return await import('ckeditor5/translations/de-ch.js');\n        case 'el': return await import('ckeditor5/translations/el.js');\n        case 'en': return await import('ckeditor5/translations/en.js');\n        case 'en-au': return await import('ckeditor5/translations/en-au.js');\n        case 'en-gb': return await import('ckeditor5/translations/en-gb.js');\n        case 'eo': return await import('ckeditor5/translations/eo.js');\n        case 'es': return await import('ckeditor5/translations/es.js');\n        case 'es-co': return await import('ckeditor5/translations/es-co.js');\n        case 'et': return await import('ckeditor5/translations/et.js');\n        case 'eu': return await import('ckeditor5/translations/eu.js');\n        case 'fa': return await import('ckeditor5/translations/fa.js');\n        case 'fi': return await import('ckeditor5/translations/fi.js');\n        case 'fr': return await import('ckeditor5/translations/fr.js');\n        case 'gl': return await import('ckeditor5/translations/gl.js');\n        case 'gu': return await import('ckeditor5/translations/gu.js');\n        case 'he': return await import('ckeditor5/translations/he.js');\n        case 'hi': return await import('ckeditor5/translations/hi.js');\n        case 'hr': return await import('ckeditor5/translations/hr.js');\n        case 'hu': return await import('ckeditor5/translations/hu.js');\n        case 'hy': return await import('ckeditor5/translations/hy.js');\n        case 'id': return await import('ckeditor5/translations/id.js');\n        case 'it': return await import('ckeditor5/translations/it.js');\n        case 'ja': return await import('ckeditor5/translations/ja.js');\n        case 'jv': return await import('ckeditor5/translations/jv.js');\n        case 'kk': return await import('ckeditor5/translations/kk.js');\n        case 'km': return await import('ckeditor5/translations/km.js');\n        case 'kn': return await import('ckeditor5/translations/kn.js');\n        case 'ko': return await import('ckeditor5/translations/ko.js');\n        case 'ku': return await import('ckeditor5/translations/ku.js');\n        case 'lt': return await import('ckeditor5/translations/lt.js');\n        case 'lv': return await import('ckeditor5/translations/lv.js');\n        case 'ms': return await import('ckeditor5/translations/ms.js');\n        case 'nb': return await import('ckeditor5/translations/nb.js');\n        case 'ne': return await import('ckeditor5/translations/ne.js');\n        case 'nl': return await import('ckeditor5/translations/nl.js');\n        case 'no': return await import('ckeditor5/translations/no.js');\n        case 'oc': return await import('ckeditor5/translations/oc.js');\n        case 'pl': return await import('ckeditor5/translations/pl.js');\n        case 'pt': return await import('ckeditor5/translations/pt.js');\n        case 'pt-br': return await import('ckeditor5/translations/pt-br.js');\n        case 'ro': return await import('ckeditor5/translations/ro.js');\n        case 'ru': return await import('ckeditor5/translations/ru.js');\n        case 'si': return await import('ckeditor5/translations/si.js');\n        case 'sk': return await import('ckeditor5/translations/sk.js');\n        case 'sl': return await import('ckeditor5/translations/sl.js');\n        case 'sq': return await import('ckeditor5/translations/sq.js');\n        case 'sr': return await import('ckeditor5/translations/sr.js');\n        case 'sr-latn': return await import('ckeditor5/translations/sr-latn.js');\n        case 'sv': return await import('ckeditor5/translations/sv.js');\n        case 'th': return await import('ckeditor5/translations/th.js');\n        case 'tk': return await import('ckeditor5/translations/tk.js');\n        case 'tr': return await import('ckeditor5/translations/tr.js');\n        case 'tt': return await import('ckeditor5/translations/tt.js');\n        case 'ug': return await import('ckeditor5/translations/ug.js');\n        case 'uk': return await import('ckeditor5/translations/uk.js');\n        case 'ur': return await import('ckeditor5/translations/ur.js');\n        case 'uz': return await import('ckeditor5/translations/uz.js');\n        case 'vi': return await import('ckeditor5/translations/vi.js');\n        case 'zh': return await import('ckeditor5/translations/zh.js');\n        case 'zh-cn': return await import('ckeditor5/translations/zh-cn.js');\n        default:\n          console.warn(`Language ${lang} not found in ckeditor5 translations`);\n          return null;\n      }\n    }\n    /* v8 ignore next 79 */\n    else {\n      // Premium features translations\n      switch (lang) {\n        case 'af': return await import('ckeditor5-premium-features/translations/af.js');\n        case 'ar': return await import('ckeditor5-premium-features/translations/ar.js');\n        case 'ast': return await import('ckeditor5-premium-features/translations/ast.js');\n        case 'az': return await import('ckeditor5-premium-features/translations/az.js');\n        case 'bg': return await import('ckeditor5-premium-features/translations/bg.js');\n        case 'bn': return await import('ckeditor5-premium-features/translations/bn.js');\n        case 'bs': return await import('ckeditor5-premium-features/translations/bs.js');\n        case 'ca': return await import('ckeditor5-premium-features/translations/ca.js');\n        case 'cs': return await import('ckeditor5-premium-features/translations/cs.js');\n        case 'da': return await import('ckeditor5-premium-features/translations/da.js');\n        case 'de': return await import('ckeditor5-premium-features/translations/de.js');\n        case 'de-ch': return await import('ckeditor5-premium-features/translations/de-ch.js');\n        case 'el': return await import('ckeditor5-premium-features/translations/el.js');\n        case 'en': return await import('ckeditor5-premium-features/translations/en.js');\n        case 'en-au': return await import('ckeditor5-premium-features/translations/en-au.js');\n        case 'en-gb': return await import('ckeditor5-premium-features/translations/en-gb.js');\n        case 'eo': return await import('ckeditor5-premium-features/translations/eo.js');\n        case 'es': return await import('ckeditor5-premium-features/translations/es.js');\n        case 'es-co': return await import('ckeditor5-premium-features/translations/es-co.js');\n        case 'et': return await import('ckeditor5-premium-features/translations/et.js');\n        case 'eu': return await import('ckeditor5-premium-features/translations/eu.js');\n        case 'fa': return await import('ckeditor5-premium-features/translations/fa.js');\n        case 'fi': return await import('ckeditor5-premium-features/translations/fi.js');\n        case 'fr': return await import('ckeditor5-premium-features/translations/fr.js');\n        case 'gl': return await import('ckeditor5-premium-features/translations/gl.js');\n        case 'gu': return await import('ckeditor5-premium-features/translations/gu.js');\n        case 'he': return await import('ckeditor5-premium-features/translations/he.js');\n        case 'hi': return await import('ckeditor5-premium-features/translations/hi.js');\n        case 'hr': return await import('ckeditor5-premium-features/translations/hr.js');\n        case 'hu': return await import('ckeditor5-premium-features/translations/hu.js');\n        case 'hy': return await import('ckeditor5-premium-features/translations/hy.js');\n        case 'id': return await import('ckeditor5-premium-features/translations/id.js');\n        case 'it': return await import('ckeditor5-premium-features/translations/it.js');\n        case 'ja': return await import('ckeditor5-premium-features/translations/ja.js');\n        case 'jv': return await import('ckeditor5-premium-features/translations/jv.js');\n        case 'kk': return await import('ckeditor5-premium-features/translations/kk.js');\n        case 'km': return await import('ckeditor5-premium-features/translations/km.js');\n        case 'kn': return await import('ckeditor5-premium-features/translations/kn.js');\n        case 'ko': return await import('ckeditor5-premium-features/translations/ko.js');\n        case 'ku': return await import('ckeditor5-premium-features/translations/ku.js');\n        case 'lt': return await import('ckeditor5-premium-features/translations/lt.js');\n        case 'lv': return await import('ckeditor5-premium-features/translations/lv.js');\n        case 'ms': return await import('ckeditor5-premium-features/translations/ms.js');\n        case 'nb': return await import('ckeditor5-premium-features/translations/nb.js');\n        case 'ne': return await import('ckeditor5-premium-features/translations/ne.js');\n        case 'nl': return await import('ckeditor5-premium-features/translations/nl.js');\n        case 'no': return await import('ckeditor5-premium-features/translations/no.js');\n        case 'oc': return await import('ckeditor5-premium-features/translations/oc.js');\n        case 'pl': return await import('ckeditor5-premium-features/translations/pl.js');\n        case 'pt': return await import('ckeditor5-premium-features/translations/pt.js');\n        case 'pt-br': return await import('ckeditor5-premium-features/translations/pt-br.js');\n        case 'ro': return await import('ckeditor5-premium-features/translations/ro.js');\n        case 'ru': return await import('ckeditor5-premium-features/translations/ru.js');\n        case 'si': return await import('ckeditor5-premium-features/translations/si.js');\n        case 'sk': return await import('ckeditor5-premium-features/translations/sk.js');\n        case 'sl': return await import('ckeditor5-premium-features/translations/sl.js');\n        case 'sq': return await import('ckeditor5-premium-features/translations/sq.js');\n        case 'sr': return await import('ckeditor5-premium-features/translations/sr.js');\n        case 'sr-latn': return await import('ckeditor5-premium-features/translations/sr-latn.js');\n        case 'sv': return await import('ckeditor5-premium-features/translations/sv.js');\n        case 'th': return await import('ckeditor5-premium-features/translations/th.js');\n        case 'tk': return await import('ckeditor5-premium-features/translations/tk.js');\n        case 'tr': return await import('ckeditor5-premium-features/translations/tr.js');\n        case 'tt': return await import('ckeditor5-premium-features/translations/tt.js');\n        case 'ug': return await import('ckeditor5-premium-features/translations/ug.js');\n        case 'uk': return await import('ckeditor5-premium-features/translations/uk.js');\n        case 'ur': return await import('ckeditor5-premium-features/translations/ur.js');\n        case 'uz': return await import('ckeditor5-premium-features/translations/uz.js');\n        case 'vi': return await import('ckeditor5-premium-features/translations/vi.js');\n        case 'zh': return await import('ckeditor5-premium-features/translations/zh.js');\n        case 'zh-cn': return await import('ckeditor5-premium-features/translations/zh-cn.js');\n        default:\n          console.warn(`Language ${lang} not found in premium translations`);\n          return await import('ckeditor5-premium-features/translations/en.js'); // fallback to English\n      }\n    }\n    /* v8 ignore next 7 */\n  }\n  catch (error) {\n    console.error(`Failed to load translation for ${pkg}/${lang}:`, error);\n    return null;\n  }\n}\n","import type { Translations } from 'ckeditor5';\n\nimport type { EditorCustomTranslationsDictionary } from '../typings';\n\nimport { mapObjectValues } from '../../../shared';\n\n/**\n * This function takes a custom translations object and maps it to the format expected by CKEditor5.\n * Each translation dictionary is wrapped in an object with a `dictionary` key.\n *\n * @param translations - The custom translations to normalize.\n * @returns A normalized translations object suitable for CKEditor5.\n */\nexport function normalizeCustomTranslations(translations: EditorCustomTranslationsDictionary): Translations {\n  return mapObjectValues(translations, dictionary => ({\n    dictionary,\n  }));\n}\n","import type { EditorId } from '../typings';\n\nimport { filterObjectValues, mapObjectValues } from '../../../shared';\n\n/**\n * Gets the initial root elements for the editor based on its type.\n *\n * @param editorId The editor's ID.\n * @returns The root element(s) for the editor.\n */\nexport function queryEditablesElements(editorId: EditorId) {\n  const editables = queryAllEditorEditables(editorId);\n\n  return mapObjectValues(editables, ({ content }) => content);\n}\n\n/**\n * Gets the initial data for the roots of the editor. If the editor is a single editing-like editor,\n * it retrieves the initial value from the element's attribute. Otherwise, it returns an object mapping\n * editable names to their initial values.\n *\n * @param editorId The editor's ID.\n * @returns The initial values for the editor's roots.\n */\nexport function queryEditablesSnapshotContent(editorId: EditorId) {\n  const editables = queryAllEditorEditables(editorId);\n  const values = mapObjectValues(editables, ({ initialValue }) => initialValue);\n\n  return filterObjectValues(values, value => typeof value === 'string') as Record<string, string>;\n}\n\n/**\n * Queries all editable elements within a specific editor instance.\n *\n * @param editorId The ID of the editor to query.\n * @returns An object mapping editable names to their corresponding elements and initial values.\n */\nexport function queryAllEditorEditables(editorId: EditorId): Record<string, EditableItem> {\n  const iterator = document.querySelectorAll<HTMLElement>(\n    [\n      `[data-cke-editor-id=\"${editorId}\"][data-cke-editable-root-name]`,\n      '[data-cke-editable-root-name]:not([data-cke-editor-id])',\n    ]\n      .join(', '),\n  );\n\n  const acc = (\n    Array\n      .from(iterator)\n      .reduce<Record<string, EditableItem>>((acc, element) => {\n        const name = element.getAttribute('data-cke-editable-root-name');\n        const initialValue = element.getAttribute('data-cke-editable-initial-value') || '';\n        const content = element.querySelector('[data-cke-editable-content]') as HTMLElement;\n\n        if (!name || !content) {\n          return acc;\n        }\n\n        return {\n          ...acc,\n          [name]: {\n            content,\n            initialValue,\n          },\n        };\n      }, Object.create({}))\n  );\n\n  const rootEditorElement = document.querySelector<HTMLElement>(`[phx-hook=\"CKEditor5\"][id=\"${editorId}\"]`);\n\n  if (!rootEditorElement) {\n    return acc;\n  }\n\n  const initialRootEditableValue = rootEditorElement.getAttribute('data-cke-initial-value') || '';\n  const contentElement = rootEditorElement.querySelector<HTMLElement>(`#${editorId}_editor `);\n  const currentMain = acc['main'];\n\n  if (currentMain) {\n    return {\n      ...acc,\n      main: {\n        ...currentMain,\n        initialValue: currentMain.initialValue || initialRootEditableValue,\n      },\n    };\n  }\n\n  if (contentElement) {\n    return {\n      ...acc,\n      main: {\n        content: contentElement,\n        initialValue: initialRootEditableValue,\n      },\n    };\n  }\n\n  return acc;\n}\n\n/**\n * Type representing an editable item within an editor.\n */\nexport type EditableItem = {\n  content: HTMLElement;\n  initialValue: string;\n};\n","/**\n * List of supported CKEditor5 editor types.\n */\nexport const EDITOR_TYPES = ['inline', 'classic', 'balloon', 'decoupled', 'multiroot'] as const;\n\n/**\n * Represents a unique identifier for a CKEditor5 editor instance.\n * This is typically the ID of the HTML element that the editor is attached to.\n */\nexport type EditorId = string;\n\n/**\n * Defines editor type supported by CKEditor5. It must match list of available\n * editor types specified in `preset/parser.ex` file.\n */\nexport type EditorType = (typeof EDITOR_TYPES)[number];\n\n/**\n * Represents a CKEditor5 plugin as a string identifier.\n */\nexport type EditorPlugin = string;\n\n/**\n * Configuration object for CKEditor5 editor instance.\n */\nexport type EditorConfig = {\n  /**\n   * Array of plugin identifiers to be loaded by the editor.\n   */\n  plugins: EditorPlugin[];\n\n  /**\n   * Other configuration options are flexible and can be any key-value pairs.\n   */\n  [key: string]: any;\n};\n\n/**\n * Represents a license key for CKEditor5.\n */\nexport type EditorLicense = {\n  key: string;\n};\n\n/**\n * Configuration object for the CKEditor5 hook.\n */\nexport type EditorPreset = {\n  /**\n   * The type of CKEditor5 editor to use.\n   * Must be one of the predefined types: 'inline', 'classic', 'balloon', 'decoupled', or 'multiroot'.\n   */\n  type: EditorType;\n\n  /**\n   * The configuration object for the CKEditor5 editor.\n   * This should match the configuration expected by CKEditor5.\n   */\n  config: EditorConfig;\n\n  /**\n   * The license key for CKEditor5.\n   * This is required for using CKEditor5 with a valid license.\n   */\n  license: EditorLicense;\n\n  /**\n   * Optional custom translations for the editor.\n   * This allows for localization of the editor interface.\n   */\n  customTranslations?: {\n    dictionary: EditorCustomTranslationsDictionary;\n  };\n};\n\n/**\n * Represents custom translations for the editor.\n */\nexport type EditorCustomTranslationsDictionary = {\n  [language: string]: {\n    [key: string]: string | ReadonlyArray<string>;\n  };\n};\n","import type { EditorPreset } from '../typings';\n\nimport { deepCamelCaseKeys } from '../../../shared/deep-camel-case-keys';\nimport { EDITOR_TYPES } from '../typings';\n\n/**\n * Reads the hook configuration from the element's attribute and parses it as JSON.\n *\n * @param element - The HTML element that contains the hook configuration.\n * @returns The parsed hook configuration.\n */\nexport function readPresetOrThrow(element: HTMLElement): EditorPreset {\n  const attributeValue = element.getAttribute('data-cke-preset');\n\n  if (!attributeValue) {\n    throw new Error('CKEditor5 hook requires a \"cke-preset\" attribute on the element.');\n  }\n\n  const { type, config, license, ...rest } = JSON.parse(attributeValue);\n\n  if (!type || !config || !license) {\n    throw new Error('CKEditor5 hook configuration must include \"editor\", \"config\", and \"license\" properties.');\n  }\n\n  if (!EDITOR_TYPES.includes(type)) {\n    throw new Error(`Invalid editor type: ${type}. Must be one of: ${EDITOR_TYPES.join(', ')}.`);\n  }\n\n  return {\n    type,\n    license,\n    config: deepCamelCaseKeys(config),\n    customTranslations: rest.customTranslations || rest.custom_translations,\n  };\n}\n","/**\n * Resolves element references in configuration object.\n * Looks for objects with { $element: \"selector\" } format and replaces them with actual DOM elements.\n *\n * @param obj - Configuration object to process\n * @returns Processed configuration object with resolved element references\n */\nexport function resolveEditorConfigElementReferences<T>(obj: T): T {\n  if (!obj || typeof obj !== 'object') {\n    return obj;\n  }\n\n  if (Array.isArray(obj)) {\n    return obj.map(item => resolveEditorConfigElementReferences(item)) as T;\n  }\n\n  const anyObj = obj as any;\n\n  if (anyObj.$element && typeof anyObj.$element === 'string') {\n    const element = document.querySelector(anyObj.$element);\n\n    if (!element) {\n      console.warn(`Element not found for selector: ${anyObj.$element}`);\n    }\n\n    return (element || null) as T;\n  }\n\n  const result = Object.create(null);\n\n  for (const [key, value] of Object.entries(obj)) {\n    result[key] = resolveEditorConfigElementReferences(value);\n  }\n\n  return result as T;\n}\n","import type { Translations } from 'ckeditor5';\n\n/**\n * Resolves translation references in a configuration object.\n *\n * The configuration may contain objects with the form `{ $translation: \"some.key\" }`.\n * These are replaced with the actual string from the provided translations map.\n *\n * The function will walk the provided object recursively, handling arrays and\n * nested objects. Primitive values are returned as-is. If a translation key is\n * not present in the map, a warning is logged and `null` is returned for that\n * value.\n *\n * @param translations - An array of CKEditor `Translations` objects. Each translation\n *                       pack will be searched in order for the requested key, and the\n *                       first matching value will be returned. This mirrors the format\n *                       returned by `loadAllEditorTranslations` and simplifies the\n *                       caller's API.\n * @param language - Language identifier to look up in the packs. Only this locale\n *                   will be consulted, ensuring that keys from other languages are\n *                   ignored even if they appear earlier in the array.\n * @param obj - Configuration object to process\n * @returns Processed configuration object with resolved translations.\n */\nexport function resolveEditorConfigTranslations<T>(\n  translations: Translations[],\n  language: string,\n  obj: T,\n): T {\n  if (!obj || typeof obj !== 'object') {\n    return obj;\n  }\n\n  if (Array.isArray(obj)) {\n    return obj.map(item => resolveEditorConfigTranslations(translations, language, item)) as T;\n  }\n\n  const anyObj = obj as any;\n\n  if (anyObj.$translation && typeof anyObj.$translation === 'string') {\n    const key: string = anyObj.$translation;\n    const value = getTranslationValue(translations, key, language);\n\n    if (value === undefined) {\n      console.warn(`Translation not found for key: ${key}`);\n    }\n\n    return (value !== undefined ? value : null) as T;\n  }\n\n  const result = Object.create(null);\n\n  for (const [key, value] of Object.entries(obj)) {\n    result[key] = resolveEditorConfigTranslations(translations, language, value);\n  }\n\n  return result as T;\n}\n\n/**\n * Look up a translation value inside the provided map or array of CKEditor packs.\n */\nfunction getTranslationValue(\n  translations: Translations[],\n  key: string,\n  language: string,\n): string | ReadonlyArray<string> | undefined {\n  for (const pack of translations) {\n    const langData = pack[language];\n\n    if (langData?.dictionary && key in langData.dictionary) {\n      return langData.dictionary[key] as string | ReadonlyArray<string>;\n    }\n  }\n\n  return undefined;\n}\n","import type { Editor } from 'ckeditor5';\n\n/**\n * Sets the height of the editable area in the CKEditor instance.\n *\n * @param instance - The CKEditor instance to modify.\n * @param height - The height in pixels to set for the editable area.\n */\nexport function setEditorEditableHeight(instance: Editor, height: number): void {\n  const { editing } = instance;\n\n  editing.view.change((writer) => {\n    writer.setStyle('height', `${height}px`, editing.view.document.getRoot()!);\n  });\n}\n","import type { Editor, EditorWatchdog } from 'ckeditor5';\n\nconst EDITOR_WATCHDOG_SYMBOL = Symbol.for('elixir-editor-watchdog');\n\n/**\n * Wraps an Editor creator with a watchdog for automatic recovery.\n *\n * @param Editor - The Editor creator to wrap.\n * @returns The Editor creator wrapped with a watchdog.\n */\nexport async function wrapWithWatchdog(Editor: EditorCreator) {\n  const { EditorWatchdog } = await import('ckeditor5');\n  const watchdog = new EditorWatchdog(Editor);\n\n  watchdog.setCreator(async (...args: Parameters<typeof Editor['create']>) => {\n    const editor = await Editor.create(...args);\n\n    (editor as any)[EDITOR_WATCHDOG_SYMBOL] = watchdog;\n\n    return editor;\n  });\n\n  return {\n    watchdog,\n    Constructor: {\n      create: async (...args: Parameters<typeof Editor['create']>) => {\n        await watchdog.create(...args);\n\n        return watchdog.editor!;\n      },\n    },\n  };\n}\n\n/**\n * Unwraps the EditorWatchdog from the editor instance.\n */\nexport function unwrapEditorWatchdog(editor: Editor): EditorWatchdog | null {\n  if (EDITOR_WATCHDOG_SYMBOL in editor) {\n    return (editor as any)[EDITOR_WATCHDOG_SYMBOL] as EditorWatchdog;\n  }\n\n  return null;\n}\n\n/**\n * Type representing an Editor creator with a create method.\n */\nexport type EditorCreator = {\n  create: (...args: any) => Promise<Editor>;\n};\n","import type { Context, ContextWatchdog } from 'ckeditor5';\n\nimport { AsyncRegistry } from '../../shared';\n\n/**\n * It provides a way to register contexts and execute callbacks on them when they are available.\n */\nexport class ContextsRegistry extends AsyncRegistry<ContextWatchdog<Context>> {\n  static readonly the = new ContextsRegistry();\n}\n","import type { ContextConfig } from '../typings';\n\nimport { deepCamelCaseKeys } from '../../../shared/deep-camel-case-keys';\n\n/**\n * Reads the hook configuration from the element's attribute and parses it as JSON.\n *\n * @param element - The HTML element that contains the hook configuration.\n * @returns The parsed hook configuration.\n */\nexport function readContextConfigOrThrow(element: HTMLElement): ContextConfig {\n  const attributeValue = element.getAttribute('data-cke-context');\n\n  if (!attributeValue) {\n    throw new Error('CKEditor5 hook requires a \"data-cke-context\" attribute on the element.');\n  }\n\n  const { config, ...rest } = JSON.parse(attributeValue);\n\n  return {\n    config: deepCamelCaseKeys(config),\n    customTranslations: rest.customTranslations || rest.custom_translations,\n    watchdogConfig: rest.watchdogConfig || rest.watchdog_config,\n  };\n}\n","import type { Context, ContextWatchdog } from 'ckeditor5';\n\nimport { ClassHook, isEmptyObject, makeHook } from '../../shared';\nimport {\n  loadAllEditorTranslations,\n  loadEditorPlugins,\n  normalizeCustomTranslations,\n  resolveEditorConfigElementReferences,\n  resolveEditorConfigTranslations,\n} from '../editor/utils';\nimport { ContextsRegistry } from './contexts-registry';\nimport { readContextConfigOrThrow } from './utils';\n\n/**\n * Context hook for Phoenix LiveView. It allows you to create contexts for collaboration editors.\n */\nclass ContextHookImpl extends ClassHook {\n  /**\n   * The promise that resolves to the context instance.\n   */\n  private contextPromise: Promise<ContextWatchdog<Context>> | null = null;\n\n  /**\n   * Attributes for the context instance.\n   */\n  private get attrs() {\n    const get = (attr: string) => this.el.getAttribute(attr) || null;\n    const value = {\n      id: this.el.id,\n      config: readContextConfigOrThrow(this.el),\n      language: {\n        ui: get('data-cke-language') || 'en',\n        content: get('data-cke-content-language') || 'en',\n      },\n    };\n\n    Object.defineProperty(this, 'attrs', {\n      value,\n      writable: false,\n      configurable: false,\n      enumerable: true,\n    });\n\n    return value;\n  }\n\n  /**\n   * Mounts the context component.\n   */\n  override async mounted() {\n    const { id, language } = this.attrs;\n    const { customTranslations, watchdogConfig, config: { plugins, ...config } } = this.attrs.config;\n    const { loadedPlugins, hasPremium } = await loadEditorPlugins(plugins ?? []);\n\n    // Mix custom translations with loaded translations.\n    const loadedTranslations = await loadAllEditorTranslations(language, hasPremium);\n    const mixedTranslations = [\n      ...loadedTranslations,\n      normalizeCustomTranslations(customTranslations?.dictionary || {}),\n    ]\n      .filter(translations => !isEmptyObject(translations));\n\n    // Construct parsed config. First resolve DOM element references in the provided configuration.\n    let resolvedConfig = resolveEditorConfigElementReferences(config);\n\n    // Then resolve translation references in the provided configuration, using the mixed translations.\n    resolvedConfig = resolveEditorConfigTranslations([...mixedTranslations].reverse(), language.ui, resolvedConfig);\n\n    // Initialize context.\n    this.contextPromise = (async () => {\n      const { ContextWatchdog, Context } = await import('ckeditor5');\n      const instance = new ContextWatchdog(Context, {\n        crashNumberLimit: 10,\n        ...watchdogConfig,\n      });\n\n      await instance.create({\n        ...resolvedConfig,\n        language,\n        plugins: loadedPlugins,\n        ...mixedTranslations.length && {\n          translations: mixedTranslations,\n        },\n      });\n\n      instance.on('itemError', (...args) => {\n        console.error('Context item error:', ...args);\n      });\n\n      return instance;\n    })();\n\n    const context = await this.contextPromise;\n\n    if (!this.isBeingDestroyed()) {\n      ContextsRegistry.the.register(id, context);\n    }\n  }\n\n  /**\n   * Destroys the context component. Unmounts root from the editor.\n   */\n  override async destroyed() {\n    const { id } = this.attrs;\n\n    // Let's hide the element during destruction to prevent flickering.\n    this.el.style.display = 'none';\n\n    // Let's wait for the mounted promise to resolve before proceeding with destruction.\n    try {\n      const context = await this.contextPromise;\n\n      await context?.destroy();\n    }\n    finally {\n      this.contextPromise = null;\n\n      if (ContextsRegistry.the.hasItem(id)) {\n        ContextsRegistry.the.unregister(id);\n      }\n    }\n  }\n}\n\n/**\n * Type guard to check if an element is a context hook HTMLElement.\n */\nfunction isContextHookHTMLElement(el: HTMLElement): el is HTMLElement & { instance: ContextHookImpl; } {\n  return el.hasAttribute('data-cke-context');\n}\n\n/**\n * Gets the nearest context hook parent element.\n */\nfunction getNearestContextParent(el: HTMLElement) {\n  let parent: HTMLElement | null = el;\n\n  while (parent) {\n    if (isContextHookHTMLElement(parent)) {\n      return parent;\n    }\n\n    parent = parent.parentElement;\n  }\n\n  return null;\n}\n\n/**\n * Gets the nearest context parent element as a promise.\n */\nexport async function getNearestContextParentPromise(el: HTMLElement): Promise<ContextWatchdog<Context> | null> {\n  const parent = getNearestContextParent(el);\n\n  if (!parent) {\n    return null;\n  }\n\n  return ContextsRegistry.the.waitFor(parent.id);\n}\n\n/**\n * Phoenix LiveView hook for CKEditor 5 context elements.\n */\nexport const ContextHook = makeHook(ContextHookImpl);\n","import type { Editor } from 'ckeditor5';\n\nimport { AsyncRegistry } from '../../shared/async-registry';\n\n/**\n * It provides a way to register editors and execute callbacks on them when they are available.\n */\nexport class EditorsRegistry extends AsyncRegistry<Editor> {\n  static readonly the = new EditorsRegistry();\n}\n","import type { MultiRootEditor } from 'ckeditor5';\n\nimport { ClassHook, debounce, makeHook } from '../shared';\nimport { EditorsRegistry } from './editor/editors-registry';\n\n/**\n * Editable hook for Phoenix LiveView. It allows you to create editables for multi-root editors.\n */\nclass EditableHookImpl extends ClassHook {\n  /**\n   * The promise that resolves to the editor instance once it's registered.\n   */\n  private editorPromise: Promise<MultiRootEditor | null> | null = null;\n\n  /**\n   * Attributes for the editable instance.\n   */\n  private get attrs() {\n    const value = {\n      editableId: this.el.getAttribute('id')!,\n      editorId: this.el.getAttribute('data-cke-editor-id') || null,\n      rootName: this.el.getAttribute('data-cke-editable-root-name')!,\n      initialValue: this.el.getAttribute('data-cke-editable-initial-value') || '',\n    };\n\n    Object.defineProperty(this, 'attrs', {\n      value,\n      writable: false,\n      configurable: false,\n      enumerable: true,\n    });\n\n    return value;\n  }\n\n  /**\n   * Mounts the editable component.\n   */\n  override async mounted() {\n    const { editableId, editorId, rootName, initialValue } = this.attrs;\n    const input = this.el.querySelector<HTMLInputElement>(`#${editableId}_input`);\n\n    // If the editor is not registered yet, we will wait for it to be registered.\n    this.editorPromise = EditorsRegistry.the.execute(editorId, (editor: MultiRootEditor) => {\n      /* v8 ignore next 3 */\n      if (this.isBeingDestroyed()) {\n        return null;\n      }\n\n      const { ui, editing, model } = editor;\n\n      if (model.document.getRoot(rootName)) {\n        return editor;\n      }\n\n      editor.addRoot(rootName, {\n        isUndoable: false,\n        data: initialValue,\n      });\n\n      const contentElement = this.el.querySelector('[data-cke-editable-content]') as HTMLElement | null;\n      const editable = ui.view.createEditable(rootName, contentElement!);\n\n      ui.addEditable(editable);\n      editing.view.forceRender();\n\n      if (input) {\n        const unmount = syncEditorRootToInput(input, editor, rootName);\n\n        this.onBeforeDestroy(unmount);\n      }\n\n      return editor;\n    });\n  }\n\n  /**\n   * Destroys the editable component. Unmounts root from the editor.\n   */\n  override async destroyed() {\n    const { rootName } = this.attrs;\n\n    // Let's hide the element during destruction to prevent flickering.\n    this.el.style.display = 'none';\n\n    // Let's wait for the mounted promise to resolve before proceeding with destruction.\n    const editor = await this.editorPromise;\n    this.editorPromise = null;\n\n    // Unmount root from the editor.\n    if (editor && editor.state !== 'destroyed') {\n      const root = editor.model.document.getRoot(rootName);\n\n      if (root && 'detachEditable' in editor) {\n        if (editor.ui.view.editables[rootName]) {\n          editor.detachEditable(root);\n        }\n\n        if (root.isAttached()) {\n          editor.detachRoot(rootName, false);\n        }\n      }\n    }\n  }\n}\n\n/**\n * Phoenix LiveView hook for CKEditor 5 editable elements.\n */\nexport const EditableHook = makeHook(EditableHookImpl);\n\n/**\n * Synchronizes the editor's root data to the corresponding input element.\n * This is used to keep the input value in sync with the editor's content.\n *\n * @param input - The input element to synchronize with the editor.\n * @param editor - The CKEditor instance.\n * @param rootName - The name of the root to synchronize.\n */\nfunction syncEditorRootToInput(input: HTMLInputElement, editor: MultiRootEditor, rootName: string) {\n  const sync = () => {\n    input.value = editor.getData({ rootName });\n  };\n\n  const debouncedSync = debounce(200, sync);\n\n  editor.model.document.on('change:data', debouncedSync);\n  sync();\n\n  return () => {\n    editor.model.document.off('change:data', debouncedSync);\n  };\n}\n","import type { FileLoader, PluginConstructor, UploadAdapter } from 'ckeditor5';\n\nimport { getCsrfToken } from '../../../shared';\n\n/**\n * Creates a PhoenixUploadAdapter plugin class for CKEditor 5.\n * This adapter handles image uploads to a Phoenix backend endpoint.\n */\nexport async function createPhoenixUploadAdapterPlugin(): Promise<PluginConstructor> {\n  const { Plugin, FileRepository } = await import('ckeditor5');\n\n  return class PhoenixUploadAdapter extends Plugin {\n    /**\n     * The name of the plugin.\n     */\n    static get pluginName() {\n      return 'PhoenixUploadAdapter' as const;\n    }\n\n    static get requires() {\n      return [FileRepository];\n    }\n\n    /**\n     * Initializes the plugin.\n     */\n    public init(): void {\n      const { editor } = this;\n      const { plugins, config } = editor;\n      const uploadUrl = config.get('phoenixUpload.url');\n\n      if (!uploadUrl) {\n        return;\n      }\n\n      // Check if we should enable this adapter\n      if (\n        plugins.has('SimpleUploadAdapter')\n        || plugins.has('Base64UploadAdapter')\n        || plugins.has('CKFinderUploadAdapter')\n      ) {\n        return;\n      }\n\n      // Register the upload adapter\n      const fileRepository = plugins.get(FileRepository);\n\n      fileRepository.createUploadAdapter = (loader: FileLoader) => new Adapter(loader, uploadUrl);\n    }\n  };\n}\n\ndeclare module 'ckeditor5' {\n  // eslint-disable-next-line ts/consistent-type-definitions\n  interface EditorConfig {\n    /**\n     * Configuration for Phoenix upload adapter.\n     */\n    phoenixUpload?: {\n      /**\n       * The URL to which files will be uploaded.\n       */\n      url: string;\n    };\n  }\n}\n\n/**\n * Upload adapter that handles communication with Phoenix backend.\n */\nclass Adapter implements UploadAdapter {\n  private readonly loader: FileLoader;\n  private readonly uploadUrl: string;\n  private abortController: AbortController | null = null;\n\n  constructor(loader: FileLoader, uploadUrl: string) {\n    this.loader = loader;\n    this.uploadUrl = uploadUrl;\n  }\n\n  /**\n   * Starts the upload process.\n   */\n  public async upload(): Promise<{ default: string; }> {\n    const file = (await this.loader.file)!;\n\n    this.abortController = new AbortController();\n\n    const data = new FormData();\n\n    data.append('file', file);\n\n    // Attempt to track progress if the file size is known, though fetch doesn't support\n    // upload progress events natively.\n    if (file.size) {\n      this.loader.uploadTotal = file.size;\n      this.loader.uploaded = 0;\n    }\n\n    const headers: HeadersInit = {};\n    const csrfToken = getCsrfToken();\n\n    if (csrfToken) {\n      headers['X-CSRF-Token'] = csrfToken;\n    }\n\n    try {\n      const response = await fetch(this.uploadUrl, {\n        method: 'POST',\n        headers,\n        body: data,\n        signal: this.abortController.signal,\n      });\n\n      if (!response.ok) {\n        let errorMessage = 'Couldn\\'t upload file!';\n\n        try {\n          const errorData = await response.json();\n          if (errorData?.error?.message) {\n            errorMessage = errorData.error.message;\n          }\n        }\n        catch { /* ignore */ }\n\n        throw new Error(errorMessage);\n      }\n\n      this.loader.uploaded = this.loader.uploadTotal!;\n\n      const result = await response.json();\n\n      return {\n        default: result.url,\n      };\n    }\n    /* v8 ignore next 7 */\n    catch (error: any) {\n      if (error.name === 'AbortError') {\n        throw error;\n      }\n\n      throw error.message || 'Couldn\\'t upload file!';\n    }\n  }\n\n  /**\n   * Aborts the upload process.\n   */\n  /* v8 ignore next 4 */\n  public abort(): void {\n    this.abortController?.abort();\n    this.abortController = null;\n  }\n}\n","import type { PluginConstructor } from 'ckeditor5';\n\nimport { debounce } from '../../../shared';\n\n/**\n * Creates a SyncEditorWithInput plugin class.\n */\nexport async function createSyncEditorWithInputPlugin(\n  {\n    editorId,\n    saveDebounceMs,\n  }: Attrs,\n): Promise<PluginConstructor> {\n  const { Plugin } = await import('ckeditor5');\n\n  return class SyncEditorWithInput extends Plugin {\n    /**\n     * The input element to synchronize with.\n     */\n    private input: HTMLInputElement | null = null;\n\n    /**\n     * The form element reference for cleanup.\n     */\n    private form: HTMLFormElement | null = null;\n\n    /**\n     * The name of the plugin.\n     */\n    static get pluginName() {\n      return 'SyncEditorWithInput' as const;\n    }\n\n    /**\n     * Initializes the plugin.\n     */\n    public afterInit(): void {\n      const { editor } = this;\n\n      this.input = document.getElementById(`${editorId}_input`) as HTMLInputElement | null;\n\n      if (!this.input) {\n        return;\n      }\n\n      // Setup handlers.\n      editor.model.document.on('change:data', debounce(saveDebounceMs, () => this.sync()));\n      editor.once('ready', this.sync);\n\n      // Setup form integration.\n      this.form = this.input.closest('form');\n      this.form?.addEventListener('submit', this.sync);\n    }\n\n    /**\n     * Synchronizes the editor's content with the input field.\n     */\n    private sync = (): void => {\n      const newValue = this.editor.getData();\n\n      this.input!.value = newValue;\n      this.input!.dispatchEvent(new Event('input', { bubbles: true }));\n    };\n\n    /**\n     * Destroys the plugin.\n     */\n    public override destroy(): void {\n      if (this.form) {\n        this.form.removeEventListener('submit', this.sync);\n      }\n\n      this.input = null;\n      this.form = null;\n    }\n  };\n}\n\ntype Attrs = {\n  editorId: string;\n  saveDebounceMs: number;\n};\n","import type { Editor, PluginConstructor } from 'ckeditor5';\n\nimport type { EditorId } from '../typings';\n\nimport { debounce, isNil, shallowEqual } from '../../../shared';\n\n/**\n * Creates a SyncEditorWithPhoenix plugin class. It's not two way binding, but\n * it allows you to push editor data to Phoenix on change, focus and blur events, and\n * also to set editor data from Phoenix.\n *\n * In order to debug two-way binding, check `EditorRootValueSentinel` component, which is used\n * to assign the value to the editor based on modification of the Elixir component's assigns.\n *\n * @param options The options for the plugin, including editorId, debounce time, events to listen to, and pushEvent/handleEvent functions.\n * @returns A Promise that resolves to the SyncEditorWithPhoenix plugin constructor.\n */\nexport async function createSyncEditorWithPhoenixPlugin(options: Attrs): Promise<PluginConstructor> {\n  const { Plugin } = await import('ckeditor5');\n  const { editorId, saveDebounceMs, events, pushEvent, handleEvent } = options;\n\n  return class SyncEditorWithPhoenix extends Plugin {\n    /**\n     * The name of the plugin.\n     */\n    static get pluginName() {\n      return 'SyncEditorWithPhoenix' as const;\n    }\n\n    /**\n     * Initializes the plugin.\n     */\n    public init(): void {\n      const { editor } = this;\n\n      if (events.change) {\n        this.setupTypingContentPush();\n      }\n\n      if (events.blur) {\n        this.setupEventPush('blur');\n      }\n\n      if (events.focus) {\n        this.setupEventPush('focus');\n      }\n\n      if (events.ready) {\n        this.editor.once('ready', () => {\n          pushEvent('ckeditor5:ready', {\n            editorId,\n            data: getEditorRootsValues(editor),\n          });\n        });\n      }\n\n      handleEvent('ckeditor5:set-data', ({ editorId: targetId, data }) => {\n        if (isNil(targetId) || targetId === editorId) {\n          editor.setData(data);\n        }\n      });\n    }\n\n    /**\n     * Setups the content push event for the editor.\n     */\n    private setupTypingContentPush() {\n      const { editor } = this;\n\n      let lastValue: Record<string, string> | null = null;\n      let isDestroyed = false;\n\n      const pushContentChange = () => {\n        if (isDestroyed) {\n          return;\n        }\n\n        const newValue = getEditorRootsValues(editor);\n\n        if (!lastValue || !shallowEqual(lastValue, newValue)) {\n          pushEvent(\n            'ckeditor5:change',\n            {\n              editorId,\n              data: newValue,\n            },\n          );\n\n          lastValue = newValue;\n        }\n      };\n\n      const debouncedPushContentChange = debounce(saveDebounceMs, pushContentChange);\n\n      editor.model.document.on('change:data', () => {\n        if (editor.ui.focusTracker.isFocused) {\n          debouncedPushContentChange();\n        }\n        else {\n          pushContentChange();\n        }\n      });\n\n      editor.once('ready', pushContentChange);\n      editor.once('destroy', () => {\n        isDestroyed = true;\n      });\n    }\n\n    /**\n     * Setups the event push for the editor.\n     */\n    private setupEventPush(eventType: 'focus' | 'blur') {\n      const { editor } = this;\n\n      const pushEventCallback = () => {\n        const { isFocused } = editor.ui.focusTracker;\n        const currentType = isFocused ? 'focus' : 'blur';\n\n        if (currentType !== eventType) {\n          return;\n        }\n\n        pushEvent(\n          `ckeditor5:${eventType}`,\n          {\n            editorId,\n            data: getEditorRootsValues(editor),\n          },\n        );\n      };\n\n      editor.ui.focusTracker.on('change:isFocused', pushEventCallback);\n    }\n  };\n}\n\ntype Attrs = {\n  editorId: EditorId;\n  saveDebounceMs: number;\n  events: {\n    change: boolean;\n    focus: boolean;\n    blur: boolean;\n    ready: boolean;\n  };\n  pushEvent: (event: string, payload: any) => void;\n  handleEvent: (event: string, callback: (payload: any) => void) => void;\n};\n\n/**\n * Gets the values of the editor's roots.\n *\n * @param editor The CKEditor instance.\n * @returns An object mapping root names to their content.\n */\nfunction getEditorRootsValues(editor: Editor) {\n  const roots = editor.model.document.getRootNames();\n\n  return roots.reduce<Record<string, string>>((acc, rootName) => {\n    acc[rootName] = editor.getData({ rootName });\n    return acc;\n  }, Object.create({}));\n}\n","import type { Editor } from 'ckeditor5';\n\nimport type { EditorId } from './typings';\nimport type { EditorCreator } from './utils';\n\nimport { isEmptyObject, parseIntIfNotNull, waitFor } from '../../shared';\nimport { ClassHook, makeHook } from '../../shared/hook';\nimport { ContextsRegistry, getNearestContextParentPromise } from '../context';\nimport { EditorsRegistry } from './editors-registry';\nimport {\n  createPhoenixUploadAdapterPlugin,\n  createSyncEditorWithInputPlugin,\n  createSyncEditorWithPhoenixPlugin,\n} from './plugins';\nimport {\n  createEditorInContext,\n  isSingleRootEditor,\n  loadAllEditorTranslations,\n  loadEditorConstructor,\n  loadEditorPlugins,\n  normalizeCustomTranslations,\n  queryEditablesElements,\n  queryEditablesSnapshotContent,\n  readPresetOrThrow,\n  resolveEditorConfigElementReferences,\n  resolveEditorConfigTranslations,\n  setEditorEditableHeight,\n  unwrapEditorContext,\n  unwrapEditorWatchdog,\n  wrapWithWatchdog,\n} from './utils';\n\n/**\n * Editor hook for Phoenix LiveView.\n *\n * This class is a hook that can be used with Phoenix LiveView to integrate\n * the CKEditor 5 WYSIWYG editor.\n */\nclass EditorHookImpl extends ClassHook {\n  /**\n   * The promise that resolves to the editor instance.\n   */\n  private editorPromise: Promise<Editor> | null = null;\n\n  /**\n   * Attributes for the editor instance.\n   */\n  private get attrs() {\n    const { el } = this;\n    const get = el.getAttribute.bind(el);\n    const has = el.hasAttribute.bind(el);\n\n    const value = {\n      editorId: get('id')!,\n      contextId: get('data-cke-context-id'),\n      preset: readPresetOrThrow(el),\n      editableHeight: parseIntIfNotNull(get('data-cke-editable-height')),\n      watchdog: has('data-cke-watchdog'),\n      events: {\n        change: has('data-cke-change-event'),\n        blur: has('data-cke-blur-event'),\n        focus: has('data-cke-focus-event'),\n        ready: has('data-cke-ready-event'),\n      },\n      saveDebounceMs: parseIntIfNotNull(get('data-cke-save-debounce-ms')) ?? 400,\n      language: {\n        ui: get('data-cke-language') || 'en',\n        content: get('data-cke-content-language') || 'en',\n      },\n    };\n\n    Object.defineProperty(this, 'attrs', {\n      value,\n      writable: false,\n      configurable: false,\n      enumerable: true,\n    });\n\n    return value;\n  }\n\n  /**\n   * Mounts the editor component.\n   */\n  override async mounted() {\n    const { editorId } = this.attrs;\n\n    EditorsRegistry.the.resetErrors(editorId);\n\n    try {\n      this.editorPromise = this.createEditor();\n\n      const editor = await this.editorPromise;\n\n      // Do not even try to broadcast about the registration of the editor\n      // if hook was immediately destroyed.\n      if (!this.isBeingDestroyed()) {\n        EditorsRegistry.the.register(editorId, editor);\n\n        editor.once('destroy', () => {\n          if (EditorsRegistry.the.hasItem(editorId)) {\n            EditorsRegistry.the.unregister(editorId);\n          }\n        });\n      }\n    }\n    catch (error: any) {\n      this.editorPromise = null;\n      EditorsRegistry.the.error(editorId, error);\n    }\n\n    return this;\n  }\n\n  /**\n   * Destroys the editor instance when the component is destroyed.\n   * This is important to prevent memory leaks and ensure that the editor is properly cleaned up.\n   */\n  override async destroyed() {\n    // Let's hide the element during destruction to prevent flickering.\n    this.el.style.display = 'none';\n\n    // Let's wait for the mounted promise to resolve before proceeding with destruction.\n    try {\n      const editor = await this.editorPromise;\n\n      if (!editor) {\n        return;\n      }\n\n      const editorContext = unwrapEditorContext(editor);\n      const watchdog = unwrapEditorWatchdog(editor);\n\n      if (editorContext) {\n        // If context is present, make sure it's not in unmounting phase, as it'll kill the editors.\n        // If it's being destroyed, don't do anything, as the context will take care of it.\n        if (editorContext.state !== 'unavailable') {\n          await editorContext.context.remove(editorContext.editorContextId);\n        }\n      }\n      else if (watchdog) {\n        await watchdog.destroy();\n      }\n      else {\n        await editor.destroy();\n      }\n    }\n    finally {\n      this.editorPromise = null;\n    }\n  }\n\n  /**\n   * Creates the CKEditor instance.\n   */\n  private async createEditor() {\n    const { preset, editorId, contextId, editableHeight, events, saveDebounceMs, language, watchdog } = this.attrs;\n    const { customTranslations, type, license, config: { plugins, ...config } } = preset;\n\n    // Wrap editor creator with watchdog if needed.\n    let Constructor: EditorCreator = await loadEditorConstructor(type);\n    const context = await (\n      contextId\n        ? ContextsRegistry.the.waitFor(contextId)\n        : getNearestContextParentPromise(this.el)\n    );\n\n    // Do not use editor specific watchdog if context is attached, as the context is by default protected.\n    if (watchdog && !context) {\n      const wrapped = await wrapWithWatchdog(Constructor);\n\n      ({ Constructor } = wrapped);\n      wrapped.watchdog.on('restart', () => {\n        const newInstance = wrapped.watchdog.editor!;\n\n        this.editorPromise = Promise.resolve(newInstance);\n\n        EditorsRegistry.the.register(editorId, newInstance);\n      });\n    }\n\n    const { loadedPlugins, hasPremium } = await loadEditorPlugins(plugins);\n\n    if (isSingleRootEditor(type)) {\n      loadedPlugins.push(\n        await createSyncEditorWithInputPlugin({\n          editorId,\n          saveDebounceMs,\n        }),\n      );\n    }\n\n    loadedPlugins.push(\n      ...await Promise.all([\n        createSyncEditorWithPhoenixPlugin({\n          editorId,\n          saveDebounceMs,\n          events,\n          pushEvent: this.pushEvent.bind(this),\n          handleEvent: this.handleEvent.bind(this),\n        }),\n        createPhoenixUploadAdapterPlugin(),\n      ]),\n    );\n\n    // Mix custom translations with loaded translations.\n    const loadedTranslations = await loadAllEditorTranslations(language, hasPremium);\n    const mixedTranslations = [\n      ...loadedTranslations,\n      normalizeCustomTranslations(customTranslations?.dictionary || {}),\n    ]\n      .filter(translations => !isEmptyObject(translations));\n\n    // Let's query all elements, and create basic configuration.\n    let initialData: string | Record<string, string> = queryEditablesSnapshotContent(editorId);\n\n    if (isSingleRootEditor(type)) {\n      initialData = initialData['main'] || '';\n    }\n\n    // Depending of the editor type, and parent lookup for nearest context or initialize it without it.\n    const editor = await (async () => {\n      let sourceElements: HTMLElement | Record<string, HTMLElement> = queryEditablesElements(editorId);\n\n      // Handle special case when user specified `initialData` of several root elements, but editable components\n      // are not yet present in the DOM. In other words - editor is initialized before attaching root elements.\n      if (!(sourceElements instanceof HTMLElement) && !('main' in sourceElements)) {\n        const requiredRoots = (\n          type === 'decoupled'\n            ? ['main']\n            : Object.keys(initialData as Record<string, string>)\n        );\n\n        if (!checkIfAllRootsArePresent(sourceElements, requiredRoots)) {\n          sourceElements = await waitForAllRootsToBePresent(editorId, requiredRoots);\n          initialData = queryEditablesSnapshotContent(editorId);\n        }\n      }\n\n      // If single root editor, unwrap the element from the object.\n      if (isSingleRootEditor(type) && 'main' in sourceElements) {\n        sourceElements = sourceElements['main'];\n      }\n\n      // Construct parsed config. First resolve DOM element references in the provided configuration.\n      let resolvedConfig = resolveEditorConfigElementReferences(config);\n\n      // Then resolve translation references in the provided configuration, using the mixed translations.\n      resolvedConfig = resolveEditorConfigTranslations([...mixedTranslations].reverse(), language.ui, resolvedConfig);\n\n      const parsedConfig = {\n        ...resolvedConfig,\n        initialData,\n        licenseKey: license.key,\n        plugins: loadedPlugins,\n        language,\n        ...mixedTranslations.length && {\n          translations: mixedTranslations,\n        },\n      };\n\n      if (!context || !(sourceElements instanceof HTMLElement)) {\n        return Constructor.create(sourceElements as any, parsedConfig);\n      }\n\n      const result = await createEditorInContext({\n        context,\n        element: sourceElements,\n        creator: Constructor,\n        config: parsedConfig,\n      });\n\n      return result.editor;\n    })();\n\n    if (isSingleRootEditor(type) && editableHeight) {\n      setEditorEditableHeight(editor, editableHeight);\n    }\n\n    return editor;\n  };\n}\n\n/**\n * Checks if all required root elements are present in the elements object.\n *\n * @param elements The elements object mapping root IDs to HTMLElements.\n * @param requiredRoots The list of required root IDs.\n * @returns True if all required roots are present, false otherwise.\n */\nfunction checkIfAllRootsArePresent(elements: Record<string, HTMLElement>, requiredRoots: string[]): boolean {\n  return requiredRoots.every(rootId => elements[rootId]);\n}\n\n/**\n * Waits for all required root elements to be present in the DOM.\n *\n * @param editorId The editor's ID.\n * @param requiredRoots The list of required root IDs.\n * @returns A promise that resolves to the record of root elements.\n */\nasync function waitForAllRootsToBePresent(\n  editorId: EditorId,\n  requiredRoots: string[],\n): Promise<Record<string, HTMLElement>> {\n  return waitFor(\n    () => {\n      const elements = queryEditablesElements(editorId) as unknown as Record<string, HTMLElement>;\n\n      if (!checkIfAllRootsArePresent(elements, requiredRoots)) {\n        throw new Error(\n          'It looks like not all required root elements are present yet.\\n'\n          + '* If you want to wait for them, ensure they are registered before editor initialization.\\n'\n          + '* If you want lazy initialize roots, consider removing root values from the `initialData` config '\n          + 'and assign initial data in editable components.\\n'\n          + `Missing roots: ${requiredRoots.filter(rootId => !elements[rootId]).join(', ')}.`,\n        );\n      }\n\n      return elements;\n    },\n    { timeOutAfter: 2000, retryAfter: 100 },\n  );\n}\n\n/**\n * Phoenix LiveView hook for CKEditor 5.\n */\nexport const EditorHook = makeHook(EditorHookImpl);\n","import type { Editor } from 'ckeditor5';\n\n/**\n * Creates a function that synchronizes root attributes on the given editor root.\n *\n * The returned function tracks which attributes were set by itself and will only\n * remove attributes it previously managed. This avoids interfering with other\n * consumers that may also change attributes on the same root.\n *\n * @param editor The editor instance containing the root to manage.\n * @param rootName The name of the root to manage attributes on.\n * @returns A function that can be called with the desired set of attributes to apply them to the root.\n *          Calling the function with `null` or an empty object will clear all attributes previously set by it.\n */\nexport function createRootAttributesUpdater(editor: Editor, rootName: string): RootAttributesUpdater {\n  const managedAttrs = new Set<string>();\n\n  return (rootAttributes?: Record<string, unknown> | null) => {\n    editor.model.enqueueChange({ isUndoable: false }, (writer) => {\n      const root = editor.model.document.getRoot(rootName);\n\n      /* v8 ignore next if -- @preserve */\n      if (!root) {\n        return;\n      }\n\n      // Remove previously managed attributes that are no longer requested.\n      for (const key of managedAttrs) {\n        if (rootAttributes && key in rootAttributes) {\n          continue;\n        }\n\n        writer.removeAttribute(key, root);\n        managedAttrs.delete(key);\n      }\n\n      // Apply or overwrite requested attributes.\n      for (const [key, value] of Object.entries(rootAttributes ?? {})) {\n        writer.setAttribute(key, value, root);\n        managedAttrs.add(key);\n      }\n    });\n  };\n}\n\nexport type RootAttributesUpdater = (rootAttributes?: Record<string, unknown> | null) => void;\n","import type { Editor } from 'ckeditor5';\n\nimport type { RootAttributesUpdater } from './root-attributes-updater';\n\nimport { ClassHook, makeHook, parseJsonIfPresent } from '../../shared';\nimport { EditorsRegistry } from '../editor/editors-registry';\nimport { createRootAttributesUpdater } from './root-attributes-updater';\n\nclass RootValueSentinel extends ClassHook {\n  /**\n   * The promise that resolves to the editor instance once it's registered.\n   * It can be either a MultiRootEditor or a DecoupledEditor, depending on the type of editor being used.\n   * It will be null if the editor is not registered yet or if the hook is being destroyed before the editor is registered.\n   */\n  private editorPromise: Promise<Editor | null> | null = null;\n\n  /**\n   * When the editor is focused and the value attribute changes, we want to wait until it blurs to\n   * avoid disrupting the user while typing. This variable holds the pending value that should be applied\n   * once the editor blurs. It is set to null when there is no pending value or when the user makes changes in the editor,\n   * indicating that the pending value should be discarded.\n   */\n  private pendingValue: string | null = null;\n\n  /**\n   * Cache the previous value to avoid reacting to attribute changes that don't actually change the value.\n   * This can happen when the parent LiveView re-renders and sets the same value again, which would otherwise cause an\n   * unnecessary update in the editor.\n   */\n  private previousValue: string | null = null;\n\n  /**\n   * Updater created once the editor is ready. Tracks which root attributes\n   * were applied by this sentinel so it can clean them up independently of\n   * other consumers.\n   */\n  private attrsUpdater: RootAttributesUpdater | null = null;\n\n  /**\n   * Helper to read and parse attributes from the element.\n   * It assumes that the element has the correct attributes set, as they are required for the hook to function properly.\n   */\n  private get attrs() {\n    return {\n      editorId: this.el.getAttribute('data-cke-editor-id')!,\n      rootName: this.el.getAttribute('data-cke-root-name')!,\n      rootAttributes: parseJsonIfPresent<Record<string, unknown>>(this.el.getAttribute('data-cke-root-attrs')),\n      value: this.el.getAttribute('data-cke-value')!,\n    };\n  }\n\n  /**\n   * When the hook is mounted, we will wait for the editor to be registered and then set the initial value of the root.\n   */\n  override async mounted() {\n    const { editorId, value, rootName } = this.attrs;\n\n    this.previousValue = value;\n    this.editorPromise = EditorsRegistry.the.execute(editorId, (editor: Editor) => {\n      /* v8 ignore next 3 */\n      if (this.isBeingDestroyed()) {\n        return null;\n      }\n\n      this.setupSyncHandlers(editor, rootName);\n\n      return editor;\n    });\n  }\n\n  /**\n   * When the value attribute changes, we want to update the editor root value.\n   * However, if the editor is focused, we want to wait until it blurs to avoid disrupting the user while typing.\n   */\n  override async updated() {\n    const { rootName, value, rootAttributes } = this.attrs;\n    const editor = await this.editorPromise;\n\n    if (!editor || editor.state === 'destroyed') {\n      return;\n    }\n\n    // Synchronize root attributes on every update, regardless of value changes.\n    this.attrsUpdater?.(rootAttributes);\n\n    // React only if the value attribute actually changed.\n    if (value !== this.previousValue) {\n      this.previousValue = value;\n\n      if (editor.ui.focusTracker.isFocused) {\n        this.pendingValue = value;\n      }\n      else {\n        this.setRootValue(editor, rootName, value);\n      }\n    }\n  }\n\n  /**\n   * Sets up focus-aware sync handlers on the editor.\n   * Registers cleanup via onBeforeDestroy.\n   */\n  private setupSyncHandlers(editor: Editor, rootName: string) {\n    this.attrsUpdater = createRootAttributesUpdater(editor, rootName);\n    this.attrsUpdater(this.attrs.rootAttributes);\n\n    const onDataChange = () => {\n      this.pendingValue = null;\n    };\n\n    const onFocusChange = () => {\n      if (!editor.ui.focusTracker.isFocused && this.pendingValue !== null) {\n        this.setRootValue(editor, rootName, this.pendingValue);\n        this.pendingValue = null;\n      }\n    };\n\n    editor.model.document.on('change:data', onDataChange);\n    editor.ui.focusTracker.on('change:isFocused', onFocusChange);\n\n    this.onBeforeDestroy(() => {\n      editor.model.document.off('change:data', onDataChange);\n      editor.ui.focusTracker.off('change:isFocused', onFocusChange);\n    });\n  }\n\n  /**\n   * Sets the value of a specific root in the editor.\n   */\n  private setRootValue(editor: Editor, rootName: string, value: string) {\n    const current = editor.getData({ rootName });\n\n    if (current !== value) {\n      editor.setData({ [rootName]: value });\n    }\n  }\n}\n\nexport const RootValueSentinelHook = makeHook(RootValueSentinel);\n","import { ClassHook, makeHook } from '../shared';\nimport { EditorsRegistry } from './editor/editors-registry';\n\n/**\n * UI Part hook for Phoenix LiveView. It allows you to create UI parts for multi-root editors.\n */\nclass UIPartHookImpl extends ClassHook {\n  /**\n   * The name of the hook.\n   */\n  private mountedPromise: Promise<void> | null = null;\n\n  /**\n   * Attributes for the editable instance.\n   */\n  private get attrs() {\n    const value = {\n      editorId: this.el.getAttribute('data-cke-editor-id') || null,\n      name: this.el.getAttribute('data-cke-ui-part-name')!,\n    };\n\n    Object.defineProperty(this, 'attrs', {\n      value,\n      writable: false,\n      configurable: false,\n      enumerable: true,\n    });\n\n    return value;\n  }\n\n  /**\n   * Mounts the editable component.\n   */\n  override async mounted() {\n    const { editorId, name } = this.attrs;\n\n    // If the editor is not registered yet, we will wait for it to be registered.\n    this.mountedPromise = EditorsRegistry.the.execute(editorId, (editor) => {\n      /* v8 ignore next 3 */\n      if (this.isBeingDestroyed()) {\n        return;\n      }\n\n      const { ui } = editor;\n\n      const uiViewName = mapUIPartView(name);\n      const uiPart = (ui.view as any)[uiViewName!];\n\n      if (!uiPart) {\n        console.error(`Unknown UI part name: \"${name}\". Supported names are \"toolbar\" and \"menubar\".`);\n        return;\n      }\n\n      this.el.appendChild(uiPart.element);\n    });\n  }\n\n  /**\n   * Destroys the editable component. Unmounts root from the editor.\n   */\n  override async destroyed() {\n    // Let's hide the element during destruction to prevent flickering.\n    this.el.style.display = 'none';\n\n    // Let's wait for the mounted promise to resolve before proceeding with destruction.\n    await this.mountedPromise;\n    this.mountedPromise = null;\n\n    // Unmount all UI parts from the editor.\n    this.el.innerHTML = '';\n  }\n}\n\n/**\n * Maps the UI part name to the corresponding view in the editor.\n */\nfunction mapUIPartView(name: string): string | null {\n  switch (name) {\n    case 'toolbar':\n      return 'toolbar';\n\n    case 'menubar':\n      return 'menuBarView';\n\n    default:\n      return null;\n  }\n}\n\n/**\n * Phoenix LiveView hook for CKEditor 5 UI parts.\n */\nexport const UIPartHook = makeHook(UIPartHookImpl);\n","import { ContextHook } from './context';\nimport { EditableHook } from './editable';\nimport { EditorHook } from './editor';\nimport { RootValueSentinelHook } from './root-value-sentinel';\nimport { UIPartHook } from './ui-part';\n\nexport const Hooks = {\n  CKEditor5: EditorHook,\n  CKEditable: EditableHook,\n  CKUIPart: UIPartHook,\n  CKContext: ContextHook,\n  CKRootValueSentinel: RootValueSentinelHook,\n};\n"],"names":["AsyncRegistry","id","onSuccess","onError","item","error","resolve","reject","pending","callback","initializationErrors","promises","watcher","camelCase","str","_","c","m","debounce","delay","timeoutId","args","isPlainObject","value","proto","deepCamelCaseKeys","input","result","key","filterObjectValues","obj","filter","filteredEntries","getCsrfToken","metaTag","match","ClassHook","cb","makeHook","constructor","instance","event","payload","selector","isEmptyObject","isNil","mapObjectValues","mapper","mappedEntries","parseIntIfNotNull","parsed","parseJsonIfPresent","json","shallowEqual","objA","objB","keysA","keysB","uid","waitFor","timeOutAfter","retryAfter","startTime","lastError","timeoutTimerId","tick","err","CONTEXT_EDITOR_WATCHDOG_SYMBOL","createEditorInContext","element","context","creator","config","editorContextId","_element","_config","editor","contextDescriptor","originalDestroy","unwrapEditorContext","isSingleRootEditor","editorType","loadEditorConstructor","type","PKG","EditorConstructor","CustomEditorPluginsRegistry","name","reader","loadEditorPlugins","plugins","basePackage","premiumPackage","loaders","plugin","customPlugin","basePkgImport","premiumPkgImport","loadAllEditorTranslations","language","hasPremium","translations","loadEditorPkgTranslations","pkg","lang","pack","loadEditorTranslation","normalizeCustomTranslations","dictionary","queryEditablesElements","editorId","editables","queryAllEditorEditables","content","queryEditablesSnapshotContent","values","initialValue","iterator","acc","rootEditorElement","initialRootEditableValue","contentElement","currentMain","EDITOR_TYPES","readPresetOrThrow","attributeValue","license","rest","resolveEditorConfigElementReferences","anyObj","resolveEditorConfigTranslations","getTranslationValue","langData","setEditorEditableHeight","height","editing","writer","EDITOR_WATCHDOG_SYMBOL","wrapWithWatchdog","Editor","EditorWatchdog","watchdog","unwrapEditorWatchdog","ContextsRegistry","readContextConfigOrThrow","ContextHookImpl","get","attr","customTranslations","watchdogConfig","loadedPlugins","mixedTranslations","resolvedConfig","ContextWatchdog","Context","isContextHookHTMLElement","el","getNearestContextParent","parent","getNearestContextParentPromise","ContextHook","EditorsRegistry","EditableHookImpl","editableId","rootName","ui","model","editable","unmount","syncEditorRootToInput","root","EditableHook","sync","debouncedSync","createPhoenixUploadAdapterPlugin","Plugin","FileRepository","uploadUrl","fileRepository","loader","Adapter","file","data","headers","csrfToken","response","errorMessage","errorData","createSyncEditorWithInputPlugin","saveDebounceMs","newValue","createSyncEditorWithPhoenixPlugin","options","events","pushEvent","handleEvent","getEditorRootsValues","targetId","lastValue","isDestroyed","pushContentChange","debouncedPushContentChange","eventType","pushEventCallback","isFocused","EditorHookImpl","has","editorContext","preset","contextId","editableHeight","Constructor","wrapped","newInstance","initialData","sourceElements","requiredRoots","checkIfAllRootsArePresent","waitForAllRootsToBePresent","parsedConfig","elements","rootId","EditorHook","createRootAttributesUpdater","managedAttrs","rootAttributes","RootValueSentinel","onDataChange","onFocusChange","RootValueSentinelHook","UIPartHookImpl","uiViewName","mapUIPartView","uiPart","UIPartHook","Hooks"],"mappings":"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EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,QAAS,OAAO,KAAM,QAAO,kDAAkD,EACpF,IAAK,KAAM,OAAO,KAAM,QAAO,+CAA+C,EAC9E,IAAK,KAAM,OAAO,K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"}