@letsprogram/ng-oat 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
- import { makeEnvironmentProviders, provideAppInitializer, inject, PLATFORM_ID, Injectable, ElementRef, DestroyRef, signal, output, afterNextRender, Directive, InjectionToken, Renderer2, ViewContainerRef, input, TemplateRef, effect, computed, Component, model, CUSTOM_ELEMENTS_SCHEMA, viewChild, viewChildren, contentChildren, contentChild } from '@angular/core';
2
+ import { makeEnvironmentProviders, provideAppInitializer, inject, PLATFORM_ID, Injectable, ElementRef, DestroyRef, signal, output, afterNextRender, Directive, InjectionToken, Renderer2, ViewContainerRef, input, TemplateRef, effect, computed, Component, model, forwardRef, CUSTOM_ELEMENTS_SCHEMA, viewChild, viewChildren, contentChildren, contentChild, HostListener } from '@angular/core';
3
3
  import { DOCUMENT, isPlatformBrowser, NgTemplateOutlet, NgSwitch, NgSwitchCase, NgSwitchDefault } from '@angular/common';
4
+ import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
5
 
5
6
  const DEFAULT_OPTIONS = {
6
7
  assets: { css: false },
@@ -1772,6 +1773,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
1772
1773
  }]
1773
1774
  }], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], overlay: [{ type: i0.Input, args: [{ isSignal: true, alias: "overlay", required: false }] }] } });
1774
1775
 
1776
+ /** Injection token provided by each value-type ng-oat form component. */
1777
+ const NG_OAT_VALUE_HOST = new InjectionToken('NG_OAT_VALUE_HOST');
1778
+ /** Injection token provided by each checkbox-type ng-oat form component. */
1779
+ const NG_OAT_CHECKBOX_HOST = new InjectionToken('NG_OAT_CHECKBOX_HOST');
1780
+
1775
1781
  /**
1776
1782
  * Angular wrapper for Oat CSS toggle switch.
1777
1783
  * Implements `FormCheckboxControl` for seamless Signal Forms integration — no CVA needed.
@@ -1789,16 +1795,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
1789
1795
  class NgOatSwitch {
1790
1796
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
1791
1797
  checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
1792
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
1798
+ disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
1799
+ touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : []));
1793
1800
  value = undefined;
1794
1801
  changed = output();
1795
1802
  onInputChange(event) {
1796
1803
  const val = event.target.checked;
1797
1804
  this.checked.set(val);
1805
+ this.touched.set(true);
1798
1806
  this.changed.emit(val);
1799
1807
  }
1800
1808
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
1801
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.0", type: NgOatSwitch, isStandalone: true, selector: "ng-oat-switch", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", changed: "changed" }, ngImport: i0, template: `
1809
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.0", type: NgOatSwitch, isStandalone: true, selector: "ng-oat-switch", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", disabled: "disabledChange", touched: "touchedChange", changed: "changed" }, providers: [{ provide: NG_OAT_CHECKBOX_HOST, useExisting: forwardRef(() => NgOatSwitch) }], ngImport: i0, template: `
1802
1810
  <label>
1803
1811
  <input
1804
1812
  type="checkbox"
@@ -1815,6 +1823,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
1815
1823
  type: Component,
1816
1824
  args: [{
1817
1825
  selector: 'ng-oat-switch',
1826
+ providers: [{ provide: NG_OAT_CHECKBOX_HOST, useExisting: forwardRef(() => NgOatSwitch) }],
1818
1827
  template: `
1819
1828
  <label>
1820
1829
  <input
@@ -1828,7 +1837,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
1828
1837
  </label>
1829
1838
  `,
1830
1839
  }]
1831
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
1840
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], changed: [{ type: i0.Output, args: ["changed"] }] } });
1832
1841
 
1833
1842
  /**
1834
1843
  * Angular wrapper for Oat CSS skeleton loader.
@@ -2396,10 +2405,23 @@ const MOBILE_BREAKPOINT = 768;
2396
2405
  /**
2397
2406
  * Angular component wrapper for Oat's sidebar layout.
2398
2407
  *
2399
- * Usage:
2408
+ * Supports two modes:
2409
+ * - `fixed` (default): Permanent sidebar on desktop, slide-out drawer on mobile.
2410
+ * - `overlay`: Slide-out drawer at all screen sizes (ideal for app shells
2411
+ * that already have a toolbar with nav links).
2412
+ *
2413
+ * Usage (fixed — permanent desktop sidebar):
2414
+ * ```html
2415
+ * <ng-oat-sidebar>
2416
+ * <aside data-sidebar>Navigation</aside>
2417
+ * <main>Main content</main>
2418
+ * </ng-oat-sidebar>
2419
+ * ```
2420
+ *
2421
+ * Usage (overlay — mobile-style drawer at all sizes):
2400
2422
  * ```html
2401
- * <ng-oat-sidebar [scrollLock]="true" (openChange)="onToggle($event)">
2402
- * <aside sidebar>Navigation</aside>
2423
+ * <ng-oat-sidebar mode="overlay">
2424
+ * <aside data-sidebar>Navigation</aside>
2403
2425
  * <main>Main content</main>
2404
2426
  * </ng-oat-sidebar>
2405
2427
  * ```
@@ -2410,11 +2432,19 @@ class NgOatSidebarComponent {
2410
2432
  destroyRef = inject(DestroyRef);
2411
2433
  platformId = inject(PLATFORM_ID);
2412
2434
  doc = inject(DOCUMENT);
2413
- /** Whether scroll lock is applied on mobile when sidebar is open */
2435
+ /**
2436
+ * Layout mode:
2437
+ * - `'fixed'` (default) — permanent sidebar on desktop, drawer on mobile.
2438
+ * - `'overlay'` — always a slide-out drawer at any screen size.
2439
+ */
2440
+ mode = input('fixed', ...(ngDevMode ? [{ debugName: "mode" }] : []));
2441
+ /** Whether scroll lock is applied when sidebar is open */
2414
2442
  scrollLock = input(true, ...(ngDevMode ? [{ debugName: "scrollLock" }] : []));
2415
2443
  initialOpen = input(false, ...(ngDevMode ? [{ debugName: "initialOpen" }] : []));
2416
2444
  isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
2417
2445
  openChange = output();
2446
+ /** Whether the sidebar is in overlay mode */
2447
+ isOverlay = computed(() => this.mode() === 'overlay', ...(ngDevMode ? [{ debugName: "isOverlay" }] : []));
2418
2448
  cleanupFns = [];
