import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { Injectable, EventEmitter, forwardRef, Component, ChangeDetectionStrategy, ViewEncapsulation, Input, Output, ViewChild, NgModule, Directive, Self, Optional, Host, HostBinding } from '@angular/core';
import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
import * as i2 from '@angular/forms';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { Destroy, _MatInputMixinBase } from '@deja-js/component/core';
import { cloneDeep } from 'lodash-es';
import { ReplaySubject, Subject, switchMap, merge, tap, debounceTime, takeUntil, from, take, delay } from 'rxjs';
import { MatFormFieldControl, MatFormFieldModule } from '@angular/material/form-field';
import * as i3 from '@angular/material/core';

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
/**
 * Monaco Editor Service
 *
 * Service used by Monaco Editor Component to load only once instance of the Monaco Editor Library
 */
class DejaEditorService {
    /**
     * Load the CKEditor Editor Library
     *
     * @return Resolved promise when the library is loaded
     */
    initDejaEditorLib() {
        if (!this._loading) {
            this.init();
        }
        return this._loader;
    }
    init() {
        this._loader = new Promise(resolve => {
            this._loading = true;
            // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
            const wnd = window;
            // Load AMD loader if necessary
            // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
            if (!wnd.ckeditor) {
                const baseElement = document.getElementsByTagName('base')[0] || {};
                const baseHref = baseElement.href;
                // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
                const basePath = wnd.CKEDITOR_BASEPATH || `${baseHref}assets/ckeditor/`;
                const loaderScript = document.createElement('script');
                document.head.appendChild(loaderScript);
                loaderScript.type = 'text/javascript';
                loaderScript.src = `${basePath}ckeditor.js`;
                loaderScript.addEventListener('load', resolve);
            }
        });
    }
}
DejaEditorService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
DejaEditorService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorService, decorators: [{
            type: Injectable
        }] });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
/**
 * CKEditor component
 * Usage :
 *  <ckeditor [(ngModel)]="data" [config]="{...}" debounce="500"></ckeditor>
 */
