import { __decorate } from "tslib";
import { DesignSystem, FoundationElement } from '@ni/fast-foundation';
import { keyEnter } from '@ni/fast-web-utilities';
import { attr, nullableNumberConverter, observable, DOM } from '@ni/fast-element';
import { mixinErrorPattern } from '@ni/nimble-components/dist/esm/patterns/error/types';
import { styles } from './styles';
import { template } from './template';
/**
 * A Spright component for composing and sending a chat message
 */
export class ChatInput extends mixinErrorPattern(FoundationElement) {
    constructor() {
        super(...arguments);
        this.value = '';
        this.maxLength = -1;
        this.processing = false;
        this.sendDisabled = false;
        /**
         * Tracks whether the send button should be disabled based on input value
         * @internal
         */
        this.isInputEmpty = true;
        /**
         * The width of the vertical scrollbar, if displayed.
         * @internal
         */
        this.scrollbarWidth = -1;
        /** @internal */
        this.footerActionsIsEmpty = true;
        /** @internal */
        this.attachmentsIsEmpty = true;
        this.updateScrollbarWidthQueued = false;
    }
    slottedFooterActionsElementsChanged(_prev, next) {
        this.footerActionsIsEmpty = next === undefined || next.length === 0;
    }
    slottedAttachmentsElementsChanged(_prev, next) {
        this.attachmentsIsEmpty = next === undefined || next.length === 0;
    }
    /**
     * @internal
     */
    textAreaKeydownHandler(e) {
        if (e.key === keyEnter && !e.shiftKey) {
            if (this.processing) {
                return false;
            }
            this.sendButtonClickHandler();
            return false;
        }
        return true;
    }
    /**
     * @internal
     */
    textAreaInputHandler() {
        this.value = this.textArea.value;
        this.isInputEmpty = this.shouldDisableSendButton();
        this.adjustTextAreaHeight();
        this.queueUpdateScrollbarWidth();
    }
    // If a property can affect whether a scrollbar is visible, we need to
    // call queueUpdateScrollbarWidth() when it changes. The exceptions are
    // properties that affect size (e.g. height, width, cols, rows), because
    // we already have a ResizeObserver handling those changes. Also,
    // a change to errorVisible cannot cause scrollbar visibility to change,
    // because we always reserve space for the error icon.
    /**
     * @internal
     */
    placeholderChanged() {
        this.queueUpdateScrollbarWidth();
    }
    /**
     * @internal
     */
    valueChanged() {
        if (this.textArea) {
            this.textArea.value = this.value;
            this.isInputEmpty = this.shouldDisableSendButton();
            this.adjustTextAreaHeight();
            this.queueUpdateScrollbarWidth();
        }
    }
    /**
     * @internal
     */
    connectedCallback() {
        super.connectedCallback();
        this.textArea.value = this.value;
        this.isInputEmpty = this.shouldDisableSendButton();
        this.adjustTextAreaHeight();
        this.resizeObserver = new ResizeObserver(() => this.onResize());
        this.resizeObserver.observe(this);
    }
    /**
     * @internal
     */
    disconnectedCallback() {
        super.disconnectedCallback();
        this.resizeObserver?.disconnect();
    }
    /**
     * @internal
     */
    sendButtonClickHandler() {
        if (this.shouldDisableSendButton()) {
            return;
        }
        const eventDetail = {
            text: this.textArea.value
        };
        this.resetInput();
        this.$emit('send', eventDetail);
    }
    /**
     * @internal
     */
    stopButtonClickHandler() {
        if (!this.processing) {
            return;
        }
        this.$emit('stop');
        this.textArea?.blur();
    }
    shouldDisableSendButton() {
        return this.textArea.value.length === 0;
    }
    resetInput() {
        this.value = '';
        this.isInputEmpty = true;
        if (this.textArea) {
            this.textArea.value = '';
            this.adjustTextAreaHeight();
            this.textArea.focus();
        }
    }
    onResize() {
        this.adjustTextAreaHeight();
        this.scrollbarWidth = this.textArea.offsetWidth - this.textArea.clientWidth;
    }
    queueUpdateScrollbarWidth() {
        if (!this.$fastController.isConnected) {
            return;
        }
        if (!this.updateScrollbarWidthQueued) {
            this.updateScrollbarWidthQueued = true;
            DOM.queueUpdate(() => this.updateScrollbarWidth());
        }
    }
    // Workaround for browsers that do not support the CSS property `field-sizing: content`
    // See https://github.com/ni/nimble/issues/2902
    adjustTextAreaHeight() {
        if (ChatInput.fieldSizingSupported || !this.textArea) {
            return;
        }
        const textArea = this.textArea;
        textArea.style.height = 'auto';
        textArea.style.height = `${textArea.scrollHeight}px`;
    }
    updateScrollbarWidth() {
        this.updateScrollbarWidthQueued = false;
        this.scrollbarWidth = this.textArea.offsetWidth - this.textArea.clientWidth;
    }
}
ChatInput.fieldSizingSupported = CSS.supports('field-sizing', 'content');
__decorate([
    attr
], ChatInput.prototype, "placeholder", void 0);
__decorate([
    attr({ attribute: 'send-button-label' })
], ChatInput.prototype, "sendButtonLabel", void 0);
__decorate([
    attr({ attribute: 'stop-button-label' })
], ChatInput.prototype, "stopButtonLabel", void 0);
__decorate([
    attr
], ChatInput.prototype, "value", void 0);
__decorate([
    attr({ attribute: 'tabindex', converter: nullableNumberConverter })
], ChatInput.prototype, "tabIndex", void 0);
__decorate([
    attr({ attribute: 'maxlength', converter: nullableNumberConverter })
], ChatInput.prototype, "maxLength", void 0);
__decorate([
    attr({ attribute: 'processing', mode: 'boolean' })
], ChatInput.prototype, "processing", void 0);
__decorate([
    attr({ attribute: 'send-disabled', mode: 'boolean' })
], ChatInput.prototype, "sendDisabled", void 0);
__decorate([
    observable
], ChatInput.prototype, "textArea", void 0);
__decorate([
    observable
], ChatInput.prototype, "isInputEmpty", void 0);
__decorate([
    observable
], ChatInput.prototype, "scrollbarWidth", void 0);
__decorate([
    observable
], ChatInput.prototype, "footerActionsIsEmpty", void 0);
__decorate([
    observable
], ChatInput.prototype, "slottedFooterActionsElements", void 0);
__decorate([
    observable
], ChatInput.prototype, "attachmentsIsEmpty", void 0);
__decorate([
    observable
], ChatInput.prototype, "slottedAttachmentsElements", void 0);
const sprightChatInput = ChatInput.compose({
    baseName: 'chat-input',
    template,
    styles,
    shadowOptions: {
        delegatesFocus: true
    }
});
DesignSystem.getOrCreate().withPrefix('spright').register(sprightChatInput());
export const chatInputTag = 'spright-chat-input';
//# sourceMappingURL=index.js.map