2419
2449
  constructor() {
2420
2450
  afterNextRender(() => {
@@ -2424,16 +2454,16 @@ class NgOatSidebarComponent {
2424
2454
  this.isOpen.set(true);
2425
2455
  }
2426
2456
  this.listen(this.doc, 'keydown', (e) => {
2427
- if (e.key === KEYS.ESCAPE && this.isOpen() && this.isMobile()) {
2457
+ if (e.key === KEYS.ESCAPE && this.isOpen() && this.shouldAutoClose()) {
2428
2458
  this.close();
2429
2459
  }
2430
2460
  });
2431
- // Outside click to close on mobile
2461
+ // Outside click to close
2432
2462
  this.listen(this.doc, 'click', (e) => {
2433
2463
  const target = e.target;
2434
2464
  if (this.isOpen() &&
2435
- this.isMobile() &&
2436
- !target.closest('[sidebar]') &&
2465
+ this.shouldAutoClose() &&
2466
+ !target.closest('[data-sidebar]') &&
2437
2467
  !target.closest('aside') &&
2438
2468
  !target.closest('[data-sidebar-toggle]')) {
2439
2469
  this.close();
@@ -2449,7 +2479,7 @@ class NgOatSidebarComponent {
2449
2479
  open() {
2450
2480
  this.isOpen.set(true);
2451
2481
  this.openChange.emit(true);
2452
- if (this.scrollLock() && this.isMobile()) {
2482
+ if (this.scrollLock() && this.shouldAutoClose()) {
2453
2483
  this.lockScroll();
2454
2484
  }
2455
2485
  }
@@ -2466,6 +2496,15 @@ class NgOatSidebarComponent {
2466
2496
  this.open();
2467
2497
  }
2468
2498
  }
2499
+ /**
2500
+ * Whether the sidebar should auto-close on outside click / ESC.
2501
+ * In overlay mode: always. In fixed mode: only on mobile.
2502
+ */
2503
+ shouldAutoClose() {
2504
+ if (this.mode() === 'overlay')
2505
+ return true;
2506
+ return typeof window !== 'undefined' && window.innerWidth < MOBILE_BREAKPOINT;
2507
+ }
2469
2508
  isMobile() {
2470
2509
  return typeof window !== 'undefined' && window.innerWidth < MOBILE_BREAKPOINT;
2471
2510
  }
@@ -2480,15 +2519,26 @@ class NgOatSidebarComponent {
2480
2519
  this.cleanupFns.push(() => el.removeEventListener(event, handler));
2481
2520
  }
2482
2521
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatSidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2483
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.0", type: NgOatSidebarComponent, isStandalone: true, selector: "ng-oat-sidebar", inputs: { scrollLock: { classPropertyName: "scrollLock", publicName: "scrollLock", isSignal: true, isRequired: false, transformFunction: null }, initialOpen: { classPropertyName: "initialOpen", publicName: "initialOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { openChange: "openChange" }, host: { properties: { "attr.data-sidebar-layout": "\"\"", "attr.data-sidebar-open": "isOpen() ? \"\" : null" } }, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block}\n"] });
2522
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatSidebarComponent, isStandalone: true, selector: "ng-oat-sidebar", inputs: { mode: { classPropertyName: "mode", publicName: "mode", isSignal: true, isRequired: false, transformFunction: null }, scrollLock: { classPropertyName: "scrollLock", publicName: "scrollLock", isSignal: true, isRequired: false, transformFunction: null }, initialOpen: { classPropertyName: "initialOpen", publicName: "initialOpen", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { openChange: "openChange" }, host: { properties: { "attr.data-sidebar-layout": "\"\"", "attr.data-sidebar-open": "isOpen() ? \"\" : null", "attr.data-sidebar-mode": "mode()" } }, ngImport: i0, template: `
2523
+ @if (isOpen() && isOverlay()) {
2524
+ <div class="ng-oat-sidebar-backdrop" (click)="close()"></div>
2525
+ }
2526
+ <ng-content />
2527
+ `, isInline: true, styles: [":host[data-sidebar-mode=overlay]{grid-template-columns:1fr!important}:host[data-sidebar-mode=overlay]>::ng-deep aside[data-sidebar]{position:fixed!important;left:0;top:var(--topnav-offset, 0px);width:16rem;height:calc(100dvh - var(--topnav-offset, 0px));z-index:20;transform:translate(-100%);transition:transform var(--transition, .3s ease);box-shadow:var(--shadow-large)}:host[data-sidebar-mode=overlay][data-sidebar-open]>::ng-deep aside[data-sidebar]{transform:translate(0)}.ng-oat-sidebar-backdrop{position:fixed;inset:0;z-index:19;background:#0006}\n"] });
2484
2528
  }
2485
2529
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatSidebarComponent, decorators: [{
2486
2530
  type: Component,
2487
2531
  args: [{ selector: 'ng-oat-sidebar', host: {
2488
2532
  '[attr.data-sidebar-layout]': '""',
2489
2533
  '[attr.data-sidebar-open]': 'isOpen() ? "" : null',
2490
- }, template: `<ng-content />`, styles: [":host{display:block}\n"] }]
2491
- }], ctorParameters: () => [], propDecorators: { scrollLock: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollLock", required: false }] }], initialOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialOpen", required: false }] }], openChange: [{ type: i0.Output, args: ["openChange"] }] } });
2534
+ '[attr.data-sidebar-mode]': 'mode()',
2535
+ }, template: `
2536
+ @if (isOpen() && isOverlay()) {
2537
+ <div class="ng-oat-sidebar-backdrop" (click)="close()"></div>
2538
+ }
2539
+ <ng-content />
2540
+ `, styles: [":host[data-sidebar-mode=overlay]{grid-template-columns:1fr!important}:host[data-sidebar-mode=overlay]>::ng-deep aside[data-sidebar]{position:fixed!important;left:0;top:var(--topnav-offset, 0px);width:16rem;height:calc(100dvh - var(--topnav-offset, 0px));z-index:20;transform:translate(-100%);transition:transform var(--transition, .3s ease);box-shadow:var(--shadow-large)}:host[data-sidebar-mode=overlay][data-sidebar-open]>::ng-deep aside[data-sidebar]{transform:translate(0)}.ng-oat-sidebar-backdrop{position:fixed;inset:0;z-index:19;background:#0006}\n"] }]
2541
+ }], ctorParameters: () => [], propDecorators: { mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], scrollLock: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollLock", required: false }] }], initialOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "initialOpen", required: false }] }], openChange: [{ type: i0.Output, args: ["openChange"] }] } });
2492
2542
 