class DejaEditorComponent extends Destroy {
    /**
     * Constructor
     */
    constructor(zone, changeDetectorRef, initializer) {
        super();
        this.zone = zone;
        this.changeDetectorRef = changeDetectorRef;
        this.initializer = initializer;
        // eslint-disable-next-line @angular-eslint/no-output-native
        this.change = new EventEmitter();
        this.ready = new EventEmitter();
        // eslint-disable-next-line @angular-eslint/no-output-native
        this.blur = new EventEmitter();
        // eslint-disable-next-line @angular-eslint/no-output-native
        this.focus = new EventEmitter();
        this.disabled = new EventEmitter();
        this._debounce = 0;
        this._inline = true;
        this.focus$ = new ReplaySubject(1);
        this.disabled$ = new ReplaySubject(1);
        this.onCkeditorChange$ = new Subject();
        this.writeValue$ = new ReplaySubject(1);
        this._value = '';
        this.isDestroyed = false;
        this.registeredListeners = new Map();
    }
    set readonly(value) {
        this._readonly = coerceBooleanProperty(value);
    }
    get readonly() {
        return this._readonly;
    }
    set inline(value) {
        this._inline = coerceBooleanProperty(value);
    }
    get inline() {
        return this._inline;
    }
    set debounce(debounce) {
        this._debounce = coerceNumberProperty(debounce);
    }
    get value() {
        return this._value;
    }
    set value(v) {
        if (v !== this._value) {
            this._value = v;
        }
    }
    ngOnChanges(changes) {
        if (changes.readonly && this.instance) {
            this.instance.setReadOnly(changes.readonly.currentValue);
        }
    }
    ngOnInit() {
        this.ready.pipe(switchMap(() => merge(this.focus$.pipe(tap(() => this.instance.focus())), this.disabled$.pipe(tap(value => this.disabled.emit(value)), tap(value => this.instance.setReadOnly(value))), this.onCkeditorChange$.pipe(debounceTime(this._debounce), tap(() => this.updateValue())), this.writeValue$.pipe(tap(value => this.updateCkeditorInstanceValue(value))))), takeUntil(this.destroyed$)).subscribe();
    }
    /**
     * On component destroy
     */
    ngOnDestroy() {
        super.ngOnDestroy();
        this.isDestroyed = true;
        this.cleanListeners();
        this.focus.complete();
        this.blur.complete();
        this.change.complete();
        this.disabled.complete();
        this.instance?.destroy();
    }
    /**
     * On component view init
     */
    ngAfterViewInit() {
        from(this.initializer.initDejaEditorLib()).pipe(take(1), tap(() => this.ckeditorInit(cloneDeep(this.config) || {})), delay(0), takeUntil(this.destroyed$)).subscribe(() => this.changeDetectorRef.markForCheck());
    }
    /**
     * Value update process
     */
    updateValue() {
        this.zone.run(() => {
            let value = this.instance.getData();
            if (!value) {
                value = null;
            }
            if (this.value !== value) {
                this.value = value;
                this.onChange(value);
                this.change.emit(value);
            }
        });
    }
    textAreaChange() {
        this.zone.run(() => {
            const value = this.host.nativeElement.value;
            this.onChange(value);
            this.change.emit(value);
        });
    }
    /**
     * CKEditor init
     */
    // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
    ckeditorInit(config) {
        if (typeof CKEDITOR === 'undefined') {
            console.warn('CKEditor 4.x is missing (http://ckeditor.com/)');
        }
        else {
            // Check textarea exists
            if (this.instance) {
                return;
            }
            if (this.readonly) {
                config.readOnly = this.readonly;
            }
            const keyEvents = config.on?.key;
            if (!config.on) {
                config.on = {};
            }
            config.on.key = (event) => {
                // Override CTRL+A event. Native one cause editor switch on first try
                if (event.data.code === 1114177) {
                    // CTRL + A
                    event.cancel();
                    event.stop();
                    this.instance.document.$.execCommand('SelectAll');
                }
                if (keyEvents) {
                    keyEvents(event);
                }
            };
            // CKEditor replace textarea
            if (this.inline) {
                this.instance = CKEDITOR.inline(this.host.nativeElement, config);
            }
            else {
                this.instance = CKEDITOR.replace(this.host.nativeElement, config);
            }
            // Set initial value
            this.instance.setData(this.value);
            // listen for instanceReady event
            this.listenEvent('instanceReady', evt => {
                // send the evt to the EventEmitter
                this.ready.emit(evt);
            });
            // CKEditor blur event
            this.listenEvent('blur', evt => {
                this.blur.emit(evt);
                this.onTouched();
            });
            // CKEditor focus event
            this.listenEvent('focus', evt => {
                if (!this.readonly) {
                    this.focus.emit(evt);
                }
            });
            this.registerChangeListener();
        }
    }
    /**
     * Implements ControlValueAccessor
     */
    writeValue(value) {
        this._value = value;
        this.writeValue$.next(value);
    }
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    onChange(_x) { }
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    onTouched() { }
    registerOnChange(fn) {
        this.onChange = fn;
    }
    registerOnTouched(fn) {
        this.onTouched = fn;
    }
    setDisabledState(isDisabled) {
        this.disabled$.next(isDisabled);
    }
    /**
     * Return the word at cursor position.
     *  - If the cursor is at the end of a word, it return that word.
     *  - If the cursor is at the begining of a word, it return that word.
     *  - If the cursor is in the middle of a word, it return that word.
     *  - If there are no word nearly the cursor, return null
     */
    getWordAtCursor() {
        const range = this.instance.getSelection().getRanges(true)[0];
        if (!range) {
            return null;
        }
        const word = this.firstTextNode(range);
        return (word?.toReplace) || null;
    }
    hasActiveSelection() {
        return !!this.getSelectedText();
    }
    getSelectedText() {
        if (this.instance) {
            const selection = this.instance.getSelection();
            return selection.getSelectedText();
        }
        return '';
    }
    /**
     * Replace the content of the editor.
     *  - If there is an active selection, replace this selection
     *  - If the editor is empty, simply insert the text
     *  - If the cursor is near a word, replace this word with the text
     *  - If there is no selection, no word near the cursor, simply insert the text at the cursor position
     * @param replace the string to replace with
     */
    replace(replace) {
        if (!replace || !this.instance) {
            return;
        }
        const selection = this.getSelectedText();
        if (selection) {
            // Focus is used during the CKEDITOR insertText process and cause deselection of the selected text
            // So we temporarily deactivate it
            const focus = this.instance.focus;
            this.instance.focus = () => undefined;
            this.instance.insertHtml(replace);
            this.instance.focus = focus;
            return;
        }
        const range = this.instance.getSelection().getRanges(true)[0];
        if (!range) {
            this.instance.insertHtml(replace);
            return;
        }
        const text = this.firstTextNode(range);
        if (text) {
            this.replaceWord(text, replace);
        }
        else {
            this.instance.insertHtml(replace);
        }
        this.updateValue();
        this.setFocus();
    }
    setFocus() {
        this.focus$.next();
    }
    registerChangeListener() {
        // CKEditor change event
        this.onDataChangeListener = this.listenEvent('change', () => {
            this.onCkeditorChange$.next();
        });
    }
    hasTextNodeAsChild(node, reverse = false) {
        const children = node.getChildren().toArray();
        if (reverse) {
            // eslint-disable-next-line no-loops/no-loops
            for (let i = children.length - 1; i >= 0; i--) {
                const child = children[i];
                if (child.type === CKEDITOR.NODE_TEXT) {
                    return child;
                }
                else {
                    const inChild = this.hasTextNodeAsChild(child);
                    if (inChild) {
                        return inChild;
                    }
                }
            }
        }
        else {
            // eslint-disable-next-line no-loops/no-loops
            for (const child of children) {
                if (child.type === CKEDITOR.NODE_TEXT) {
                    return child;
                }
                else {
                    const inChild = this.hasTextNodeAsChild(child);
                    if (inChild) {
                        return inChild;
                    }
                }
            }
        }
        return null;
    }
    mergeTextNodeAroundWithDirection(textNode, reverse = false) {
        const toRemove = [];
        let newText = textNode.getText();
        let x = textNode;
        // eslint-disable-next-line no-loops/no-loops
        while ((x = reverse ? x.getPrevious() : x.getNext)) {
            if (x.type !== CKEDITOR.NODE_TEXT ||
                x
                    .getText()
                    .charAt(reverse ? x.getText().length - 1 : 0)
                    .match(/[\s,;.:!?]/)) {
                break;
            }
            if (reverse) {
                // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
                newText = x.getText() + newText;
            }
            else {
                newText += x.getText();
            }
            toRemove.push(x);
        }
        if (toRemove.length > 0) {
            textNode.setText(newText);
            toRemove.forEach(node => node.remove());
        }
    }
    mergeTextNodeAround(textNode) {
        this.mergeTextNodeAroundWithDirection(textNode, true);
        this.mergeTextNodeAroundWithDirection(textNode);
        return textNode;
    }
    firstNonEmptyTextNode(node, reverse = false) {
        let x = node;
        // eslint-disable-next-line no-loops/no-loops
        while ((x = reverse ? x.getPrevious() : x.getNext())) {
            if (x.type === CKEDITOR.NODE_TEXT) {
                if (x.getText() !== '') {
                    return x;
                }
            }
            else {
                return x;
            }
        }
        return undefined;
    }
    trim(text) {
        if (text) {
            text = text.replace(/[\u200b\u00A0]/g, '').trim();
        }
        return text;
    }
    extractFirstWord(text, reverse = false) {
        if (!text) {
            return text;
        }
        if (text.includes(' ')) {
            const spaceSplit = text.split(' ');
            return this.trim(spaceSplit[reverse ? spaceSplit.length - 1 : 0]);
        }
        else {
            return this.trim(text);
        }
    }
    firstTextNodeResult(selectedNode, reverse = false, firstNodeIsText = false) {
        const text = selectedNode.getText();
        if (this.trim(text) && this.trim(text.substring(text.length - 1))) {
            const node = this.mergeTextNodeAround(selectedNode);
            return {
                textNode: node,
                firstNodeIsText: firstNodeIsText,
                toReplace: this.extractFirstWord(node.getText(), reverse)
            };
        }
        return null;
    }
    firstTextNodeWithDirection(range, reverse = false) {
        const startContainer = range.startContainer;
        if (reverse && startContainer.type === CKEDITOR.NODE_TEXT) {
            return this.firstTextNodeResult(startContainer, reverse, true);
        }
        const startNode = startContainer.type === CKEDITOR.NODE_TEXT ? ((reverse && this.firstNonEmptyTextNode(startContainer, true)) || this.firstNonEmptyTextNode(startContainer)) : startContainer.getChildren().getItem(range.startOffset - 1);
        if (startNode) {
            if (startNode.type === CKEDITOR.NODE_TEXT) {
                return this.firstTextNodeResult(startNode, reverse);
            }
            let x = this.hasTextNodeAsChild(startNode, reverse);
            if (x) {
                return this.firstTextNodeResult(x, reverse);
            }
            x = startNode;
            // eslint-disable-next-line no-loops/no-loops
            while ((x = reverse ? x.getPrevious() : x.getNext())) {
                if (x.type === CKEDITOR.NODE_TEXT) {
                    return this.firstTextNodeResult(x, reverse);
                }
                const textNode = this.hasTextNodeAsChild(x, reverse);
                if (textNode) {
                    return this.firstTextNodeResult(textNode, reverse);
                }
            }
        }
        return null;
    }
    firstTextNode(range) {
        let textNode = this.firstTextNodeWithDirection(range, true);
        if (!textNode) {
            textNode = this.firstTextNodeWithDirection(range);
        }
        return textNode;
    }
    replaceWord(node, replace) {
        const index = node.textNode.getText().lastIndexOf(node.toReplace);
        if (index !== -1) {
            const beforeText = node.textNode.getText().substring(0, index);
            // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
            const afterText = node.textNode.getText().substring(index + node.toReplace.length);
            node.textNode.setText(beforeText);
            // Wrap into a span otherwise methode createFromHtml will only take the html element :
            // For instance if replace is 'abc<br/>def', createFromHtml will create an html text element with abc only
            // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
            const newElement = CKEDITOR.dom.element.createFromHtml(`<span>${CKEDITOR.tools.htmlDecode(CKEDITOR.tools.transformPlainTextToHtml(replace, CKEDITOR.ENTER_BR))}</span>`);
            newElement.insertAfter(node.textNode);
            // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
            if (node.textNode.getText().substring(index + node.toReplace.length)) {
                const end = new CKEDITOR.dom.text(afterText);
                end.insertAfter(newElement);
            }
            this.instance.getSelection().selectElement(node.textNode);
            const tmpRange = this.instance.getSelection().getRanges()[0];
            tmpRange.setStartAfter(node.textNode);
            tmpRange.select();
        }
    }
    updateCkeditorInstanceValue(value) {
        if (this.instance && !this.isDestroyed) {
            this.onDataChangeListener?.removeListener();
            // The data change listener must be removed before setting the data,
            // valueAccessor.onChange is called by the data change listener and must not be subsequently called on writeValue call which fire
            // the data change event by calling instance.setData.
            this.instance.setData(value, {
                callback: () => {
                    this.registerChangeListener();
                }
            });
        }
        else {
            this.host.nativeElement.value = value;
        }
    }
    listenEvent(eventType, callback) {
        this.instance.on(eventType, callback);
        this.registeredListeners.set(eventType, callback);
    }
    cleanListeners() {
        this.registeredListeners.forEach((callback, eventType) => this.instance?.removeListener(eventType, callback));
    }
}
DejaEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorComponent, deps: [{ token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: DejaEditorService }], target: i0.ɵɵFactoryTarget.Component });
DejaEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.1", type: DejaEditorComponent, selector: "deja-editor", inputs: { config: "config", readonly: "readonly", inline: "inline", debounce: "debounce", value: "value" }, outputs: { change: "change", ready: "ready", blur: "blur", focus: "focus", disabled: "disabled" }, providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => DejaEditorComponent),
            multi: true
        }
    ], viewQueries: [{ propertyName: "host", first: true, predicate: ["host"], descendants: true, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<textarea #host (onchange)=\"textAreaChange()\" style=\"visibility: hidden\"></textarea>\n", styles: ["deja-editor{line-height:normal}deja-editor .cke_textarea_inline>p{margin:0}deja-editor .cke_textarea_inline:focus{outline:none}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorComponent, decorators: [{
            type: Component,
            args: [{ selector: 'deja-editor', providers: [
                        {
                            provide: NG_VALUE_ACCESSOR,
                            useExisting: forwardRef(() => DejaEditorComponent),
                            multi: true
                        }
                    ], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, template: "<textarea #host (onchange)=\"textAreaChange()\" style=\"visibility: hidden\"></textarea>\n", styles: ["deja-editor{line-height:normal}deja-editor .cke_textarea_inline>p{margin:0}deja-editor .cke_textarea_inline:focus{outline:none}\n"] }]
        }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: DejaEditorService }]; }, propDecorators: { config: [{
                type: Input
            }], change: [{
                type: Output
            }], ready: [{
                type: Output
            }], blur: [{
                type: Output
            }], focus: [{
                type: Output
            }], disabled: [{
                type: Output
            }], host: [{
                type: ViewChild,
                args: ['host', { static: true }]
            }], readonly: [{
                type: Input
            }], inline: [{
                type: Input
            }], debounce: [{
                type: Input
            }], value: [{
                type: Input
            }] } });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class StringUtils {
    static getLastWord(from, cursorPosition) {
        if (!from) {
            return null;
        }
        if (from.length > cursorPosition) {
            from =
                from.substr(0, cursorPosition) +
                    from.substr(cursorPosition).split(/[\s,;.:]/)[0];
        }
        if (!from) {
            return null;
        }
        // eslint-disable-next-line @typescript-eslint/prefer-regexp-exec
        if (from.match(/[\s,.!?;:]$/)) {
            return null;
        }
        const stringArray = from.split(/[\s,.!?;:]/);
        return stringArray[stringArray.length - 1];
    }
    static insert(from, newValue, cursorStartPosition, cursorEndPosition) {
        if (cursorStartPosition === cursorEndPosition) {
            const result = {
                value: from.substring(0, cursorStartPosition === 0 ? 0 : cursorStartPosition + 1) + newValue,
                newStartPosition: 0,
                newEndPosition: 0
            };
            result.newStartPosition = result.value.length;
            result.newEndPosition = result.value.length;
            return result;
        }
        else {
            const result = {
                value: from.substring(0, cursorStartPosition),
                newStartPosition: 0,
                newEndPosition: 0
            };
            result.newStartPosition = result.value.length;
            result.value += newValue;
            result.newEndPosition = result.value.length;
            result.value = result.value + from.substring(cursorEndPosition);
            return result;
        }
    }
    static replace(from, lastValue, newValue, cursorStartPosition, cursorEndPosition) {
        if (cursorStartPosition === cursorEndPosition) {
            let position = cursorStartPosition;
            // eslint-disable-next-line @typescript-eslint/prefer-regexp-exec
            if (from.charAt(position).match(/[\s,;.:]/)) {
                position--;
            }
            // eslint-disable-next-line no-loops/no-loops, @typescript-eslint/prefer-regexp-exec
            while (!from.charAt(position).match(/[\s,;.:]/) && position > 0) {
                position--;
            }
            const result = {
                value: from.substring(0, position === 0 ? 0 : position + 1) +
                    newValue,
                newStartPosition: 0,
                newEndPosition: 0
            };
            result.newStartPosition = result.value.length;
            result.newEndPosition = result.value.length;
            result.value =
                result.value +
                    from.substring((position === 0 ? 0 : position + 1) +
                        (lastValue ? lastValue.length : 0));
            return result;
        }
        else {
            const result = {
                value: from.substring(0, cursorStartPosition),
                newStartPosition: 0,
                newEndPosition: 0
            };
            result.newStartPosition = result.value.length;
            result.value += newValue;
            result.newEndPosition = result.value.length;
            result.value = result.value + from.substring(cursorEndPosition);
            return result;
        }
    }
    static removeLastWord(from, cursorStartPosition, cursorEndPosition) {
        if (cursorStartPosition === cursorEndPosition) {
            let position = cursorStartPosition;
            // eslint-disable-next-line no-loops/no-loops, @typescript-eslint/prefer-regexp-exec
            while (!from.charAt(position).match(/[\s,;.:]/) && position > 0) {
                position--;
            }
            let endPosition = cursorEndPosition + 1;
            // eslint-disable-next-line no-loops/no-loops, @typescript-eslint/prefer-regexp-exec
            while (!from.charAt(endPosition).match(/[\s,;.:]/) && endPosition < from.length) {
                endPosition++;
            }
            const result = {
                startValue: from.substring(0, position === 0 ? 0 : position + 1),
                endValue: from.substring(endPosition)
            };
            return result;
        }
        else {
            const result = {
                startValue: from.substring(0, cursorStartPosition),
                endValue: from.substring(cursorEndPosition)
            };
            return result;
        }
    }
}

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
/**
 * CKEditorModule
 */
