All files / roosterjs-content-model-plugins/lib/imageEdit/Rotator createImageRotator.ts

100% Statements 15/15
75% Branches 3/4
100% Functions 5/5
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 851x 1x 1x     1x                       1x 18x   18x 18x 18x     18x                 18x 18x   18x 18x                                       18x                                                    
import { createElement } from '../../pluginUtils/CreateElement/createElement';
import { ImageEditElementClass } from '../types/ImageEditElementClass';
import { isElementOfType, isNodeOfType } from 'roosterjs-content-model-dom';
import type { CreateElementData } from '../../pluginUtils/CreateElement/CreateElementData';
import type { ImageHtmlOptions } from '../types/ImageHtmlOptions';
import {
    ROTATE_GAP,
    ROTATE_HANDLE_TOP,
    ROTATE_ICON_MARGIN,
    ROTATE_SIZE,
    ROTATE_WIDTH,
} from '../constants/constants';
 
/**
 * @internal
 * Get HTML for rotate elements, including the rotate handle with icon, and a line between the handle and the image
 */
export function createImageRotator(doc: Document, htmlOptions: ImageHtmlOptions) {
    return getRotateHTML(htmlOptions)
        .map(element => {
            const rotator = createElement(element, doc);
            Eif (isNodeOfType(rotator, 'ELEMENT_NODE') && isElementOfType(rotator, 'div')) {
                return rotator;
            }
        })
        .filter(rotator => !!rotator) as HTMLDivElement[];
}
 
/**
 * @internal
 * Get HTML for rotate elements, including the rotate handle with icon, and a line between the handle and the image
 *
 */
function getRotateHTML({
    borderColor,
    rotateHandleBackColor,
}: ImageHtmlOptions): CreateElementData[] {
    const handleLeft = ROTATE_SIZE / 2;
    return [
        {
            tag: 'div',
            className: ImageEditElementClass.RotateCenter,
            style: `position:absolute;left:50%;width:1px;background-color:${borderColor};top:${-ROTATE_HANDLE_TOP}px;height:${ROTATE_GAP}px;margin-left:${-ROTATE_WIDTH}px;`,
            children: [
                {
                    tag: 'div',
                    className: ImageEditElementClass.RotateHandle,
                    style: `position:absolute;background-color:${rotateHandleBackColor};border:solid 1px ${borderColor};border-radius:50%;width:${ROTATE_SIZE}px;height:${ROTATE_SIZE}px;left:-${
                        handleLeft + ROTATE_WIDTH
                    }px;cursor:move;top:${-ROTATE_SIZE}px;line-height: 0px;`,
                    children: [getRotateIconHTML(borderColor)],
                },
            ],
        },
    ];
}
 
function getRotateIconHTML(borderColor: string): CreateElementData {
    return {
        tag: 'svg',
        namespace: 'http://www.w3.org/2000/svg',
        style: `width:16px;height:16px;margin: ${ROTATE_ICON_MARGIN}px ${ROTATE_ICON_MARGIN}px`,
        children: [
            {
                tag: 'path',
                namespace: 'http://www.w3.org/2000/svg',
                attributes: {
                    d: 'M 10.5,10.0 A 3.8,3.8 0 1 1 6.7,6.3',
                    transform: 'matrix(1.1 1.1 -1.1 1.1 11.6 -10.8)',
                    ['fill-opacity']: '0',
                    stroke: borderColor,
                },
            },
            {
                tag: 'path',
                namespace: 'http://www.w3.org/2000/svg',
                attributes: {
                    d: 'M12.0 3.648l.884-.884.53 2.298-2.298-.53z',
                    stroke: borderColor,
                },
            },
        ],
    };
}