"use strict";
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.ImageNode = void 0;
exports.$createImageNode = $createImageNode;
exports.$isImageNode = $isImageNode;
const tslib_1 = require("tslib");
const lexical_1 = require("lexical");
const React = tslib_1.__importStar(require("react"));
const react_1 = require("react");
const ImageComponent = React.lazy(
// @ts-ignore
() => Promise.resolve().then(() => tslib_1.__importStar(require('./ImageComponent'))));
/**
 * Gets the image alignment position encoded in a wrapper class name.
 * @param className Wrapper class name to inspect.
 * @returns Matching image position, or undefined when no position class exists.
 */
function getPositionFromClassName(className) {
    if (className.includes('position-left')) {
        return 'left';
    }
    if (className.includes('position-right')) {
        return 'right';
    }
    if (className.includes('position-center')) {
        return 'center';
    }
    return undefined;
}
/**
 * Converts an imported DOM image element into an ImageNode.
 * @param domNode DOM node provided by Lexical import.
 * @returns DOM conversion output for image nodes, or null for unsupported nodes.
 */
function convertImageElement(domNode) {
    var _a;
    if (domNode instanceof HTMLImageElement) {
        const { alt: altText, height, src, width } = domNode;
        const position = getPositionFromClassName(((_a = domNode.parentElement) === null || _a === void 0 ? void 0 : _a.className) || '');
        const node = $createImageNode({ altText, height, position, src, width });
        return { node };
    }
    return null;
}
class ImageNode extends lexical_1.DecoratorNode {
    /**
     * Gets the Lexical node type for image nodes.
     * @returns Image node type.
     */
    static getType() {
        return 'image';
    }
    /**
     * Clones an existing image node.
     * @param node Image node to clone.
     * @returns Cloned image node.
     */
    static clone(node) {
        return new ImageNode(node.__src, node.__altText, node.__maxWidth, node.__width, node.__height, node.__showCaption, node.__caption, node.__position, node.__captionsEnabled, node.__key);
    }
    /**
     * Imports a serialized image node into the editor state.
     * @param serializedNode Serialized image node payload.
     * @returns Hydrated image node.
     */
    static importJSON(serializedNode) {
        const { altText, caption, height, maxWidth, position, showCaption, src, width } = serializedNode;
        const node = $createImageNode({
            altText,
            height,
            maxWidth,
            position,
            showCaption,
            src,
            width,
        });
        const nestedEditor = node.__caption;
        const editorState = nestedEditor.parseEditorState(caption.editorState);
        if (!editorState.isEmpty()) {
            nestedEditor.setEditorState(editorState);
        }
        return node;
    }
    /**
     * Exports this image node to DOM.
     * @returns DOM export output containing the image wrapper.
     */
    exportDOM() {
        const wrapper = document.createElement('span');
        wrapper.className = `editor-image position-${this.__position || 'center'}`;
        const element = document.createElement('img');
        element.setAttribute('src', this.__src);
        element.setAttribute('alt', this.__altText);
        element.setAttribute('width', this.__width.toString());
        element.setAttribute('height', this.__height.toString());
        wrapper.appendChild(element);
        return { element: wrapper };
    }
    /**
     * Defines DOM import conversions for image elements.
     * @returns DOM conversion map for image imports.
     */
    static importDOM() {
        return {
            img: () => ({
                conversion: convertImageElement,
                priority: 0,
            }),
        };
    }
    /**
     * Creates an image node instance.
     * @param src Image source URL.
     * @param altText Accessible alt text.
     * @param maxWidth Maximum rendered image width.
     * @param width Initial image width.
     * @param height Initial image height.
     * @param showCaption Whether the caption editor is visible.
     * @param caption Nested caption editor.
     * @param position Image alignment position.
     * @param captionsEnabled Whether captions are enabled.
     * @param key Optional Lexical node key.
     */
    constructor(src, altText, maxWidth, width, height, showCaption, caption, position, captionsEnabled, key) {
        super(key);
        this.__src = src;
        this.__altText = altText;
        this.__maxWidth = maxWidth;
        this.__width = width || 'inherit';
        this.__height = height || 'inherit';
        this.__showCaption = showCaption || false;
        this.__caption = caption || (0, lexical_1.createEditor)();
        this.__position = position || 'center';
        this.__captionsEnabled = captionsEnabled || captionsEnabled === undefined;
    }
    /**
     * Serializes this image node.
     * @returns Serialized image node payload.
     */
    exportJSON() {
        return {
            altText: this.getAltText(),
            caption: this.__caption.toJSON(),
            height: this.__height === 'inherit' ? 0 : this.__height,
            maxWidth: this.__maxWidth,
            position: this.__position,
            showCaption: this.__showCaption,
            src: this.getSrc(),
            type: 'image',
            version: 1,
            width: this.__width === 'inherit' ? 0 : this.__width,
        };
    }
    /**
     * Updates the stored image dimensions.
     * @param width Next image width.
     * @param height Next image height.
     */
    setWidthAndHeight(width, height) {
        const writable = this.getWritable();
        writable.__width = width;
        writable.__height = height;
    }
    /**
     * Updates caption visibility for this image.
     * @param showCaption Whether the caption should be shown.
     */
    setShowCaption(showCaption) {
        const writable = this.getWritable();
        writable.__showCaption = showCaption;
    }
    /**
     * Gets the current image alignment position.
     * @returns Current image position.
     */
    getPosition() {
        return this.__position;
    }
    /**
     * Updates the image alignment position.
     * @param position Next image position.
     */
    setPosition(position) {
        const writable = this.getWritable();
        writable.__position = position || 'center';
    }
    // View
    /**
     * Creates the DOM wrapper for this image node.
     * @param config Lexical editor config.
     * @returns Image wrapper element.
     */
    createDOM(config) {
        const span = document.createElement('span');
        const theme = config.theme;
        const className = `${theme.image} position-${this.__position || 'center'}`;
        if (className !== undefined) {
            span.className = className;
        }
        return span;
    }
    /**
     * Updates the DOM wrapper when node state changes.
     * @param prevNode Previous image node state.
     * @param dom Existing image wrapper element.
     * @param config Lexical editor config.
     * @returns False because the existing DOM element is reused.
     */
    updateDOM(prevNode, dom, config) {
        const position = this.__position;
        if (position !== prevNode.__position) {
            const className = `${config.theme.image} position-${position || 'center'}`;
            if (className !== undefined) {
                dom.className = className;
            }
        }
        return false;
    }
    /**
     * Gets the image source URL.
     * @returns Image source URL.
     */
    getSrc() {
        return this.__src;
    }
    /**
     * Gets the image alt text.
     * @returns Image alt text.
     */
    getAltText() {
        return this.__altText;
    }
    /**
     * Renders the React decorator for this image node.
     * @returns Image decorator element.
     */
    decorate() {
        return (React.createElement(react_1.Suspense, { fallback: null },
            React.createElement(ImageComponent, { altText: this.__altText, caption: this.__caption, height: this.__height, maxWidth: this.__maxWidth, nodeKey: this.getKey(), showCaption: this.__showCaption, src: this.__src, width: this.__width })));
    }
}
exports.ImageNode = ImageNode;
/**
 * Creates and inserts a replacement image node.
 * @param payload Image node creation payload.
 * @returns Created image node.
 */
function $createImageNode({ altText, caption, captionsEnabled, height, key, maxWidth = 500, position, showCaption, src, width, }) {
    return (0, lexical_1.$applyNodeReplacement)(new ImageNode(src, altText, maxWidth, width, height, showCaption, caption, position || 'center', captionsEnabled, key));
}
/**
 * Checks whether a Lexical node is an ImageNode.
 * @param node Node to test.
 * @returns True when the node is an ImageNode.
 */
function $isImageNode(node) {
    return node instanceof ImageNode;
}
//# sourceMappingURL=ImageNode.js.map