class DejaEditorModule {
}
DejaEditorModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
DejaEditorModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorModule, declarations: [DejaEditorComponent], imports: [CommonModule], exports: [DejaEditorComponent] });
DejaEditorModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorModule, providers: [DejaEditorService], imports: [CommonModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [CommonModule],
                    declarations: [DejaEditorComponent],
                    exports: [DejaEditorComponent],
                    providers: [DejaEditorService]
                }]
        }] });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
let nextUniqueId = 0;
class DejaEditorSelectorDirective extends _MatInputMixinBase {
    constructor(editor, ngControl, parentForm, parentFormGroup, defaultErrorStateMatcher, hostElement) {
        super(defaultErrorStateMatcher, parentForm, parentFormGroup, ngControl);
        this.editor = editor;
        this.ngControl = ngControl;
        this.hostElement = hostElement;
        this.describedBy = '';
        // eslint-disable-next-line rxjs/finnish
        this.stateChanges = new Subject();
        this.controlType = 'app-editor';
        this._disabled = false;
        this._uid = `mat-input-${nextUniqueId++}`;
        this._required = false;
    }
    get id() {
        return this._id;
    }
    set id(value) {
        this._id = value || this._uid;
    }
    get required() {
        return this._required;
    }
    set required(value) {
        this._required = coerceBooleanProperty(value);
    }
    get disabled() {
        if (this.ngControl?.disabled !== null) {
            return this.ngControl.disabled;
        }
        return this._disabled;
    }
    set disabled(value) {
        this._disabled = coerceBooleanProperty(value);
        // Browsers may not fire the blur event if the input is disabled too quickly.
        // Reset from here to ensure that the element doesn't become stuck.
        if (this.focused) {
            this.focused = false;
            this.stateChanges.next();
        }
    }
    onContainerClick() {
        this.editor.setFocus();
    }
    setDescribedByIds(ids) {
        this.describedBy = ids.join(' ');
    }
    ngOnInit() {
        this.editor.focus.subscribe(() => {
            this.focused = true;
            this.stateChanges.next();
        });
        this.editor.blur.subscribe(() => {
            this.focused = false;
            this.stateChanges.next();
        });
        this.editor.change.subscribe(() => {
            this.stateChanges.next();
        });
        this.generatePlaceholder();
    }
    ngDoCheck() {
        if (this.ngControl) {
            this.updateErrorState();
        }
    }
    ngOnDestroy() {
        this.stateChanges.complete();
    }
    get empty() {
        return !this.editor.value;
    }
    get shouldLabelFloat() {
        if (this.focused || !this.empty) {
            if (this.empty) {
                this.attachPlaceholder();
            }
            else {
                this.detachPlaceholder();
            }
            return true;
        }
        else {
            this.detachPlaceholder();
            return false;
        }
    }
    attachPlaceholder() {
        if (this._placeholder && !this._placeholder.parentElement) {
            this.hostElement.nativeElement.appendChild(this._placeholder);
        }
    }
    detachPlaceholder() {
        if (this._placeholder?.parentElement) {
            this._placeholder.remove();
        }
    }
    generatePlaceholder() {
        if (this.placeholder) {
            this._placeholder = document.createElement('div');
            this._placeholder.style.position = 'absolute';
            this._placeholder.style.position = 'absolute';
            this._placeholder.style.left = '0';
            this._placeholder.style.boxSizing = 'content-box';
            this._placeholder.style.width = '100%';
            this._placeholder.style.height = '100%';
            this._placeholder.style.overflow = 'hidden';
            this._placeholder.style.pointerEvents = 'none';
            this._placeholder.style.top = '-0.84375em';
            this._placeholder.style.paddingTop = '0.84375em';
            const placeholderChildren = document.createElement('div');
            placeholderChildren.style.color = 'rgba(0,0,0,0.54)';
            placeholderChildren.style.top = '1.28125em';
            placeholderChildren.style.position = 'absolute';
            const placeholderText = document.createTextNode(this.placeholder);
            placeholderChildren.appendChild(placeholderText);
            this._placeholder.appendChild(placeholderChildren);
        }
    }
}
DejaEditorSelectorDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorSelectorDirective, deps: [{ token: DejaEditorComponent, self: true }, { token: i2.NgControl, optional: true, self: true }, { token: i2.NgForm, optional: true }, { token: i2.FormGroupDirective, optional: true }, { token: i3.ErrorStateMatcher }, { token: i0.ElementRef, host: true }], target: i0.ɵɵFactoryTarget.Directive });
DejaEditorSelectorDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.1.1", type: DejaEditorSelectorDirective, selector: "deja-editor", inputs: { placeholder: "placeholder", id: "id", required: "required", disabled: "disabled" }, host: { properties: { "attr.aria-describedby": "this.describedBy" } }, providers: [
        {
            provide: MatFormFieldControl,
            useExisting: DejaEditorSelectorDirective
        }
    ], usesInheritance: true, ngImport: i0 });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaEditorSelectorDirective, decorators: [{
            type: Directive,
            args: [{
                    selector: 'deja-editor',
                    providers: [
                        {
                            provide: MatFormFieldControl,
                            useExisting: DejaEditorSelectorDirective
                        }
                    ]
                }]
        }], ctorParameters: function () { return [{ type: DejaEditorComponent, decorators: [{
                    type: Self
                }] }, { type: i2.NgControl, decorators: [{
                    type: Optional
                }, {
                    type: Self
                }] }, { type: i2.NgForm, decorators: [{
                    type: Optional
                }] }, { type: i2.FormGroupDirective, decorators: [{
                    type: Optional
                }] }, { type: i3.ErrorStateMatcher }, { type: i0.ElementRef, decorators: [{
                    type: Host
                }] }]; }, propDecorators: { placeholder: [{
                type: Input
            }], describedBy: [{
                type: HostBinding,
                args: ['attr.aria-describedby']
            }], id: [{
                type: Input
            }], required: [{
                type: Input
            }], disabled: [{
                type: Input
            }] } });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */
