{"version":3,"file":"ng-forge-dynamic-forms-bootstrap-lazy-input.mjs","mappings":";;;;;;;;;AA6Oc;;;;AAMH;;AAET,IAKS;;IAGQ;AAER;;AACA;;IAGU;;;AAtBA;AApFjB;AACE;AACA;AACD;AACD;gFAME;;AAEE;AACA;AACA;oBAEA;;AAEE;AACE;AACA;;;;;;AAOC;;;;AAIR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AApKO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqIR;AACE;AACA;AACD;AACD;4IAME;;AAEE;AACA;AACA;;;AAIE;AACE;AACA;;;;;;AAOC;;;;AAIR;AACF","names":[],"ignoreList":[],"sources":["../../../../packages/dynamic-forms-bootstrap/src/lib/fields/input/bs-input.component.ts"],"sourcesContent":["import { AsyncPipe } from '@angular/common';\nimport { ChangeDetectionStrategy, Component, computed, forwardRef, inject, input, signal } from '@angular/core';\nimport { FormField } from '@angular/forms/signals';\nimport { AddonActionContext, AddonActionPreset, DynamicFormLogger } from '@ng-forge/dynamic-forms';\nimport { DfAddonSlot } from '@ng-forge/dynamic-forms/integration';\nimport { WrapperFieldInputs } from '@ng-forge/dynamic-forms/integration';\nimport { DynamicTextPipe, FIELD_SIGNAL_CONTEXT } from '@ng-forge/dynamic-forms/integration';\nimport {\n  ADDON_PRESET_HANDLER,\n  AddonPresetHandler,\n  injectNgForgeAddons,\n  injectNgForgeField,\n  NgForgeAddons,\n  NgForgeControl,\n  NgForgeFieldHost,\n} from '@ng-forge/dynamic-forms/integration';\nimport { BOOTSTRAP_CONFIG, BS_INPUT_TYPE_OVERRIDE, runBsPresetAction } from '@ng-forge/dynamic-forms-bootstrap/shared';\nimport { BsInputAddon, BsInputProps } from './bs-input.type';\n\n@Component({\n  selector: 'df-bs-input',\n  imports: [FormField, DynamicTextPipe, AsyncPipe, NgForgeControl, DfAddonSlot],\n  styleUrl: '../../styles/_form-field.scss',\n  hostDirectives: [NgForgeFieldHost, NgForgeAddons],\n  template: `\n    @let f = ngf.field(); @let p = props(); @let inputId = ngf.key() + '-input';\n    @if (floatingLabel()) {\n      <div class=\"mb-3\">\n        @if (ngfa.hasAddons()) {\n          <div class=\"input-group\">\n            @for (a of ngfa.prefixAddons(); track $index) {\n              <span class=\"input-group-text\">\n                <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n              </span>\n            }\n            <div class=\"form-floating\">\n              <input\n                ngForgeControl\n                [formField]=\"f\"\n                [id]=\"inputId\"\n                [type]=\"type()\"\n                [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n                [attr.tabindex]=\"ngf.tabIndex()\"\n                class=\"form-control\"\n                [class.form-control-sm]=\"size() === 'sm'\"\n                [class.form-control-lg]=\"size() === 'lg'\"\n                [class.form-control-plaintext]=\"p?.plaintext\"\n                [class.is-invalid]=\"f().invalid() && f().touched()\"\n                [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n              />\n              @if (ngf.label()) {\n                <label [for]=\"inputId\">{{ ngf.label() | dynamicText | async }}</label>\n              }\n            </div>\n            @for (a of ngfa.suffixAddons(); track $index) {\n              <span class=\"input-group-text\">\n                <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n              </span>\n            }\n          </div>\n        } @else {\n          <div class=\"form-floating\">\n            <input\n              ngForgeControl\n              [formField]=\"f\"\n              [id]=\"inputId\"\n              [type]=\"type()\"\n              [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n              [attr.tabindex]=\"ngf.tabIndex()\"\n              class=\"form-control\"\n              [class.form-control-sm]=\"size() === 'sm'\"\n              [class.form-control-lg]=\"size() === 'lg'\"\n              [class.form-control-plaintext]=\"p?.plaintext\"\n              [class.is-invalid]=\"f().invalid() && f().touched()\"\n              [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n            />\n            @if (ngf.label()) {\n              <label [for]=\"inputId\">{{ ngf.label() | dynamicText | async }}</label>\n            }\n          </div>\n        }\n        @if (p?.validFeedback && f().valid() && f().touched()) {\n          <div class=\"valid-feedback d-block\">\n            {{ p?.validFeedback | dynamicText | async }}\n          </div>\n        }\n        @if (ngf.errorsToDisplay()[0]; as error) {\n          <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n        }\n      </div>\n    } @else {\n      <div class=\"mb-3\">\n        @if (ngf.label()) {\n          <label [for]=\"inputId\" class=\"form-label\">{{ ngf.label() | dynamicText | async }}</label>\n        }\n        @if (ngfa.hasAddons()) {\n          <div class=\"input-group\">\n            @for (a of ngfa.prefixAddons(); track $index) {\n              <span class=\"input-group-text\">\n                <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n              </span>\n            }\n            <input\n              ngForgeControl\n              [formField]=\"f\"\n              [id]=\"inputId\"\n              [type]=\"type()\"\n              [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n              [attr.tabindex]=\"ngf.tabIndex()\"\n              class=\"form-control\"\n              [class.form-control-sm]=\"size() === 'sm'\"\n              [class.form-control-lg]=\"size() === 'lg'\"\n              [class.form-control-plaintext]=\"p?.plaintext\"\n              [class.is-invalid]=\"f().invalid() && f().touched()\"\n              [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n            />\n            @for (a of ngfa.suffixAddons(); track $index) {\n              <span class=\"input-group-text\">\n                <df-addon-slot [addon]=\"a\" [fieldInputs]=\"fieldInputs()\" [hidden]=\"ngfa.hiddenSignalCache().get(a)\" />\n              </span>\n            }\n          </div>\n        } @else {\n          <input\n            ngForgeControl\n            [formField]=\"f\"\n            [id]=\"inputId\"\n            [type]=\"type()\"\n            [placeholder]=\"(ngf.placeholder() | dynamicText | async) ?? ''\"\n            [attr.tabindex]=\"ngf.tabIndex()\"\n            class=\"form-control\"\n            [class.form-control-sm]=\"size() === 'sm'\"\n            [class.form-control-lg]=\"size() === 'lg'\"\n            [class.form-control-plaintext]=\"p?.plaintext\"\n            [class.is-invalid]=\"f().invalid() && f().touched()\"\n            [class.is-valid]=\"f().valid() && f().touched() && p?.validFeedback\"\n          />\n        }\n        @if (p?.validFeedback && f().valid() && f().touched()) {\n          <div class=\"valid-feedback d-block\">\n            {{ p?.validFeedback | dynamicText | async }}\n          </div>\n        }\n        @if (ngf.errorsToDisplay()[0]; as error) {\n          <div class=\"invalid-feedback d-block\" [id]=\"ngf.errorId()\" role=\"alert\">{{ error.message }}</div>\n        } @else if (p?.hint) {\n          <div class=\"form-text\" [id]=\"ngf.hintId()\">{{ p?.hint | dynamicText | async }}</div>\n        }\n      </div>\n    }\n  `,\n  changeDetection: ChangeDetectionStrategy.OnPush,\n  providers: [\n    {\n      provide: BS_INPUT_TYPE_OVERRIDE,\n      useFactory: () => signal<string | undefined>(undefined),\n    },\n    {\n      // Adapter-specific preset semantics for `bs-button` addons (clear /\n      // reset / paste / copy / toggle-password-visibility). The directive\n      // (`NgForgeAddonAction`) delegates here when an addon configures a\n      // `preset`. Per-bs-input-instance so the `typeOverride` signal is\n      // scoped to one field.\n      provide: ADDON_PRESET_HANDLER,\n      useFactory: (): AddonPresetHandler => {\n        const typeOverride = inject(BS_INPUT_TYPE_OVERRIDE);\n        const fsc = inject(FIELD_SIGNAL_CONTEXT, { optional: true });\n        const logger = inject(DynamicFormLogger);\n        // forwardRef for baselineType only — host.props()?.type gates toggle-password-visibility.\n        const host = inject(forwardRef(() => BsInputFieldComponent));\n        return {\n          run: (preset: string, ctx: AddonActionContext) => {\n            const fieldKey = ctx.field.key;\n            return runBsPresetAction(preset as AddonActionPreset, ctx, {\n              typeOverride,\n              fieldValueSetter: ctx.setValue,\n              fieldDefaultValueGetter:\n                fsc && fieldKey ? () => (fsc.defaultValues() as Record<string, unknown> | undefined)?.[fieldKey] : undefined,\n              baselineType: () => host.props()?.type,\n              logger,\n            });\n          },\n        };\n      },\n    },\n  ],\n  styles: [\n    `\n      :host([hidden]) {\n        display: none !important;\n      }\n      /* Per-side padding on the .input-group-text addon containers — each\n         side is its own knob so consumers can tune the prefix's gap from\n         the border (outer-left), the prefix's gap to the input text\n         (inner-right), and the symmetric suffix counterparts independently. */\n      :host {\n        --df-bs-addon-prefix-outer-padding: 0.75rem;\n        --df-bs-addon-prefix-inner-padding: 0.75rem;\n        --df-bs-addon-suffix-inner-padding: 0.75rem;\n        --df-bs-addon-suffix-outer-padding: 0.75rem;\n      }\n      :host ::ng-deep .input-group > .input-group-text:first-child {\n        padding-left: var(--df-bs-addon-prefix-outer-padding);\n        padding-right: var(--df-bs-addon-prefix-inner-padding);\n      }\n      :host ::ng-deep .input-group > .input-group-text:last-child {\n        padding-left: var(--df-bs-addon-suffix-inner-padding);\n        padding-right: var(--df-bs-addon-suffix-outer-padding);\n      }\n      /* bs-button addons live inside .input-group-text for visual parity with\n         bs-icon (shared grey container). Strip the inner .btn's own visual\n         chrome (border, background, focus ring) so the button blends with\n         the addon container — done via Bootstrap's own CSS variables so the\n         cascade reaches the rendered <button> in any theme. No !important. */\n      :host ::ng-deep .input-group-text df-bs-button-addon .btn {\n        --bs-btn-bg: transparent;\n        --bs-btn-color: var(--bs-body-color);\n        --bs-btn-border-color: transparent;\n        --bs-btn-hover-bg: rgba(127, 127, 127, 0.12);\n        --bs-btn-hover-color: var(--bs-body-color);\n        --bs-btn-hover-border-color: transparent;\n        --bs-btn-active-bg: rgba(127, 127, 127, 0.18);\n        --bs-btn-active-border-color: transparent;\n        --bs-btn-focus-shadow-rgb: 0, 0, 0;\n        --bs-btn-padding-x: 0;\n        --bs-btn-padding-y: 0;\n        box-shadow: none;\n      }\n      :host ::ng-deep .input-group-text df-bs-button-addon .btn:focus-visible {\n        /* 2px solid for WCAG 2.4.11; currentColor adapts to light/dark themes. */\n        box-shadow: none;\n        outline: 2px solid currentColor;\n        outline-offset: 2px;\n      }\n    `,\n  ],\n})\nexport default class BsInputFieldComponent {\n  private bootstrapConfig = inject(BOOTSTRAP_CONFIG, { optional: true });\n\n  protected readonly ngf = injectNgForgeField<string>();\n  protected readonly ngfa = injectNgForgeAddons<BsInputAddon>();\n\n  readonly props = input<BsInputProps>();\n\n  /**\n   * Wrapper-style host bag pushed by `DfFieldOutlet`. Declared at the\n   * component level so `setInputIfDeclared` (which uses\n   * `reflectComponentType`) can write it.\n   */\n  readonly fieldInputs = input<WrapperFieldInputs | undefined>();\n\n  /** Per-instance type override populated by `toggle-password-visibility` preset. */\n  private readonly typeOverride = inject(BS_INPUT_TYPE_OVERRIDE);\n\n  readonly size = computed(() => this.props()?.size ?? this.bootstrapConfig?.size);\n  readonly floatingLabel = computed(() => this.props()?.floatingLabel ?? this.bootstrapConfig?.floatingLabel ?? false);\n\n  /** Override (set by `toggle-password-visibility` preset) wins over `props().type`. */\n  protected readonly type = computed(() => this.typeOverride() ?? this.props()?.type ?? 'text');\n}\n"]}