2493
2543
  /**
2494
2544
  * Angular component wrapper for Oat's tabs.
@@ -3055,9 +3105,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
3055
3105
  class NgOatInputOtp {
3056
3106
  length = input(6, ...(ngDevMode ? [{ debugName: "length" }] : []));
3057
3107
  separator = input(0, ...(ngDevMode ? [{ debugName: "separator" }] : []));
3058
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
3108
+ disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
3059
3109
  mask = input(false, ...(ngDevMode ? [{ debugName: "mask" }] : []));
3060
3110
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
3111
+ touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : []));
3061
3112
  checked = undefined;
3062
3113
  slotInputRefs = viewChildren('slotInput', ...(ngDevMode ? [{ debugName: "slotInputRefs" }] : []));
3063
3114
  slots = computed(() => {
@@ -3069,6 +3120,7 @@ class NgOatInputOtp {
3069
3120
  const input = event.target;
3070
3121
  const char = input.value.replace(/\D/g, '').slice(-1);
3071
3122
  input.value = char;
3123
+ this.touched.set(true);
3072
3124
  this.updateValueAt(index, char);
3073
3125
  // Auto-advance to next slot
3074
3126
  if (char && index < this.length() - 1) {
@@ -3134,7 +3186,7 @@ class NgOatInputOtp {
3134
3186
  this.focusSlot(0);
3135
3187
  }
3136
3188
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatInputOtp, deps: [], target: i0.ɵɵFactoryTarget.Component });
3137
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatInputOtp, isStandalone: true, selector: "ng-oat-input-otp", inputs: { length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, mask: { classPropertyName: "mask", publicName: "mask", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, viewQueries: [{ propertyName: "slotInputRefs", predicate: ["slotInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
3189
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatInputOtp, isStandalone: true, selector: "ng-oat-input-otp", inputs: { length: { classPropertyName: "length", publicName: "length", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, mask: { classPropertyName: "mask", publicName: "mask", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", value: "valueChange", touched: "touchedChange" }, providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatInputOtp) }], viewQueries: [{ propertyName: "slotInputRefs", predicate: ["slotInput"], descendants: true, isSignal: true }], ngImport: i0, template: `
3138
3190
  <div class="otp-group" role="group" [attr.aria-label]="'OTP input with ' + length() + ' digits'">
3139
3191
  @for (slot of slots(); track $index) {
3140
3192
  @if (separator() > 0 && $index === separator()) {
@@ -3162,7 +3214,7 @@ class NgOatInputOtp {
3162
3214
  }
3163
3215
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatInputOtp, decorators: [{
3164
3216
  type: Component,
3165
- args: [{ selector: 'ng-oat-input-otp', template: `
3217
+ args: [{ selector: 'ng-oat-input-otp', providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatInputOtp) }], template: `
3166
3218
  <div class="otp-group" role="group" [attr.aria-label]="'OTP input with ' + length() + ' digits'">
3167
3219
  @for (slot of slots(); track $index) {
3168
3220
  @if (separator() > 0 && $index === separator()) {
@@ -3187,7 +3239,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
3187
3239
  }
3188
3240
  </div>
3189
3241
  `, styles: [":host{display:inline-block}\n"] }]
3190
- }], propDecorators: { length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], mask: [{ type: i0.Input, args: [{ isSignal: true, alias: "mask", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], slotInputRefs: [{ type: i0.ViewChildren, args: ['slotInput', { isSignal: true }] }] } });
3242
+ }], propDecorators: { length: [{ type: i0.Input, args: [{ isSignal: true, alias: "length", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], mask: [{ type: i0.Input, args: [{ isSignal: true, alias: "mask", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], slotInputRefs: [{ type: i0.ViewChildren, args: ['slotInput', { isSignal: true }] }] } });
3191
3243
 
3192
3244
  /**
3193
3245
  * Search input with icon, clear button, optional keyboard shortcut badge, and built-in debounce.
@@ -3201,7 +3253,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
3201
3253
  */