class DejaMatEditorModule {
}
DejaMatEditorModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaMatEditorModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
DejaMatEditorModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.1.1", ngImport: i0, type: DejaMatEditorModule, declarations: [DejaEditorSelectorDirective], imports: [DejaEditorModule, MatFormFieldModule], exports: [DejaEditorComponent, DejaEditorSelectorDirective] });
DejaMatEditorModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaMatEditorModule, imports: [DejaEditorModule, MatFormFieldModule] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.1", ngImport: i0, type: DejaMatEditorModule, decorators: [{
            type: NgModule,
            args: [{
                    imports: [DejaEditorModule, MatFormFieldModule],
                    declarations: [DejaEditorSelectorDirective],
                    exports: [DejaEditorComponent, DejaEditorSelectorDirective]
                }]
        }] });

/*
 *  @license
 *  Copyright Hôpitaux Universitaires de Genève. All Rights Reserved.
 *
 *  Use of this source code is governed by an Apache-2.0 license that can be
 *  found in the LICENSE file at https://github.com/DSI-HUG/dejajs-components/blob/master/LICENSE
 */

/**
 * Generated bundle index. Do not edit.
 */

export { DejaEditorComponent, DejaEditorModule, DejaEditorSelectorDirective, DejaMatEditorModule, StringUtils };
//# sourceMappingURL=deja-js-component-editor.mjs.map
