import { CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { model, input, booleanAttribute, output, viewChild, signal, effect, afterNextRender, computed, ChangeDetectionStrategy, Component } from '@angular/core';
import * as i1 from '@angular/forms';
import { ReactiveFormsModule } from '@angular/forms';
import * as i2 from '@angular/material/icon';
import { MatIconModule } from '@angular/material/icon';

/**
 * Borderless, content-hugging text input — the seamless primitive shared by
 * `sd-input` / `sd-input-number` (`viewed='inline'`) and the query-bar / query-builder chips.
 *
 * why: a native `<input>` inside `mat-form-field` cannot hug its content, so inline-edit
 * looked like a full-width input rather than text. This primitive renders a raw `<input>`
 * sized via the native `size` attribute (clamped) so the click/hover target tracks the value.
 *
 * It is intentionally unopinionated about commit/parse/format: it forwards the raw DOM events
 * (focus / blur / keydown / paste / composition / Enter / Escape) so each consumer keeps its own
 * logic (e.g. sd-input-number's vi-VN formatting). Two binding modes:
 *  - **uncontrolled** via `[(value)]` — used by the chips' signal drafts;
 *  - **controlled** via `[control]` (an external `SdFormControl`) — used by the form controls.
 */
class SdInlineText {
    /** Uncontrolled value (two-way). Ignored when `[control]` is provided. */
    value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
    /** Optional external FormControl (controlled mode) — used by sd-input / sd-input-number. */
    control = input(undefined, ...(ngDevMode ? [{ debugName: "control" }] : []));
    placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
    disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
    /** Show a hover/value-gated clear-× (default `true`). */
    clearable = input(true, ...(ngDevMode ? [{ debugName: "clearable", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
    /** `'auto'` derives state from focus + value; pass an explicit value (e.g. `'error'`) to override. */
    state = input('auto', ...(ngDevMode ? [{ debugName: "state" }] : []));
    chrome = input('standalone', ...(ngDevMode ? [{ debugName: "chrome" }] : []));
    autoId = input(undefined, ...(ngDevMode ? [{ debugName: "autoId" }] : []));
    autofocus = input(false, ...(ngDevMode ? [{ debugName: "autofocus", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
    /** Lower bound (chars) so short/empty values keep a clickable target. */
    minSize = input(2, ...(ngDevMode ? [{ debugName: "minSize" }] : []));
    cleared = output();
    keyupEnter = output();
    keydownEscape = output();
    sdFocus = output();
    sdBlur = output();
    sdKeydown = output();
    sdPaste = output();
    sdCompositionStart = output();
    sdCompositionEnd = output();
    inputRef = viewChild('inputEl', ...(ngDevMode ? [{ debugName: "inputRef" }] : []));
    /** Bumped on input/blur/composition + bound-control changes so size/state methods re-eval under OnPush. */
    tick = signal(0, ...(ngDevMode ? [{ debugName: "tick" }] : []));
    focused = signal(false, ...(ngDevMode ? [{ debugName: "focused" }] : []));
    constructor() {
        // why: a bound control's value can change programmatically (sd-input-number reformats
        // on blur) without a DOM input event — subscribe so the size/state still refresh.
        effect(onCleanup => {
            const c = this.control();
            if (!c)
                return;
            const sub = c.valueChanges.subscribe(() => this.tick.update(n => n + 1));
            onCleanup(() => sub.unsubscribe());
        });
        afterNextRender(() => {
            if (this.autofocus())
                this.focus();
        });
    }
    /**
     * Current text — from the bound control in controlled mode, else the value model.
     * why: `tick` is a tracked dependency so the computed re-runs when a bound control's
     * value changes programmatically (control.value itself is not a signal).
     */
    currentText = computed(() => {
        this.tick();
        const c = this.control();
        const raw = c ? c.value : this.value();
        return raw == null ? '' : String(raw);
    }, ...(ngDevMode ? [{ debugName: "currentText" }] : []));
    hasValue = computed(() => this.currentText().length > 0, ...(ngDevMode ? [{ debugName: "hasValue" }] : []));
    sizeOf = computed(() => {
        const text = this.currentText();
        const base = text.length > 0 ? text.length : this.placeholder().length;
        return Math.max(this.minSize(), base);
    }, ...(ngDevMode ? [{ debugName: "sizeOf" }] : []));
    showClear = computed(() => this.clearable() && this.hasValue() && !this.disabled(), ...(ngDevMode ? [{ debugName: "showClear" }] : []));
    effectiveState = computed(() => {
        const s = this.state();
        if (s !== 'auto')
            return s;
        if (this.focused())
            return 'focus';
        return this.hasValue() ? 'active' : 'pending';
    }, ...(ngDevMode ? [{ debugName: "effectiveState" }] : []));
    // ── event handlers ─────────────────────────────────────────────────────────
    onInput(ev) {
        const el = ev.target;
        // why: only the uncontrolled mode owns the value model; in controlled mode the bound
        // FormControl carries the value natively (ReactiveForms), so we must not double-write.
        if (!this.control())
            this.value.set(el.value);
        this.tick.update(n => n + 1);
    }
    onFocus(ev) {
        this.focused.set(true);
        this.sdFocus.emit(ev);
    }
    onBlur(ev) {
        this.focused.set(false);
        this.tick.update(n => n + 1);
        this.sdBlur.emit(ev);
    }
    onKeyup(ev) {
        if (ev.key === 'Enter')
            this.keyupEnter.emit();
    }
    onKeydown(ev) {
        if (ev.key === 'Escape')
            this.keydownEscape.emit();
        this.sdKeydown.emit(ev);
    }
    onPaste(ev) {
        this.sdPaste.emit(ev);
    }
    onCompositionStart(ev) {
        this.sdCompositionStart.emit(ev);
    }
    onCompositionEnd(ev) {
        this.tick.update(n => n + 1);
        this.sdCompositionEnd.emit(ev);
    }
    clear(ev) {
        ev.stopPropagation();
        const c = this.control();
        if (c)
            c.setValue('');
        else
            this.value.set('');
        this.tick.update(n => n + 1);
        this.cleared.emit();
    }
    // ── public API ───────────────────────────────────────────────────────────
    /** Focus the native input. */
    focus() {
        this.inputRef()?.nativeElement.focus();
    }
    /** Blur the native input. */
    blur() {
        this.inputRef()?.nativeElement.blur();
    }
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: SdInlineText, deps: [], target: i0.ɵɵFactoryTarget.Component });
    static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.24", type: SdInlineText, isStandalone: true, selector: "sd-inline-text", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, state: { classPropertyName: "state", publicName: "state", isSignal: true, isRequired: false, transformFunction: null }, chrome: { classPropertyName: "chrome", publicName: "chrome", isSignal: true, isRequired: false, transformFunction: null }, autoId: { classPropertyName: "autoId", publicName: "autoId", isSignal: true, isRequired: false, transformFunction: null }, autofocus: { classPropertyName: "autofocus", publicName: "autofocus", isSignal: true, isRequired: false, transformFunction: null }, minSize: { classPropertyName: "minSize", publicName: "minSize", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", cleared: "cleared", keyupEnter: "keyupEnter", keydownEscape: "keydownEscape", sdFocus: "sdFocus", sdBlur: "sdBlur", sdKeydown: "sdKeydown", sdPaste: "sdPaste", sdCompositionStart: "sdCompositionStart", sdCompositionEnd: "sdCompositionEnd" }, host: { properties: { "class.sd-inline-text--standalone": "chrome() === 'standalone'", "class.sd-inline-text--seamless": "chrome() === 'seamless'", "attr.data-state": "effectiveState()" }, classAttribute: "sd-inline-text" }, viewQueries: [{ propertyName: "inputRef", first: true, predicate: ["inputEl"], descendants: true, isSignal: true }], ngImport: i0, template: "@let _autoId = autoId();\n@let _placeholder = placeholder();\n@let _size = sizeOf();\n@let _control = control();\n\n@if (_control) {\n  <input\n    #inputEl\n    class=\"sd-inline-text__input\"\n    type=\"text\"\n    [formControl]=\"_control\"\n    [placeholder]=\"_placeholder\"\n    [size]=\"_size\"\n    [attr.data-autoId]=\"_autoId\"\n    (input)=\"onInput($event)\"\n    (focus)=\"onFocus($event)\"\n    (blur)=\"onBlur($event)\"\n    (keyup)=\"onKeyup($event)\"\n    (keydown)=\"onKeydown($event)\"\n    (paste)=\"onPaste($event)\"\n    (compositionstart)=\"onCompositionStart($event)\"\n    (compositionend)=\"onCompositionEnd($event)\" />\n} @else {\n  <input\n    #inputEl\n    class=\"sd-inline-text__input\"\n    type=\"text\"\n    [value]=\"currentText()\"\n    [disabled]=\"disabled()\"\n    [placeholder]=\"_placeholder\"\n    [size]=\"_size\"\n    [attr.data-autoId]=\"_autoId\"\n    (input)=\"onInput($event)\"\n    (focus)=\"onFocus($event)\"\n    (blur)=\"onBlur($event)\"\n    (keyup)=\"onKeyup($event)\"\n    (keydown)=\"onKeydown($event)\"\n    (paste)=\"onPaste($event)\"\n    (compositionstart)=\"onCompositionStart($event)\"\n    (compositionend)=\"onCompositionEnd($event)\" />\n}\n\n@if (showClear()) {\n  <button type=\"button\" class=\"sd-inline-text__clear\" (click)=\"clear($event)\" aria-label=\"Clear\" tabindex=\"-1\">\n    <mat-icon>close</mat-icon>\n  </button>\n}\n", styles: [":host{display:inline-flex;align-items:center;max-width:100%;font:inherit;color:inherit}.sd-inline-text__input{appearance:none;border:0;outline:0;background:transparent;font:inherit;color:inherit;padding:0;min-width:0;max-width:240px}:host(.sd-inline-text--standalone){border-radius:4px;padding:1px 6px;background-color:#0000000a;transition:background-color .15s ease,box-shadow .15s ease}:host(.sd-inline-text--standalone):hover{background-color:#00000014}:host(.sd-inline-text--standalone)[data-state=focus]{background-color:#0000000f;box-shadow:inset 0 0 0 1px var(--sd-primary, #1f6feb)}:host(.sd-inline-text--standalone)[data-state=error]{box-shadow:inset 0 0 0 1px var(--sd-error, #b32626)}:host(.sd-inline-text--standalone) .sd-inline-text__clear{display:none}:host(.sd-inline-text--standalone):hover .sd-inline-text__clear,:host(.sd-inline-text--standalone)[data-state=focus] .sd-inline-text__clear{display:inline-flex}:host(.sd-inline-text--seamless) .sd-inline-text__input{font-weight:500}:host(.sd-inline-text--seamless) .sd-inline-text__input::placeholder{font-style:italic}:host(.sd-inline-text--seamless)[data-state=active] .sd-inline-text__input{color:var(--sd-primary, #1f6feb)}:host(.sd-inline-text--seamless)[data-state=error] .sd-inline-text__input{color:var(--sd-error, #b32626)}.sd-inline-text__clear{display:inline-flex;align-items:center;margin-left:4px;padding:0;border:0;background:transparent;cursor:pointer;line-height:0;color:var(--sd-text-secondary, #6b7280);transition:color .15s ease}.sd-inline-text__clear mat-icon{font-size:16px;width:16px;height:16px}.sd-inline-text__clear:hover{color:var(--sd-error, #b32626)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: SdInlineText, decorators: [{
            type: Component,
            args: [{ selector: 'sd-inline-text', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, ReactiveFormsModule, MatIconModule], host: {
                        class: 'sd-inline-text',
                        '[class.sd-inline-text--standalone]': "chrome() === 'standalone'",
                        '[class.sd-inline-text--seamless]': "chrome() === 'seamless'",
                        '[attr.data-state]': 'effectiveState()',
                    }, template: "@let _autoId = autoId();\n@let _placeholder = placeholder();\n@let _size = sizeOf();\n@let _control = control();\n\n@if (_control) {\n  <input\n    #inputEl\n    class=\"sd-inline-text__input\"\n    type=\"text\"\n    [formControl]=\"_control\"\n    [placeholder]=\"_placeholder\"\n    [size]=\"_size\"\n    [attr.data-autoId]=\"_autoId\"\n    (input)=\"onInput($event)\"\n    (focus)=\"onFocus($event)\"\n    (blur)=\"onBlur($event)\"\n    (keyup)=\"onKeyup($event)\"\n    (keydown)=\"onKeydown($event)\"\n    (paste)=\"onPaste($event)\"\n    (compositionstart)=\"onCompositionStart($event)\"\n    (compositionend)=\"onCompositionEnd($event)\" />\n} @else {\n  <input\n    #inputEl\n    class=\"sd-inline-text__input\"\n    type=\"text\"\n    [value]=\"currentText()\"\n    [disabled]=\"disabled()\"\n    [placeholder]=\"_placeholder\"\n    [size]=\"_size\"\n    [attr.data-autoId]=\"_autoId\"\n    (input)=\"onInput($event)\"\n    (focus)=\"onFocus($event)\"\n    (blur)=\"onBlur($event)\"\n    (keyup)=\"onKeyup($event)\"\n    (keydown)=\"onKeydown($event)\"\n    (paste)=\"onPaste($event)\"\n    (compositionstart)=\"onCompositionStart($event)\"\n    (compositionend)=\"onCompositionEnd($event)\" />\n}\n\n@if (showClear()) {\n  <button type=\"button\" class=\"sd-inline-text__clear\" (click)=\"clear($event)\" aria-label=\"Clear\" tabindex=\"-1\">\n    <mat-icon>close</mat-icon>\n  </button>\n}\n", styles: [":host{display:inline-flex;align-items:center;max-width:100%;font:inherit;color:inherit}.sd-inline-text__input{appearance:none;border:0;outline:0;background:transparent;font:inherit;color:inherit;padding:0;min-width:0;max-width:240px}:host(.sd-inline-text--standalone){border-radius:4px;padding:1px 6px;background-color:#0000000a;transition:background-color .15s ease,box-shadow .15s ease}:host(.sd-inline-text--standalone):hover{background-color:#00000014}:host(.sd-inline-text--standalone)[data-state=focus]{background-color:#0000000f;box-shadow:inset 0 0 0 1px var(--sd-primary, #1f6feb)}:host(.sd-inline-text--standalone)[data-state=error]{box-shadow:inset 0 0 0 1px var(--sd-error, #b32626)}:host(.sd-inline-text--standalone) .sd-inline-text__clear{display:none}:host(.sd-inline-text--standalone):hover .sd-inline-text__clear,:host(.sd-inline-text--standalone)[data-state=focus] .sd-inline-text__clear{display:inline-flex}:host(.sd-inline-text--seamless) .sd-inline-text__input{font-weight:500}:host(.sd-inline-text--seamless) .sd-inline-text__input::placeholder{font-style:italic}:host(.sd-inline-text--seamless)[data-state=active] .sd-inline-text__input{color:var(--sd-primary, #1f6feb)}:host(.sd-inline-text--seamless)[data-state=error] .sd-inline-text__input{color:var(--sd-error, #b32626)}.sd-inline-text__clear{display:inline-flex;align-items:center;margin-left:4px;padding:0;border:0;background:transparent;cursor:pointer;line-height:0;color:var(--sd-text-secondary, #6b7280);transition:color .15s ease}.sd-inline-text__clear mat-icon{font-size:16px;width:16px;height:16px}.sd-inline-text__clear:hover{color:var(--sd-error, #b32626)}\n"] }]
        }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], state: [{ type: i0.Input, args: [{ isSignal: true, alias: "state", required: false }] }], chrome: [{ type: i0.Input, args: [{ isSignal: true, alias: "chrome", required: false }] }], autoId: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoId", required: false }] }], autofocus: [{ type: i0.Input, args: [{ isSignal: true, alias: "autofocus", required: false }] }], minSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSize", required: false }] }], cleared: [{ type: i0.Output, args: ["cleared"] }], keyupEnter: [{ type: i0.Output, args: ["keyupEnter"] }], keydownEscape: [{ type: i0.Output, args: ["keydownEscape"] }], sdFocus: [{ type: i0.Output, args: ["sdFocus"] }], sdBlur: [{ type: i0.Output, args: ["sdBlur"] }], sdKeydown: [{ type: i0.Output, args: ["sdKeydown"] }], sdPaste: [{ type: i0.Output, args: ["sdPaste"] }], sdCompositionStart: [{ type: i0.Output, args: ["sdCompositionStart"] }], sdCompositionEnd: [{ type: i0.Output, args: ["sdCompositionEnd"] }], inputRef: [{ type: i0.ViewChild, args: ['inputEl', { isSignal: true }] }] } });

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

export { SdInlineText };
//# sourceMappingURL=sdcorejs-angular-forms-inline-text.mjs.map