3202
3254
  class NgOatSearchInput {
3203
3255
  placeholder = input('Search...', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
3204
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
3256
+ disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
3205
3257
  shortcut = input('', ...(ngDevMode ? [{ debugName: "shortcut" }] : []));
3206
3258
  debounceMs = input(300, ...(ngDevMode ? [{ debugName: "debounceMs" }] : []));
3207
3259
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
@@ -3274,7 +3326,7 @@ class NgOatSearchInput {
3274
3326
  this.searchInputRef()?.nativeElement.focus(options);
3275
3327
  }
3276
3328
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatSearchInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
3277
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatSearchInput, isStandalone: true, selector: "ng-oat-search-input", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, shortcut: { classPropertyName: "shortcut", publicName: "shortcut", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", search: "search", touched: "touchedChange" }, viewQueries: [{ propertyName: "searchInputRef", first: true, predicate: ["searchEl"], descendants: true, isSignal: true }], ngImport: i0, template: `
3329
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatSearchInput, isStandalone: true, selector: "ng-oat-search-input", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, shortcut: { classPropertyName: "shortcut", publicName: "shortcut", isSignal: true, isRequired: false, transformFunction: null }, debounceMs: { classPropertyName: "debounceMs", publicName: "debounceMs", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange", value: "valueChange", search: "search", touched: "touchedChange" }, providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatSearchInput) }], viewQueries: [{ propertyName: "searchInputRef", first: true, predicate: ["searchEl"], descendants: true, isSignal: true }], ngImport: i0, template: `
3278
3330
  <div class="search-input" [class.has-value]="hasValue()">
3279
3331
  <span class="search-input-icon" aria-hidden="true">
3280
3332
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -3310,7 +3362,7 @@ class NgOatSearchInput {
3310
3362
  }
3311
3363
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatSearchInput, decorators: [{
3312
3364
  type: Component,
3313
- args: [{ selector: 'ng-oat-search-input', template: `
3365
+ args: [{ selector: 'ng-oat-search-input', providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatSearchInput) }], template: `
3314
3366
  <div class="search-input" [class.has-value]="hasValue()">
3315
3367
  <span class="search-input-icon" aria-hidden="true">
3316
3368
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -3343,7 +3395,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
3343
3395
  }
3344
3396
  </div>
3345
3397
  `, styles: [":host{display:block}\n"] }]
3346
- }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], shortcut: [{ type: i0.Input, args: [{ isSignal: true, alias: "shortcut", required: false }] }], debounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceMs", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], search: [{ type: i0.Output, args: ["search"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], searchInputRef: [{ type: i0.ViewChild, args: ['searchEl', { isSignal: true }] }] } });
3398
+ }], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], shortcut: [{ type: i0.Input, args: [{ isSignal: true, alias: "shortcut", required: false }] }], debounceMs: [{ type: i0.Input, args: [{ isSignal: true, alias: "debounceMs", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], search: [{ type: i0.Output, args: ["search"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], searchInputRef: [{ type: i0.ViewChild, args: ['searchEl', { isSignal: true }] }] } });
3347
3399
 
3348
3400
  /**
3349
3401
  * Separator component for visual content division. Renders as `<hr>` for
@@ -4992,7 +5044,7 @@ class NgOatInput {
4992
5044
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
4993
5045
  checked = undefined;
4994
5046
  // --- Signal Forms optional bindings ---
4995
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5047
+ disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
4996
5048
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
4997
5049
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
4998
5050
  invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : []));
@@ -5002,12 +5054,13 @@ class NgOatInput {
5002
5054
  max = input(undefined, ...(ngDevMode ? [{ debugName: "max" }] : []));
5003
5055
  minLength = input(undefined, ...(ngDevMode ? [{ debugName: "minLength" }] : []));
5004
5056
  maxLength = input(undefined, ...(ngDevMode ? [{ debugName: "maxLength" }] : []));
5057
+ autocomplete = input(undefined, ...(ngDevMode ? [{ debugName: "autocomplete" }] : []));
5005
5058
  // --- Component-specific inputs ---
5006
5059
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
5007
5060
  type = input('text', ...(ngDevMode ? [{ debugName: "type" }] : []));
5008
5061
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
5009
5062
  showErrors = input(true, ...(ngDevMode ? [{ debugName: "showErrors" }] : []));
5010
- inputId = computed(() => `ng-oat-input-${++NgOatInput.nextId}`, ...(ngDevMode ? [{ debugName: "inputId" }] : []));
5063
+ inputId = `ng-oat-input-${++NgOatInput.nextId}`;
5011
5064
  onInput(event) {
5012
5065
  const val = event.target.value;
5013
5066
  this.value.set(val);
@@ -5016,66 +5069,68 @@ class NgOatInput {
5016
5069
  this.touched.set(true);
5017
5070
  }
5018
5071
  focus(options) {
5019
- const input = document.getElementById(this.inputId());
5072
+ const input = document.getElementById(this.inputId);
5020
5073
  input?.focus(options);
5021
5074
  }
5022
5075
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
5023
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatInput, isStandalone: true, selector: "ng-oat-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, showErrors: { classPropertyName: "showErrors", publicName: "showErrors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: `
5076
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatInput, isStandalone: true, selector: "ng-oat-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, autocomplete: { classPropertyName: "autocomplete", publicName: "autocomplete", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, showErrors: { classPropertyName: "showErrors", publicName: "showErrors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", disabled: "disabledChange", touched: "touchedChange" }, providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatInput) }], ngImport: i0, template: `
5024
5077
  @if (label()) {
5025
- <label [attr.for]="inputId()">{{ label() }}</label>
5078
+ <label [attr.for]="inputId">{{ label() }}</label>
5026
5079
  }
5027
5080
  <input
5028
- [id]="inputId()"
5081
+ [id]="inputId"
5029
5082
  [type]="type()"
5030
5083
  [value]="value()"
5031
5084
  [placeholder]="placeholder()"
5032
5085
  [disabled]="disabled()"
5033
5086
  [readOnly]="readonly()"
5034
5087
  [required]="required()"
5035
- [attr.aria-invalid]="invalid() || null"
5088
+ [attr.aria-invalid]="(invalid() && touched()) || null"
5036
5089
  [attr.min]="min() ?? null"
5037
5090
  [attr.max]="max() ?? null"
5038
5091
  [attr.minlength]="minLength() ?? null"
5092
+ [attr.autocomplete]="autocomplete() ?? null"
5039
5093
  [attr.maxlength]="maxLength() ?? null"
5040
5094
  (input)="onInput($event)"
5041
5095
  (blur)="onBlur()"
5042
5096
  />
5043
- @if (showErrors()) {
5097
+ <!-- @if (showErrors() && touched()) {
5044
5098
  @for (err of errors(); track $index) {
5045
5099
  <small class="error">{{ err.message }}</small>
5046
5100
  }
5047
- }
5101
+ } -->
5048
5102
  `, isInline: true, styles: [":host{display:block}.error{color:var(--danger);display:block;font-size:var(--text-8);margin-block-start:var(--space-1)}\n"] });
5049
5103
  }
5050
5104
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatInput, decorators: [{
5051
5105
  type: Component,
5052
- args: [{ selector: 'ng-oat-input', template: `
5106
+ args: [{ selector: 'ng-oat-input', providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatInput) }], template: `
5053
5107
  @if (label()) {
5054
- <label [attr.for]="inputId()">{{ label() }}</label>
5108
+ <label [attr.for]="inputId">{{ label() }}</label>
5055
5109
  }
5056
5110
  <input
5057
- [id]="inputId()"
5111
+ [id]="inputId"
5058
5112
  [type]="type()"
5059
5113
  [value]="value()"
5060
5114
  [placeholder]="placeholder()"
5061
5115
  [disabled]="disabled()"
5062
5116
  [readOnly]="readonly()"
5063
5117
  [required]="required()"
5064
- [attr.aria-invalid]="invalid() || null"
5118
+ [attr.aria-invalid]="(invalid() && touched()) || null"
5065
5119
  [attr.min]="min() ?? null"
5066
5120
  [attr.max]="max() ?? null"
5067
5121
  [attr.minlength]="minLength() ?? null"
5122
+ [attr.autocomplete]="autocomplete() ?? null"
5068
5123
  [attr.maxlength]="maxLength() ?? null"
5069
5124
  (input)="onInput($event)"
5070
5125
  (blur)="onBlur()"
5071
5126
  />
5072
- @if (showErrors()) {
5127
+ <!-- @if (showErrors() && touched()) {
5073
5128
  @for (err of errors(); track $index) {
5074
5129
  <small class="error">{{ err.message }}</small>
5075
5130
  }
5076
- }
5131
+ } -->
5077
5132
  `, styles: [":host{display:block}.error{color:var(--danger);display:block;font-size:var(--text-8);margin-block-start:var(--space-1)}\n"] }]
5078
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], showErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrors", required: false }] }] } });
5133
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], autocomplete: [{ type: i0.Input, args: [{ isSignal: true, alias: "autocomplete", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], showErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrors", required: false }] }] } });
5079
5134
 
5080
5135
  /**
5081
5136
  * Oat-styled textarea implementing `FormValueControl<string>`.
@@ -5095,7 +5150,7 @@ class NgOatTextarea {
5095
5150
  static nextId = 0;
5096
5151
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
5097
5152
  checked = undefined;
5098
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5153
+ disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5099
5154
  readonly = input(false, ...(ngDevMode ? [{ debugName: "readonly" }] : []));
5100
5155
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
5101
5156
  invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : []));
@@ -5108,7 +5163,7 @@ class NgOatTextarea {
5108
5163
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
5109
5164
  rows = input(4, ...(ngDevMode ? [{ debugName: "rows" }] : []));
5110
5165
  showErrors = input(true, ...(ngDevMode ? [{ debugName: "showErrors" }] : []));
5111
- textareaId = computed(() => `ng-oat-ta-${++NgOatTextarea.nextId}`, ...(ngDevMode ? [{ debugName: "textareaId" }] : []));
5166
+ textareaId = `ng-oat-ta-${++NgOatTextarea.nextId}`;
5112
5167
  onInput(event) {
5113
5168
  const val = event.target.value;
5114
5169
  this.value.set(val);
@@ -5117,29 +5172,29 @@ class NgOatTextarea {
5117
5172
  this.touched.set(true);
5118
5173
  }
5119
5174
  focus(options) {
5120
- const el = document.getElementById(this.textareaId());
5175
+ const el = document.getElementById(this.textareaId);
5121
5176
  el?.focus(options);
5122
5177
  }
5123
5178
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatTextarea, deps: [], target: i0.ɵɵFactoryTarget.Component });
5124
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatTextarea, isStandalone: true, selector: "ng-oat-textarea", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, showErrors: { classPropertyName: "showErrors", publicName: "showErrors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: `
5179
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatTextarea, isStandalone: true, selector: "ng-oat-textarea", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, minLength: { classPropertyName: "minLength", publicName: "minLength", isSignal: true, isRequired: false, transformFunction: null }, maxLength: { classPropertyName: "maxLength", publicName: "maxLength", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, showErrors: { classPropertyName: "showErrors", publicName: "showErrors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", disabled: "disabledChange", touched: "touchedChange" }, providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatTextarea) }], ngImport: i0, template: `
5125
5180
  @if (label()) {
5126
- <label [attr.for]="textareaId()">{{ label() }}</label>
5181
+ <label [attr.for]="textareaId">{{ label() }}</label>
5127
5182
  }
5128
5183
  <textarea
5129
- [id]="textareaId()"
5184
+ [id]="textareaId"
5130
5185
  [value]="value()"
5131
5186
  [placeholder]="placeholder()"
5132
5187
  [disabled]="disabled()"
5133
5188
  [readOnly]="readonly()"
5134
5189
  [required]="required()"
5135
5190
  [rows]="rows()"
5136
- [attr.aria-invalid]="invalid() || null"
5191
+ [attr.aria-invalid]="(invalid() && touched()) || null"
5137
5192
  [attr.minlength]="minLength() ?? null"
5138
5193
  [attr.maxlength]="maxLength() ?? null"
5139
5194
  (input)="onInput($event)"
5140
5195
  (blur)="onBlur()"
5141
5196
  ></textarea>
5142
- @if (showErrors()) {
5197
+ @if (showErrors() && touched()) {
5143
5198
  @for (err of errors(); track $index) {
5144
5199
  <small class="error">{{ err.message }}</small>
5145
5200
  }
@@ -5148,31 +5203,31 @@ class NgOatTextarea {
5148
5203
  }
5149
5204
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatTextarea, decorators: [{
5150
5205
  type: Component,
5151
- args: [{ selector: 'ng-oat-textarea', template: `
5206
+ args: [{ selector: 'ng-oat-textarea', providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatTextarea) }], template: `
5152
5207
  @if (label()) {
5153
- <label [attr.for]="textareaId()">{{ label() }}</label>
5208
+ <label [attr.for]="textareaId">{{ label() }}</label>
5154
5209
  }
5155
5210
  <textarea
5156
- [id]="textareaId()"
5211
+ [id]="textareaId"
5157
5212
  [value]="value()"
5158
5213
  [placeholder]="placeholder()"
5159
5214
  [disabled]="disabled()"
5160
5215
  [readOnly]="readonly()"
5161
5216
  [required]="required()"
5162
5217
  [rows]="rows()"
5163
- [attr.aria-invalid]="invalid() || null"
5218
+ [attr.aria-invalid]="(invalid() && touched()) || null"
5164
5219
  [attr.minlength]="minLength() ?? null"
5165
5220
  [attr.maxlength]="maxLength() ?? null"
5166
5221
  (input)="onInput($event)"
5167
5222
  (blur)="onBlur()"
5168
5223
  ></textarea>
5169
- @if (showErrors()) {
5224
+ @if (showErrors() && touched()) {
5170
5225
  @for (err of errors(); track $index) {
5171
5226
  <small class="error">{{ err.message }}</small>
5172
5227
  }
5173
5228
  }
5174
5229
  `, styles: [":host{display:block}.error{color:var(--danger);display:block;font-size:var(--text-8);margin-block-start:var(--space-1)}\n"] }]
5175
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], showErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrors", required: false }] }] } });
5230
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], minLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "minLength", required: false }] }], maxLength: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxLength", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], showErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrors", required: false }] }] } });
5176
5231
 
5177
5232
  /**
5178
5233
  * Oat-styled select implementing `FormValueControl<string>`.
@@ -5193,7 +5248,7 @@ class NgOatSelect {
5193
5248
  checked = undefined;
5194
5249
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
5195
5250
  // --- Signal Forms optional bindings ---
5196
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5251
+ disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5197
5252
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
5198
5253
  invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : []));
5199
5254
  errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : []));
@@ -5203,7 +5258,7 @@ class NgOatSelect {
5203
5258
  placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
5204
5259
  options = input.required(...(ngDevMode ? [{ debugName: "options" }] : []));
5205
5260
  showErrors = input(true, ...(ngDevMode ? [{ debugName: "showErrors" }] : []));
5206
- selectId = computed(() => `ng-oat-sel-${++NgOatSelect.nextId}`, ...(ngDevMode ? [{ debugName: "selectId" }] : []));
5261
+ selectId = `ng-oat-sel-${++NgOatSelect.nextId}`;
5207
5262
  onChange(event) {
5208
5263
  const val = event.target.value;
5209
5264
  this.value.set(val);
@@ -5212,20 +5267,20 @@ class NgOatSelect {
5212
5267
  this.touched.set(true);
5213
5268
  }
5214
5269
  focus(options) {
5215
- const el = document.getElementById(this.selectId());
5270
+ const el = document.getElementById(this.selectId);
5216
5271
  el?.focus(options);
5217
5272
  }
5218
5273
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatSelect, deps: [], target: i0.ɵɵFactoryTarget.Component });
5219
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatSelect, isStandalone: true, selector: "ng-oat-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, showErrors: { classPropertyName: "showErrors", publicName: "showErrors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: `
5274
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatSelect, isStandalone: true, selector: "ng-oat-select", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, showErrors: { classPropertyName: "showErrors", publicName: "showErrors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", disabled: "disabledChange", touched: "touchedChange" }, providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatSelect) }], ngImport: i0, template: `
5220
5275
  @if (label()) {
5221
- <label [attr.for]="selectId()">{{ label() }}</label>
5276
+ <label [attr.for]="selectId">{{ label() }}</label>
5222
5277
  }
5223
5278
  <select
5224
- [id]="selectId()"
5279
+ [id]="selectId"
5225
5280
  [value]="value()"
5226
5281
  [disabled]="disabled()"
5227
5282
  [required]="required()"
5228
- [attr.aria-invalid]="invalid() || null"
5283
+ [attr.aria-invalid]="(invalid() && touched()) || null"
5229
5284
  (change)="onChange($event)"
5230
5285
  (blur)="onBlur()"
5231
5286
  >
@@ -5241,7 +5296,7 @@ class NgOatSelect {
5241
5296
  </option>
5242
5297
  }
5243
5298
  </select>
5244
- @if (showErrors()) {
5299
+ @if (showErrors() && touched()) {
5245
5300
  @for (err of errors(); track $index) {
5246
5301
  <small class="error">{{ err.message }}</small>
5247
5302
  }
@@ -5250,16 +5305,16 @@ class NgOatSelect {
5250
5305
  }
5251
5306
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatSelect, decorators: [{
5252
5307
  type: Component,
5253
- args: [{ selector: 'ng-oat-select', template: `
5308
+ args: [{ selector: 'ng-oat-select', providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatSelect) }], template: `
5254
5309
  @if (label()) {
5255
- <label [attr.for]="selectId()">{{ label() }}</label>
5310
+ <label [attr.for]="selectId">{{ label() }}</label>
5256
5311
  }
5257
5312
  <select
5258
- [id]="selectId()"
5313
+ [id]="selectId"
5259
5314
  [value]="value()"
5260
5315
  [disabled]="disabled()"
5261
5316
  [required]="required()"
5262
- [attr.aria-invalid]="invalid() || null"
5317
+ [attr.aria-invalid]="(invalid() && touched()) || null"
5263
5318
  (change)="onChange($event)"
5264
5319
  (blur)="onBlur()"
5265
5320
  >
@@ -5275,13 +5330,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
5275
5330
  </option>
5276
5331
  }
5277
5332
  </select>
5278
- @if (showErrors()) {
5333
+ @if (showErrors() && touched()) {
5279
5334
  @for (err of errors(); track $index) {
5280
5335
  <small class="error">{{ err.message }}</small>
5281
5336
  }
5282
5337
  }
5283
5338
  `, styles: [":host{display:block}.error{color:var(--danger);display:block;font-size:var(--text-8);margin-block-start:var(--space-1)}\n"] }]
5284
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], showErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrors", required: false }] }] } });
5339
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], showErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrors", required: false }] }] } });
5285
5340
 
5286
5341
  /**
5287
5342
  * Oat-styled checkbox implementing `FormCheckboxControl`.
@@ -5299,7 +5354,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
5299
5354
  */
5300
5355
  class NgOatCheckbox {
5301
5356
  checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : []));
5302
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5357
+ disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5358
+ touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : []));
5303
5359
  /** FormCheckboxControl requires `value` to be undefined */
5304
5360
  value = undefined;
5305
5361
  // --- Component-specific inputs ---
@@ -5307,9 +5363,10 @@ class NgOatCheckbox {
5307
5363
  onChange(event) {
5308
5364
  const val = event.target.checked;
5309
5365
  this.checked.set(val);
5366
+ this.touched.set(true);
5310
5367
  }
5311
5368
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
5312
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.0", type: NgOatCheckbox, isStandalone: true, selector: "ng-oat-checkbox", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange" }, ngImport: i0, template: `
5369
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.0", type: NgOatCheckbox, isStandalone: true, selector: "ng-oat-checkbox", inputs: { checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", disabled: "disabledChange", touched: "touchedChange" }, providers: [{ provide: NG_OAT_CHECKBOX_HOST, useExisting: forwardRef(() => NgOatCheckbox) }], ngImport: i0, template: `
5313
5370
  <label>
5314
5371
  <input
5315
5372
  type="checkbox"
@@ -5325,6 +5382,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
5325
5382
  type: Component,
5326
5383
  args: [{
5327
5384
  selector: 'ng-oat-checkbox',
5385
+ providers: [{ provide: NG_OAT_CHECKBOX_HOST, useExisting: forwardRef(() => NgOatCheckbox) }],
5328
5386
  template: `
5329
5387
  <label>
5330
5388
  <input
@@ -5337,7 +5395,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
5337
5395
  </label>
5338
5396
  `,
5339
5397
  }]
5340
- }], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
5398
+ }], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
5341
5399
 
