All files / roosterjs-content-model-plugins/lib/picker PickerHelperImpl.ts

100% Statements 27/27
100% Branches 8/8
100% Functions 6/6
100% Lines 24/24

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 731x 1x 1x                         1x 64x     64x 64x 64x                   2x         2x   2x     2x 2x             2x 1x 1x 1x 1x   1x                   1x 7x 6x 6x     1x  
import { formatTextSegmentBeforeSelectionMarker } from 'roosterjs-content-model-api';
import { getQueryString } from './getQueryString';
import { mergeModel } from 'roosterjs-content-model-dom';
import type {
    ContentModelDocument,
    ContentModelText,
    FormatContentModelOptions,
    IEditor,
} from 'roosterjs-content-model-types';
import type { PickerDirection, PickerHandler } from './PickerHandler';
import type { PickerHelper } from './PickerHelper';
 
/**
 * @internal
 */
export class PickerHelperImpl implements PickerHelper {
    public direction: PickerDirection | null = null;
 
    constructor(
        public readonly editor: IEditor,
        public readonly handler: PickerHandler,
        private triggerCharacter: string
    ) {}
 
    /**
     * Replace the query string with a given Content Model.
     * This is used for commit a change from picker and insert the committed content into editor.
     * @param model The Content Model to insert
     * @param options Options for formatting content model
     * @param canUndoByBackspace Whether this change can be undone using Backspace key
     */
    replaceQueryString(
        model: ContentModelDocument,
        options?: FormatContentModelOptions,
        canUndoByBackspace?: boolean
    ): void {
        this.editor.focus();
 
        formatTextSegmentBeforeSelectionMarker(
            this.editor,
            (target, previousSegment, paragraph, _, context) => {
                const potentialSegments: ContentModelText[] = [];
                const queryString = getQueryString(
                    this.triggerCharacter,
                    paragraph,
                    previousSegment,
                    potentialSegments
                );
 
                if (queryString) {
                    potentialSegments.forEach(x => (x.isSelected = true));
                    mergeModel(target, model, context);
                    context.canUndoByBackspace = canUndoByBackspace;
                    return true;
                } else {
                    return false;
                }
            },
            options
        );
    }
 
    /**
     * Notify Picker Plugin that picker is closed from the handler code, so picker plugin can quit the suggesting state
     */
    closePicker() {
        if (this.direction) {
            this.direction = null;
            this.handler.onClosePicker?.();
        }
    }
}