{"version":3,"file":"AbstractSplitText.mjs","sources":["../../../src/scene/text-split/AbstractSplitText.ts"],"sourcesContent":["import { type PointData } from '../../maths/point/PointData';\nimport { Container, type ContainerOptions } from '../container/Container';\nimport { type DestroyOptions } from '../container/destroyTypes';\nimport { TextStyle, type TextStyleOptions } from '../text/TextStyle';\nimport { type SplitableTextObject, type TextSplitOutput } from './types';\n\n/**\n * Configuration options for text splitting.\n * @category text\n * @standard\n */\nexport interface AbstractSplitOptions\n{\n    /** Text content to be split */\n    text: string;\n\n    /** Text styling - accepts TextStyle instance or style object */\n    style: TextStyle | Partial<TextStyleOptions>;\n\n    /**\n     * Enables automatic splitting on text/style changes\n     * @default true\n     */\n    autoSplit?: boolean;\n\n    /**\n     * Transform origin for line segments. Range: [0-1]\n     * @example\n     * ```ts\n     * lineAnchor: 0.5        // Center horizontally and vertically\n     * lineAnchor: { x: 0, y: 0.5 }  // Left-center alignment\n     *\n     * ```\n     * @default 0\n     */\n    lineAnchor?: number | PointData;\n\n    /**\n     * Transform origin for word segments. Range: [0-1]\n     * @example\n     * ```ts\n     * wordAnchor: { x: 1, y: 0 }  // Top-right alignment\n     * wordAnchor: 0.5  // Center alignment\n     * ```\n     * @default 0\n     */\n    wordAnchor?: number | PointData;\n\n    /**\n     * Transform origin for character segments. Range: [0-1]\n     * @example\n     * ```ts\n     * charAnchor: { x: 0.5, y: 1 }  // Bottom-center alignment\n     * charAnchor: 0.5  // Center alignment\n     * ```\n     * @default 0\n     */\n    charAnchor?: number | PointData;\n}\n\n/**\n * Configuration options for SplitText, combining container properties with text splitting settings.\n * @example Basic Usage\n * ```ts\n * const options: SplitTextOptions = {\n *   text: 'Hello World',\n *   style: { fontSize: 32, fill: 0xffffff },\n *   // Transform origins\n *   lineAnchor: 0.5,                // Center each line\n *   wordAnchor: { x: 0, y: 0.5 },  // Left-center each word\n *   charAnchor: { x: 0.5, y: 1 },  // Bottom-center each char\n * };\n * ```\n * @example Advanced Configuration\n * ```ts\n * const options: SplitTextOptions = {\n *   // Text content and style\n *   text: 'Multi\\nLine Text',\n *   style: new TextStyle({\n *     fontSize: 24,\n *     fill: 'white',\n *     strokeThickness: 2,\n *   }),\n *\n *   // Container properties\n *   x: 100,\n *   y: 100,\n *   alpha: 0.8,\n *\n *   // Splitting settings\n *   autoSplit: true,\n *\n *   // Transform origins (normalized 0-1)\n *   lineAnchor: { x: 1, y: 0 },    // Top-right\n *   wordAnchor: 0.5,               // Center\n *   charAnchor: { x: 0, y: 1 },    // Bottom-left\n * };\n * ```\n *\n * Properties:\n * - Container options from {@link ContainerOptions}\n * - Text split options from {@link AbstractSplitOptions}\n * @see {@link AbstractSplitText} For the main implementation\n * @see {@link ContainerOptions} For base container properties\n * @see {@link AbstractSplitOptions} For text splitting options\n * @category text\n * @standard\n */\nexport interface AbstractSplitTextOptions extends ContainerOptions, AbstractSplitOptions {}\n\n/**\n * @experimental\n * A container that splits text into individually manipulatable segments (lines, words, and characters)\n * for advanced text effects and animations.\n * @example Basic Usage\n * ```ts\n * const text = new SplitText({\n *   text: \"Hello World\",\n *   style: { fontSize: 24 },\n *   // Origin points for transformations (0-1 range)\n *   lineAnchor: 0.5,  // Center of each line\n *   wordAnchor: { x: 0, y: 0.5 },  // Left-center of each word\n *   charAnchor: { x: 0.5, y: 1 },  // Bottom-center of each character\n *   autoSplit: true  // Auto-update segments on text/style changes\n * });\n * ```\n *\n * Features:\n * - Hierarchical text splitting (lines → words → characters)\n * - Independent transformation origins for each segment level\n * - Automatic or manual segment updates\n * - Support for both canvas text and bitmap text\n * @example Animation Example\n * ```ts\n * // Character fade-in sequence\n * text.chars.forEach((char, i) => {\n *   gsap.from(char, {\n *     alpha: 0,\n *     delay: i * 0.1\n *   });\n * });\n *\n * // Word scale animation\n * text.words.forEach((word, i) => {\n *   gsap.to(word.scale, {\n *     x: 1.2, y: 1.2,\n *     yoyo: true,\n *     repeat: -1,\n *     delay: i * 0.2\n *   });\n * });\n *\n * // Line slide-in effect\n * text.lines.forEach((line, i) => {\n *   gsap.from(line, {\n *     x: -200,\n *     delay: i * 0.3\n *   });\n * });\n * ```\n *\n * Configuration Options:\n * - `text`: The string to render and segment\n * - `style`: TextStyle instance or configuration object\n * - `autoSplit`: Automatically update segments on changes (default: true)\n * - `lineAnchor`: Transform origin for lines (default: 0)\n * - `wordAnchor`: Transform origin for words (default: 0)\n * - `charAnchor`: Transform origin for characters (default: 0)\n *\n * > [!NOTE] Anchor points are normalized (0-1):\n * > - 0,0: Top-left\n * > - 0.5,0.5: Center\n * > - 1,1: Bottom-right\n *\n * > [!WARNING] Limitations\n * > - Character spacing may differ slightly from standard text due to browser\n * >   kerning being lost when characters are separated\n * @category text\n * @standard\n */\nexport abstract class AbstractSplitText<T extends SplitableTextObject> extends Container\n{\n    /**\n     * Individual character segments of the text.\n     * @example\n     * ```ts\n     * // Fade in characters sequentially\n     * text.chars.forEach((char, i) => {\n     *   char.alpha = 0;\n     *   gsap.to(char, {\n     *     alpha: 1,\n     *     delay: i * 0.1\n     *   });\n     * });\n     * ```\n     */\n    public chars: T[];\n\n    /**\n     * Word segments of the text, each containing one or more characters.\n     * @example\n     * ```ts\n     * // Scale words on hover\n     * text.words.forEach(word => {\n     *   word.interactive = true;\n     *   word.on('pointerover', () => {\n     *     gsap.to(word.scale, { x: 1.2, y: 1.2 });\n     *   });\n     *   word.on('pointerout', () => {\n     *     gsap.to(word.scale, { x: 1, y: 1 });\n     *   });\n     * });\n     * ```\n     */\n    public words: Container[];\n\n    /**\n     * Line segments of the text, each containing one or more words.\n     * @example\n     * ```ts\n     * // Stagger line entrance animations\n     * text.lines.forEach((line, i) => {\n     *   line.x = -200;\n     *   gsap.to(line, {\n     *     x: 0,\n     *     duration: 0.5,\n     *     delay: i * 0.2,\n     *     ease: 'back.out'\n     *   });\n     * });\n     * ```\n     */\n    public lines: Container[];\n\n    protected _originalText: string;\n    protected _lineAnchor: number | PointData;\n    protected _wordAnchor: number | PointData;\n    protected _charAnchor: number | PointData;\n    protected _autoSplit: boolean;\n    protected _style: TextStyle;\n\n    protected _dirty: boolean = false;\n    protected _canReuseChars: boolean = false;\n\n    constructor(config: AbstractSplitTextOptions)\n    {\n        const {\n            text,\n            style,\n            autoSplit,\n            lineAnchor,\n            wordAnchor,\n            charAnchor,\n            ...options\n        } = config;\n\n        super(options);\n        this.chars = [];\n        this.words = [];\n        this.lines = [];\n\n        this._originalText = text;\n        this._autoSplit = autoSplit;\n        this._lineAnchor = lineAnchor;\n        this._wordAnchor = wordAnchor;\n        this._charAnchor = charAnchor;\n\n        // setting the style will segment the text if autoSplit is true\n        this.style = style;\n    }\n\n    protected abstract splitFn(): TextSplitOutput<T>;\n\n    /**\n     * Splits the text into lines, words, and characters.\n     * Call this manually when autoSplit is false.\n     * @example Manual Splitting\n     * ```ts\n     * const text = new SplitText({\n     *   text: 'Manual Update',\n     *   autoSplit: false\n     * });\n     *\n     * text.text = 'New Content';\n     * text.style = { fontSize: 32 };\n     * text.split(); // Apply changes\n     * ```\n     */\n    public split(): void\n    {\n        const res: TextSplitOutput<T> = this.splitFn();\n\n        this.chars = res.chars;\n        this.words = res.words;\n        this.lines = res.lines;\n\n        this.addChild(...this.lines);\n\n        // force origin to be set\n        this.charAnchor = this._charAnchor;\n        this.wordAnchor = this._wordAnchor;\n        this.lineAnchor = this._lineAnchor;\n\n        this._dirty = false;\n        this._canReuseChars = true;\n    }\n\n    get text(): string\n    {\n        return this._originalText;\n    }\n    /**\n     * Gets or sets the text content.\n     * Setting new text triggers splitting if autoSplit is true.\n     * > [!NOTE] Setting this frequently can have a performance impact, especially with large texts and canvas text.\n     * @example Dynamic Text Updates\n     * ```ts\n     * const text = new SplitText({\n     *   text: 'Original',\n     *   autoSplit: true\n     * });\n     *\n     * // Auto-splits on change\n     * text.text = 'Updated Content';\n     *\n     * // Manual update\n     * text.autoSplit = false;\n     * text.text = 'Manual Update';\n     * text.split();\n     * ```\n     */\n    set text(value: string)\n    {\n        this._originalText = value;\n        this.lines.forEach((line) => line.destroy({ children: true }));\n        this.lines.length = 0;\n        this.words.length = 0;\n        this.chars.length = 0;\n        this._canReuseChars = false;\n        // You can't reuse chars if the text changes\n        this.onTextUpdate();\n    }\n\n    private _setOrigin(\n        value: number | PointData,\n        elements: Array<Container | T>,\n        property: '_lineAnchor' | '_wordAnchor' | '_charAnchor',\n    ): void\n    {\n        let originPoint: PointData;\n\n        if (typeof value === 'number')\n        {\n            originPoint = { x: value, y: value };\n        }\n        else\n        {\n            originPoint = { x: value.x, y: value.y };\n        }\n\n        elements.forEach((element) =>\n        {\n            const localBounds = element.getLocalBounds();\n\n            // Calculate origin position relative to the bounds\n            const originX = localBounds.minX + (localBounds.width * originPoint.x);\n            const originY = localBounds.minY + (localBounds.height * originPoint.y);\n\n            element.origin.set(originX, originY);\n        });\n\n        this[property] = value;\n    }\n\n    /**\n     * Gets or sets the transform anchor for line segments.\n     * The anchor point determines the center of rotation and scaling for each line.\n     * @example Setting Line Anchors\n     * ```ts\n     * // Center rotation/scaling\n     * text.lineAnchor = 0.5;\n     *\n     * // Rotate/scale from top-right corner\n     * text.lineAnchor = { x: 1, y: 0 };\n     *\n     * // Custom anchor point\n     * text.lineAnchor = {\n     *   x: 0.2, // 20% from left\n     *   y: 0.8  // 80% from top\n     * };\n     * ```\n     */\n    get lineAnchor(): number | PointData\n    {\n        return this._lineAnchor;\n    }\n    set lineAnchor(value: number | PointData)\n    {\n        this._setOrigin(value, this.lines, '_lineAnchor');\n    }\n\n    /**\n     * Gets or sets the transform anchor for word segments.\n     * The anchor point determines the center of rotation and scaling for each word.\n     * @example\n     * ```ts\n     * // Center each word\n     * text.wordAnchor = 0.5;\n     *\n     * // Scale from bottom-left\n     * text.wordAnchor = { x: 0, y: 1 };\n     *\n     * // Rotate around custom point\n     * text.wordAnchor = {\n     *   x: 0.75,  // 75% from left\n     *   y: 0.5    // Middle vertically\n     * };\n     * ```\n     */\n    get wordAnchor(): number | PointData\n    {\n        return this._wordAnchor;\n    }\n    set wordAnchor(value: number | PointData)\n    {\n        this._setOrigin(value, this.words, '_wordAnchor');\n    }\n\n    /**\n     * Gets or sets the transform anchor for character segments.\n     * The anchor point determines the center of rotation and scaling for each character.\n     * @example Setting Character Anchors\n     * ```ts\n     * // Center each character\n     * text.charAnchor = 0.5;\n     *\n     * // Rotate from top-center\n     * text.charAnchor = { x: 0.5, y: 0 };\n     *\n     * // Scale from bottom-right\n     * text.charAnchor = { x: 1, y: 1 };\n     * ```\n     * @example Animation with Anchors\n     * ```ts\n     * // Rotate characters around their centers\n     * text.charAnchor = 0.5;\n     * text.chars.forEach((char, i) => {\n     *   gsap.to(char, {\n     *     rotation: Math.PI * 2,\n     *     duration: 1,\n     *     delay: i * 0.1,\n     *     repeat: -1\n     *   });\n     * });\n     * ```\n     */\n    get charAnchor(): number | PointData\n    {\n        return this._charAnchor;\n    }\n    set charAnchor(value: number | PointData)\n    {\n        this._setOrigin(value, this.chars, '_charAnchor');\n    }\n\n    get style(): TextStyle\n    {\n        return this._style;\n    }\n\n    /**\n     * The style configuration for the text.\n     * Can be a TextStyle instance or a configuration object.\n     * @example\n     * ```ts\n     * const text = new Text({\n     *     text: 'Styled Text',\n     *     style: {\n     *         fontSize: 24,\n     *         fill: 0xff1010, // Red color\n     *         fontFamily: 'Arial',\n     *         align: 'center', // Center alignment\n     *         stroke: { color: '#4a1850', width: 5 }, // Purple stroke\n     *         dropShadow: {\n     *             color: '#000000', // Black shadow\n     *             blur: 4, // Shadow blur\n     *             distance: 6 // Shadow distance\n     *         }\n     *     }\n     * });\n     * // Update style dynamically\n     * text.style = {\n     *     fontSize: 30, // Change font size\n     *     fill: 0x00ff00, // Change color to green\n     *     align: 'right', // Change alignment to right\n     *     stroke: { color: '#000000', width: 2 }, // Add black stroke\n     * }\n     */\n    set style(style: TextStyle | Partial<TextStyle> | TextStyleOptions)\n    {\n        style ||= {};\n\n        this._style = new TextStyle(style);\n\n        this.styleChanged();\n    }\n\n    /**\n     * Used to notify the text that the style has changed.\n     * This will re-split the text and re-apply the style.\n     * @example\n     * ```ts\n     * text.style.fontSize = 32;\n     * text.styleChanged();\n     * ```\n     */\n    public styleChanged(): void\n    {\n        // tidy up word/line containers, characters can be reused\n        this.words.forEach((word) => word.destroy());\n        this.words.length = 0;\n\n        this.lines.forEach((line) => line.destroy());\n        this.lines.length = 0;\n\n        this._canReuseChars = true;\n\n        this.onTextUpdate();\n    }\n\n    protected onTextUpdate(): void\n    {\n        this._dirty = true;\n\n        if (this._autoSplit)\n        {\n            this.split();\n        }\n    }\n\n    /**\n     * Destroys the SplitText instance and all its resources.\n     * Cleans up all segment arrays, event listeners, and optionally the text style.\n     * @param options - Destroy configuration options\n     * @example\n     * ```ts\n     * // Clean up everything\n     * text.destroy({ children: true, texture: true, style: true });\n     *\n     * // Remove from parent but keep style\n     * text.destroy({ children: true, style: false });\n     * ```\n     */\n    public destroy(options?: DestroyOptions): void\n    {\n        super.destroy(options);\n        this.chars = [];\n        this.words = [];\n        this.lines = [];\n        if (typeof options === 'boolean' ? options : options?.style)\n        {\n            this._style.destroy(options);\n        }\n\n        this._style = null;\n        this._originalText = '';\n    }\n}\n"],"names":[],"mappings":"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"}