5342
5400
  /**
5343
5401
  * Oat-styled radio group implementing `FormValueControl<string>`.
@@ -5364,7 +5422,7 @@ class NgOatRadioGroup {
5364
5422
  value = model('', ...(ngDevMode ? [{ debugName: "value" }] : []));
5365
5423
  checked = undefined;
5366
5424
  // --- Signal Forms optional bindings ---
5367
- disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5425
+ disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
5368
5426
  required = input(false, ...(ngDevMode ? [{ debugName: "required" }] : []));
5369
5427
  invalid = input(false, ...(ngDevMode ? [{ debugName: "invalid" }] : []));
5370
5428
  errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : []));
@@ -5373,13 +5431,13 @@ class NgOatRadioGroup {
5373
5431
  label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
5374
5432
  options = input.required(...(ngDevMode ? [{ debugName: "options" }] : []));
5375
5433
  showErrors = input(true, ...(ngDevMode ? [{ debugName: "showErrors" }] : []));
5376
- groupName = computed(() => `ng-oat-radio-${++NgOatRadioGroup.nextId}`, ...(ngDevMode ? [{ debugName: "groupName" }] : []));
5434
+ groupName = `ng-oat-radio-${++NgOatRadioGroup.nextId}`;
5377
5435
  onSelect(val) {
5378
5436
  this.value.set(val);
5379
5437
  this.touched.set(true);
5380
5438
  }
5381
5439
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatRadioGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
5382
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatRadioGroup, isStandalone: true, selector: "ng-oat-radio-group", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, showErrors: { classPropertyName: "showErrors", publicName: "showErrors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, ngImport: i0, template: `
5440
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatRadioGroup, isStandalone: true, selector: "ng-oat-radio-group", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, showErrors: { classPropertyName: "showErrors", publicName: "showErrors", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", disabled: "disabledChange", touched: "touchedChange" }, providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatRadioGroup) }], ngImport: i0, template: `
5383
5441
  @if (label()) {
5384
5442
  <fieldset>
5385
5443
  <legend>{{ label() }}</legend>
@@ -5387,7 +5445,7 @@ class NgOatRadioGroup {
5387
5445
  <label>
5388
5446
  <input
5389
5447
  type="radio"
5390
- [name]="groupName()"
5448
+ [name]="groupName"
5391
5449
  [value]="opt.value"
5392
5450
  [checked]="opt.value === value()"
5393
5451
  [disabled]="disabled() || (opt.disabled ?? false)"
@@ -5402,7 +5460,7 @@ class NgOatRadioGroup {
5402
5460
  <label>
5403
5461
  <input
5404
5462
  type="radio"
5405
- [name]="groupName()"
5463
+ [name]="groupName"
5406
5464
  [value]="opt.value"
5407
5465
  [checked]="opt.value === value()"
5408
5466
  [disabled]="disabled() || (opt.disabled ?? false)"
@@ -5412,7 +5470,7 @@ class NgOatRadioGroup {
5412
5470
  </label>
5413
5471
  }
5414
5472
  }
5415
- @if (showErrors()) {
5473
+ @if (showErrors() && touched()) {
5416
5474
  @for (err of errors(); track $index) {
5417
5475
  <small class="error">{{ err.message }}</small>
5418
5476
  }
@@ -5421,7 +5479,7 @@ class NgOatRadioGroup {
5421
5479
  }
5422
5480
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatRadioGroup, decorators: [{
5423
5481
  type: Component,
5424
- args: [{ selector: 'ng-oat-radio-group', template: `
5482
+ args: [{ selector: 'ng-oat-radio-group', providers: [{ provide: NG_OAT_VALUE_HOST, useExisting: forwardRef(() => NgOatRadioGroup) }], template: `
5425
5483
  @if (label()) {
5426
5484
  <fieldset>
5427
5485
  <legend>{{ label() }}</legend>
@@ -5429,7 +5487,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
5429
5487
  <label>
5430
5488
  <input
5431
5489
  type="radio"
5432
- [name]="groupName()"
5490
+ [name]="groupName"
5433
5491
  [value]="opt.value"
5434
5492
  [checked]="opt.value === value()"
5435
5493
  [disabled]="disabled() || (opt.disabled ?? false)"
@@ -5444,7 +5502,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
5444
5502
  <label>
5445
5503
  <input
5446
5504
  type="radio"
5447
- [name]="groupName()"
5505
+ [name]="groupName"
5448
5506
  [value]="opt.value"
5449
5507
  [checked]="opt.value === value()"
5450
5508
  [disabled]="disabled() || (opt.disabled ?? false)"
@@ -5454,35 +5512,54 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
5454
5512
  </label>
5455
5513
  }
5456
5514
  }
5457
- @if (showErrors()) {
5515
+ @if (showErrors() && touched()) {
5458
5516
  @for (err of errors(); track $index) {
5459
5517
  <small class="error">{{ err.message }}</small>
5460
5518
  }
5461
5519
  }
5462
5520
  `, styles: [":host{display:block}fieldset{border:none;padding:0;margin:0}legend{font-size:var(--text-7);font-weight:var(--font-medium);margin-block-end:var(--space-1)}label{display:flex;align-items:center;gap:var(--space-2);margin-block-end:var(--space-1)}.error{color:var(--danger);display:block;font-size:var(--text-8);margin-block-start:var(--space-1)}\n"] }]
5463
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], showErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrors", required: false }] }] } });
5521
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], showErrors: [{ type: i0.Input, args: [{ isSignal: true, alias: "showErrors", required: false }] }] } });
5464
5522
 
5465
5523
  /**
5466
- * Displays validation errors for a Signal Forms field.
5467
- * Shows errors only when the field has been touched and is invalid.
5524
+ * Displays validation errors for form fields.
5468
5525
  *
5469
- * Usage:
5526
+ * **Signal Forms** — pass the `FieldState` directly:
5470
5527
  * ```html
5471
- * <ng-oat-input label="Email" [formField]="myForm.email" />
5472
5528
  * <ng-oat-form-error [control]="myForm.email" />
5473
5529
  * ```
5530
+ *
5531
+ * **Reactive / Template-driven** — pass error strings and a visibility flag:
5532
+ * ```html
5533
+ * <ng-oat-form-error [errors]="['Email is required']" [show]="email.touched && email.invalid" />
5534
+ * ```
5474
5535
  */
