UNPKG

phx-react

Version:

PHX REACT

266 lines • 9.32 kB
"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(), resizable: true, 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