5475
5536
  class NgOatFormError {
5476
- control = input.required(...(ngDevMode ? [{ debugName: "control" }] : []));
5537
+ /** Signal Forms FieldState for automatic error display. */
5538
+ control = input(...(ngDevMode ? [undefined, { debugName: "control" }] : []));
5539
+ /** Plain error message strings — for Reactive / Template-driven forms. */
5540
+ errors = input([], ...(ngDevMode ? [{ debugName: "errors" }] : []));
5541
+ /** External visibility flag — for Reactive / Template-driven forms. */
5542
+ show = input(false, ...(ngDevMode ? [{ debugName: "show" }] : []));
5543
+ /** Unified list of error message strings. */
5544
+ errorMessages = computed(() => {
5545
+ const ctrl = this.control();
5546
+ if (ctrl) {
5547
+ return ctrl.errors().map(e => e.message);
5548
+ }
5549
+ return this.errors();
5550
+ }, ...(ngDevMode ? [{ debugName: "errorMessages" }] : []));
5477
5551
  shouldShowError = computed(() => {
5478
- const field = this.control();
5479
- return !field.valid() && field.touched();
5552
+ const ctrl = this.control();
5553
+ if (ctrl) {
5554
+ return !ctrl.valid() && ctrl.touched();
5555
+ }
5556
+ return this.show() && this.errors().length > 0;
5480
5557
  }, ...(ngDevMode ? [{ debugName: "shouldShowError" }] : []));
5481
5558
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatFormError, deps: [], target: i0.ɵɵFactoryTarget.Component });
5482
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatFormError, isStandalone: true, selector: "ng-oat-form-error", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
5559
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.0", type: NgOatFormError, isStandalone: true, selector: "ng-oat-form-error", inputs: { control: { classPropertyName: "control", publicName: "control", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, show: { classPropertyName: "show", publicName: "show", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
5483
5560
  @if (shouldShowError()) {
5484
- @for (error of control().errors(); track error.kind) {
5485
- <small class="error">{{ error.message }}</small>
5561
+ @for (msg of errorMessages(); track $index) {
5562
+ <small class="error">{{ msg }}</small>
5486
5563
  }
5487
5564
  }
5488
5565
  `, isInline: true, styles: [":host{display:block}.error{display:block;font-size:var(--text-8);font-weight:var(--font-normal);color:var(--danger);margin-block-start:var(--space-1)}\n"] });
@@ -5491,12 +5568,175 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImpor
5491
5568
  type: Component,
5492
5569
  args: [{ selector: 'ng-oat-form-error', template: `
5493
5570
  @if (shouldShowError()) {
5494
- @for (error of control().errors(); track error.kind) {
5495
- <small class="error">{{ error.message }}</small>
5571
+ @for (msg of errorMessages(); track $index) {
5572
+ <small class="error">{{ msg }}</small>
5496
5573
  }
5497
5574
  }
5498
5575
  `, styles: [":host{display:block}.error{display:block;font-size:var(--text-8);font-weight:var(--font-normal);color:var(--danger);margin-block-start:var(--space-1)}\n"] }]
5499
- }], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: true }] }] } });
5576
+ }], propDecorators: { control: [{ type: i0.Input, args: [{ isSignal: true, alias: "control", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], show: [{ type: i0.Input, args: [{ isSignal: true, alias: "show", required: false }] }] } });
5577
+
5578
+ /**
5579
+ * ControlValueAccessor adapter for ng-oat **value-type** components.
5580
+ *
5581
+ * Auto-activates when a Reactive Forms or Template-driven directive is present
5582
+ * (`formControlName`, `[formControl]`, or `[(ngModel)]`).
5583
+ *
5584
+ * Add this directive to your component's `imports` alongside the form component:
5585
+ * ```typescript
5586
+ * imports: [ReactiveFormsModule, NgOatInput, NgOatValueCva]
5587
+ * ```
5588
+ *
5589
+ * ```html
5590
+ * <ng-oat-input label="Email" formControlName="email" />
5591
+ * <ng-oat-input label="Name" [(ngModel)]="name" />
5592
+ * ```
5593
+ */
5594
+ class NgOatValueCva {
5595
+ host = inject(NG_OAT_VALUE_HOST);
5596
+ onChange = () => { };
5597
+ onTouched = () => { };
5598
+ /**
5599
+ * Listen for native `input` and `change` events that bubble from the inner
5600
+ * `<input>`, `<textarea>`, or `<select>` element up to the host component.
5601
+ */
5602
+ onHostValueChange() {
5603
+ this.onChange(this.host.value());
5604
+ }
5605
+ /** Mark as touched when focus leaves the host element tree. */
5606
+ onHostBlur() {
5607
+ this.host.touched.set(true);
5608
+ this.onTouched();
5609
+ }
5610
+ // --- ControlValueAccessor ---
5611
+ writeValue(val) {
5612
+ this.host.value.set(val ?? '');
5613
+ }
5614
+ registerOnChange(fn) {
5615
+ this.onChange = fn;
5616
+ }
5617
+ registerOnTouched(fn) {
5618
+ this.onTouched = fn;
5619
+ }
5620
+ setDisabledState(isDisabled) {
5621
+ this.host.disabled.set(isDisabled);
5622
+ }
5623
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatValueCva, deps: [], target: i0.ɵɵFactoryTarget.Directive });
5624
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.0", type: NgOatValueCva, isStandalone: true, selector: "ng-oat-input[formControlName],ng-oat-input[formControl],ng-oat-input[ngModel],\nng-oat-textarea[formControlName],ng-oat-textarea[formControl],ng-oat-textarea[ngModel],\nng-oat-select[formControlName],ng-oat-select[formControl],ng-oat-select[ngModel],\nng-oat-radio-group[formControlName],ng-oat-radio-group[formControl],ng-oat-radio-group[ngModel],\nng-oat-search-input[formControlName],ng-oat-search-input[formControl],ng-oat-search-input[ngModel],\nng-oat-input-otp[formControlName],ng-oat-input-otp[formControl],ng-oat-input-otp[ngModel]", host: { listeners: { "input": "onHostValueChange()", "change": "onHostValueChange()", "focusout": "onHostBlur()" } }, providers: [
5625
+ {
5626
+ provide: NG_VALUE_ACCESSOR,
5627
+ useExisting: forwardRef(() => NgOatValueCva),
5628
+ multi: true,
5629
+ },
5630
+ ], ngImport: i0 });
5631
+ }
5632
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatValueCva, decorators: [{
5633
+ type: Directive,
5634
+ args: [{
5635
+ selector: `ng-oat-input[formControlName],ng-oat-input[formControl],ng-oat-input[ngModel],
5636
+ ng-oat-textarea[formControlName],ng-oat-textarea[formControl],ng-oat-textarea[ngModel],
5637
+ ng-oat-select[formControlName],ng-oat-select[formControl],ng-oat-select[ngModel],
5638
+ ng-oat-radio-group[formControlName],ng-oat-radio-group[formControl],ng-oat-radio-group[ngModel],
5639
+ ng-oat-search-input[formControlName],ng-oat-search-input[formControl],ng-oat-search-input[ngModel],
5640
+ ng-oat-input-otp[formControlName],ng-oat-input-otp[formControl],ng-oat-input-otp[ngModel]`,
5641
+ providers: [
5642
+ {
5643
+ provide: NG_VALUE_ACCESSOR,
5644
+ useExisting: forwardRef(() => NgOatValueCva),
5645
+ multi: true,
5646
+ },
5647
+ ],
5648
+ }]
5649
+ }], propDecorators: { onHostValueChange: [{
5650
+ type: HostListener,
5651
+ args: ['input']
5652
+ }, {
5653
+ type: HostListener,
5654
+ args: ['change']
5655
+ }], onHostBlur: [{
5656
+ type: HostListener,
5657
+ args: ['focusout']
5658
+ }] } });
5659
+
5660
+ /**
5661
+ * ControlValueAccessor adapter for ng-oat **checkbox-type** components.
5662
+ *
5663
+ * Auto-activates when a Reactive Forms or Template-driven directive is present
5664
+ * (`formControlName`, `[formControl]`, or `[(ngModel)]`).
5665
+ *
5666
+ * Add this directive to your component's `imports` alongside the form component:
5667
+ * ```typescript
5668
+ * imports: [ReactiveFormsModule, NgOatCheckbox, NgOatCheckboxCva]
5669
+ * ```
5670
+ *
5671
+ * ```html
5672
+ * <ng-oat-checkbox label="Accept terms" formControlName="accepted" />
5673
+ * <ng-oat-switch label="Alerts" [(ngModel)]="alertsOn" />
5674
+ * ```
5675
+ */
5676
+ class NgOatCheckboxCva {
5677
+ host = inject(NG_OAT_CHECKBOX_HOST);
5678
+ onChange = () => { };
5679
+ onTouched = () => { };
5680
+ /**
5681
+ * Listen for native `change` events that bubble from the inner
5682
+ * `<input type="checkbox">` up to the host component.
5683
+ */
5684
+ onHostChange() {
5685
+ this.onChange(this.host.checked());
5686
+ this.host.touched.set(true);
5687
+ this.onTouched();
5688
+ }
5689
+ /** Mark as touched when focus leaves the host element tree. */
5690
+ onHostBlur() {
5691
+ this.host.touched.set(true);
5692
+ this.onTouched();
5693
+ }
5694
+ // --- ControlValueAccessor ---
5695
+ writeValue(val) {
5696
+ this.host.checked.set(!!val);
5697
+ }
5698
+ registerOnChange(fn) {
5699
+ this.onChange = fn;
5700
+ }
5701
+ registerOnTouched(fn) {
5702
+ this.onTouched = fn;
5703
+ }
5704
+ setDisabledState(isDisabled) {
5705
+ this.host.disabled.set(isDisabled);
5706
+ }
5707
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatCheckboxCva, deps: [], target: i0.ɵɵFactoryTarget.Directive });
5708
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.0", type: NgOatCheckboxCva, isStandalone: true, selector: "ng-oat-checkbox[formControlName],ng-oat-checkbox[formControl],ng-oat-checkbox[ngModel],\nng-oat-switch[formControlName],ng-oat-switch[formControl],ng-oat-switch[ngModel]", host: { listeners: { "change": "onHostChange()", "focusout": "onHostBlur()" } }, providers: [
5709
+ {
5710
+ provide: NG_VALUE_ACCESSOR,
5711
+ useExisting: forwardRef(() => NgOatCheckboxCva),
5712
+ multi: true,
5713
+ },
5714
+ ], ngImport: i0 });
5715
+ }
5716
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.0", ngImport: i0, type: NgOatCheckboxCva, decorators: [{
5717
+ type: Directive,
5718
+ args: [{
5719
+ selector: `ng-oat-checkbox[formControlName],ng-oat-checkbox[formControl],ng-oat-checkbox[ngModel],
5720
+ ng-oat-switch[formControlName],ng-oat-switch[formControl],ng-oat-switch[ngModel]`,
5721
+ providers: [
5722
+ {
5723
+ provide: NG_VALUE_ACCESSOR,
5724
+ useExisting: forwardRef(() => NgOatCheckboxCva),
5725
+ multi: true,
5726
+ },
5727
+ ],
5728
+ }]
5729
+ }], propDecorators: { onHostChange: [{
5730
+ type: HostListener,
5731
+ args: ['change']
5732
+ }], onHostBlur: [{
5733
+ type: HostListener,
5734
+ args: ['focusout']
5735
+ }] } });
5736
+
5737
+ // Forms barrel export
5738
+ /** Convenience array — import both CVA adapters at once. */
5739
+ const NgOatFormsCva = [NgOatValueCva, NgOatCheckboxCva];
5500
5740
 
5501
5741
  // Components barrel export
5502
5742
 
@@ -5517,5 +5757,5 @@ const OAT_VERSION_TOKEN = new InjectionToken('OAT_VERSION', {
5517
5757
  * Generated bundle index. Do not edit.
5518
5758
  */
5519
5759
 
5520
- export { NG_OAT_CHIP_GROUP, NG_OAT_TOGGLE_GROUP, NgOatAccordion, NgOatAlert, NgOatAvatar, NgOatBadge, NgOatBreadcrumb, NgOatButton, NgOatCard, NgOatCardCarousel, NgOatCardFooter, NgOatCardHeader, NgOatCarousel, NgOatCheckbox, NgOatChip, NgOatChipGroup, NgOatChipInput, NgOatDialog, NgOatDialogComponent, NgOatDropdown, NgOatDropdownComponent, NgOatFileUpload, NgOatFormError, NgOatInput, NgOatInputOtp, NgOatMeter, NgOatPagination, NgOatProgress, NgOatRadioGroup, NgOatSearchInput, NgOatSelect, NgOatSeparator, NgOatSidebar, NgOatSidebarComponent, NgOatSkeleton, NgOatSpinner, NgOatSplitButton, NgOatSwitch, NgOatTable, NgOatTabs, NgOatTabsComponent, NgOatTextarea, NgOatThemeRef, NgOatThemeSelector, NgOatThemeSelectorIcon, NgOatToast, NgOatToggle, NgOatToggleGroup, NgOatToolbar, NgOatToolbarRow, NgOatTooltip, NgOatTooltipComponent, OAT_TOKEN_MAP, OAT_VERSION, OAT_VERSION_TOKEN, TOOLTIP_POSITIONER, provideNgOat, provideNgOatTheme };
5760
+ export { NG_OAT_CHECKBOX_HOST, NG_OAT_CHIP_GROUP, NG_OAT_TOGGLE_GROUP, NG_OAT_VALUE_HOST, NgOatAccordion, NgOatAlert, NgOatAvatar, NgOatBadge, NgOatBreadcrumb, NgOatButton, NgOatCard, NgOatCardCarousel, NgOatCardFooter, NgOatCardHeader, NgOatCarousel, NgOatCheckbox, NgOatCheckboxCva, NgOatChip, NgOatChipGroup, NgOatChipInput, NgOatDialog, NgOatDialogComponent, NgOatDropdown, NgOatDropdownComponent, NgOatFileUpload, NgOatFormError, NgOatFormsCva, NgOatInput, NgOatInputOtp, NgOatMeter, NgOatPagination, NgOatProgress, NgOatRadioGroup, NgOatSearchInput, NgOatSelect, NgOatSeparator, NgOatSidebar, NgOatSidebarComponent, NgOatSkeleton, NgOatSpinner, NgOatSplitButton, NgOatSwitch, NgOatTable, NgOatTabs, NgOatTabsComponent, NgOatTextarea, NgOatThemeRef, NgOatThemeSelector, NgOatThemeSelectorIcon, NgOatToast, NgOatToggle, NgOatToggleGroup, NgOatToolbar, NgOatToolbarRow, NgOatTooltip, NgOatTooltipComponent, NgOatValueCva, OAT_TOKEN_MAP, OAT_VERSION, OAT_VERSION_TOKEN, TOOLTIP_POSITIONER, provideNgOat, provideNgOatTheme };
5521
5761
  //# sourceMappingURL=letsprogram-ng-oat.mjs.map