@truenas/ui-components 0.3.8 → 0.3.9

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.
@@ -13563,11 +13563,33 @@ class TnSliderThumbDirective {
13563
13563
  slider; // Will be set by parent slider component
13564
13564
  onTouched = () => { };
13565
13565
  onChangeCallback = (_value) => { };
13566
+ // Pointer is held down on the thumb (set on mousedown/touchstart). Drives the
13567
+ // global move/up listeners.
13568
+ isPointerDown = false;
13569
+ // The pointer has actually moved since going down — i.e. a genuine drag. Only
13570
+ // set once movement occurs (onGlobalMouseMove/onGlobalTouchMove), never on the
13571
+ // initial press, so a plain click still commits through onInput. See onInput.
13566
13572
  isDragging = false;
13573
+ // Last value written by the form. Retained so the parent slider can pick it up
13574
+ // once it links the thumb (ngAfterContentInit) — writeValue can run before the
13575
+ // slider sets `this.slider`.
13576
+ currentValue = 0;
13577
+ // Whether the form has actually written a value to this thumb. Lets the parent
13578
+ // slider distinguish "form wrote 0" from "thumb never bound" so it doesn't
13579
+ // clobber its own form value with this default. See getValue()/hasFormValue().
13580
+ hasWrittenValue = false;
13567
13581
  elementRef = inject((ElementRef));
13582
+ // An accessible name set directly on the <input tnSliderThumb> (e.g.
13583
+ // aria-label="Volume"). Captured up front so the host's [attr.aria-label]
13584
+ // binding can fall back to it instead of clobbering it when the parent slider
13585
+ // doesn't supply one. See ariaLabel()/ariaLabelledby().
13586
+ fallbackAriaLabel = null;
13587
+ fallbackAriaLabelledby = null;
13568
13588
  ngOnInit() {
13569
13589
  // Make the native input visually hidden but still accessible
13570
13590
  const input = this.elementRef.nativeElement;
13591
+ this.fallbackAriaLabel = input.getAttribute('aria-label');
13592
+ this.fallbackAriaLabelledby = input.getAttribute('aria-labelledby');
13571
13593
  input.style.opacity = '0';
13572
13594
  input.style.position = 'absolute';
13573
13595
  input.style.width = '100%';
@@ -13580,10 +13602,46 @@ class TnSliderThumbDirective {
13580
13602
  ngOnDestroy() {
13581
13603
  this.cleanup();
13582
13604
  }
13605
+ /** Value last written by the form, for the slider to read once linked. */
13606
+ getValue() {
13607
+ return this.currentValue;
13608
+ }
13609
+ /**
13610
+ * Whether the form has written a value to this thumb. The slider checks this
13611
+ * before adopting getValue() so an unbound thumb's default 0 never overwrites
13612
+ * a value bound directly on the slider.
13613
+ */
13614
+ hasFormValue() {
13615
+ return this.hasWrittenValue;
13616
+ }
13583
13617
  // ControlValueAccessor implementation
13584
13618
  writeValue(value) {
13585
- if (this.elementRef.nativeElement) {
13586
- this.elementRef.nativeElement.value = value?.toString() || '0';
13619
+ const nextValue = value ?? 0;
13620
+ this.hasWrittenValue = true;
13621
+ // Propagate to the parent slider so its value signal (and thus the thumb
13622
+ // position / track fill) reflects the form value, not just the native input.
13623
+ // When linked, mirror the slider's clamped/stepped result so currentValue and
13624
+ // the native input agree with it; otherwise retain the raw value for the
13625
+ // slider to adopt (and clamp) once it links the thumb in ngAfterContentInit.
13626
+ if (this.slider) {
13627
+ this.slider.updateValue(nextValue);
13628
+ // Note: we don't emit the clamped result back to the form control, so an
13629
+ // out-of-range write (e.g. setValue(143) on a 0–100 slider) leaves the model
13630
+ // holding 143 while the slider renders 100. This mirrors native
13631
+ // <input type="range">, which also doesn't reconcile the bound value.
13632
+ this.currentValue = this.slider.value();
13633
+ // When linked, the host `[value]="slider?.value()"` binding writes the
13634
+ // native input on the next change-detection pass, so a manual write here
13635
+ // would only be re-overwritten — leave it to the binding to keep one source
13636
+ // of truth.
13637
+ }
13638
+ else {
13639
+ this.currentValue = nextValue;
13640
+ // Unlinked: no host binding value yet (slider?.value() is undefined), so set
13641
+ // the native input directly until the slider links and takes over.
13642
+ if (this.elementRef.nativeElement) {
13643
+ this.elementRef.nativeElement.value = this.currentValue.toString();
13644
+ }
13587
13645
  }
13588
13646
  }
13589
13647
  registerOnChange(fn) {
@@ -13599,21 +13657,45 @@ class TnSliderThumbDirective {
13599
13657
  }
13600
13658
  }
13601
13659
  onInput(event) {
13660
+ // Once a drag is underway, the global pointer handlers
13661
+ // (updateValueFromPosition) own value commits; the native range also fires
13662
+ // input here, so skip it to avoid a redundant double emit. A plain click sets
13663
+ // isPointerDown but not isDragging (no movement), so its native input commits
13664
+ // here; keyboard changes set neither and also flow through.
13665
+ if (this.isDragging) {
13666
+ return;
13667
+ }
13602
13668
  const input = event.target;
13603
13669
  const value = parseFloat(input.value);
13670
+ // An empty/garbage value parses to NaN, which clampValue can't sanitize
13671
+ // (Math.max/min with NaN stay NaN). Native range inputs shouldn't produce
13672
+ // this, but guard so a NaN never reaches the form or slider value.
13673
+ if (!Number.isFinite(value)) {
13674
+ return;
13675
+ }
13604
13676
  if (this.slider) {
13605
13677
  this.slider.updateValue(value);
13606
13678
  }
13607
13679
  this.onChangeCallback(value);
13608
13680
  }
13609
13681
  onChange(_event) {
13682
+ this.notifyTouched();
13683
+ }
13684
+ /**
13685
+ * Marks the bound control touched. Calls the thumb's own `onTouched` (for a
13686
+ * thumb-bound control) and forwards to the linked slider (for a
13687
+ * slider-host-bound control) — the thumb is the only interactive element, so
13688
+ * the slider relies on it to ever become touched.
13689
+ */
13690
+ notifyTouched() {
13610
13691
  this.onTouched();
13692
+ this.slider?.markTouched();
13611
13693
  }
13612
13694
  onMouseDown(event) {
13613
13695
  if (this.disabled()) {
13614
13696
  return;
13615
13697
  }
13616
- this.isDragging = true;
13698
+ this.isPointerDown = true;
13617
13699
  this.addGlobalListeners();
13618
13700
  event.stopPropagation(); // Prevent track click
13619
13701
  }
@@ -13621,7 +13703,7 @@ class TnSliderThumbDirective {
13621
13703
  if (this.disabled()) {
13622
13704
  return;
13623
13705
  }
13624
- this.isDragging = true;
13706
+ this.isPointerDown = true;
13625
13707
  this.addGlobalListeners();
13626
13708
  event.stopPropagation(); // Prevent track click
13627
13709
  }
@@ -13638,31 +13720,35 @@ class TnSliderThumbDirective {
13638
13720
  document.removeEventListener('touchend', this.onGlobalTouchEnd);
13639
13721
  }
13640
13722
  onGlobalMouseMove = (event) => {
13641
- if (!this.isDragging || this.disabled()) {
13723
+ if (!this.isPointerDown || this.disabled()) {
13642
13724
  return;
13643
13725
  }
13726
+ this.isDragging = true;
13644
13727
  event.preventDefault();
13645
13728
  this.updateValueFromPosition(event.clientX);
13646
13729
  };
13647
13730
  onGlobalMouseUp = () => {
13648
- if (this.isDragging) {
13731
+ if (this.isPointerDown) {
13732
+ this.isPointerDown = false;
13649
13733
  this.isDragging = false;
13650
- this.onTouched();
13734
+ this.notifyTouched();
13651
13735
  this.removeGlobalListeners();
13652
13736
  }
13653
13737
  };
13654
13738
  onGlobalTouchMove = (event) => {
13655
- if (!this.isDragging || this.disabled()) {
13739
+ if (!this.isPointerDown || this.disabled()) {
13656
13740
  return;
13657
13741
  }
13742
+ this.isDragging = true;
13658
13743
  event.preventDefault();
13659
13744
  const touch = event.touches[0];
13660
13745
  this.updateValueFromPosition(touch.clientX);
13661
13746
  };
13662
13747
  onGlobalTouchEnd = () => {
13663
- if (this.isDragging) {
13748
+ if (this.isPointerDown) {
13749
+ this.isPointerDown = false;
13664
13750
  this.isDragging = false;
13665
- this.onTouched();
13751
+ this.notifyTouched();
13666
13752
  this.removeGlobalListeners();
13667
13753
  }
13668
13754
  };
@@ -13676,12 +13762,58 @@ class TnSliderThumbDirective {
13676
13762
  const maxVal = this.slider.max();
13677
13763
  const newValue = minVal + (percentage * (maxVal - minVal));
13678
13764
  this.slider.updateValue(newValue);
13765
+ // updateValue only moves the visual thumb; commit the (clamped/stepped) value
13766
+ // to the form and native input so dragging actually emits changes — otherwise
13767
+ // only click (native input event) updates the model.
13768
+ this.commit(this.slider.value());
13769
+ }
13770
+ /**
13771
+ * Resolve the accessible name for the range input: the parent slider's
13772
+ * `aria-label`/`aria-labelledby` input when set, otherwise a value placed
13773
+ * directly on the `<input tnSliderThumb>`. Returning the fallback keeps the
13774
+ * host binding from wiping a directly-set label. Null removes the attribute.
13775
+ */
13776
+ ariaLabel() {
13777
+ return this.slider?.ariaLabel() ?? this.fallbackAriaLabel;
13778
+ }
13779
+ ariaLabelledby() {
13780
+ return this.slider?.ariaLabelledby() ?? this.fallbackAriaLabelledby;
13781
+ }
13782
+ /**
13783
+ * Commit a value that originated outside the native input (a thumb drag).
13784
+ * Syncs `currentValue`, the native input, and emits to the form. The slider's
13785
+ * own `onChange` only reaches a slider-bound control, so a thumb-bound control
13786
+ * relies on this to stay in sync. Expects an already clamped/stepped value
13787
+ * (slider.value()).
13788
+ */
13789
+ commit(value) {
13790
+ this.currentValue = value;
13791
+ if (this.elementRef.nativeElement) {
13792
+ this.elementRef.nativeElement.value = value.toString();
13793
+ }
13794
+ this.onChangeCallback(value);
13795
+ }
13796
+ /**
13797
+ * Builds an aria-valuetext when the slider has a label prefix/suffix so screen
13798
+ * readers announce "50 km/h" rather than the bare number. Returns null when
13799
+ * neither is set, letting the native range's valuenow announcement stand.
13800
+ */
13801
+ ariaValueText() {
13802
+ if (!this.slider) {
13803
+ return null;
13804
+ }
13805
+ const prefix = this.slider.labelPrefix();
13806
+ const suffix = this.slider.labelSuffix();
13807
+ if (!prefix && !suffix) {
13808
+ return null;
13809
+ }
13810
+ return `${prefix}${this.slider.value()}${suffix}`;
13679
13811
  }
13680
13812
  cleanup() {
13681
13813
  this.removeGlobalListeners();
13682
13814
  }
13683
13815
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSliderThumbDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
13684
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: TnSliderThumbDirective, isStandalone: true, selector: "input[tnSliderThumb]", host: { attributes: { "type": "range" }, listeners: { "input": "onInput($event)", "change": "onChange($event)", "blur": "onTouched()", "mousedown": "onMouseDown($event)", "touchstart": "onTouchStart($event)" }, properties: { "disabled": "slider?.isDisabled()", "attr.min": "slider?.min()", "attr.max": "slider?.max()", "attr.step": "slider?.step()", "value": "slider?.value()" }, classAttribute: "tn-slider-thumb" }, providers: [
13816
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.0", type: TnSliderThumbDirective, isStandalone: true, selector: "input[tnSliderThumb]", host: { attributes: { "type": "range" }, listeners: { "input": "onInput($event)", "change": "onChange($event)", "blur": "notifyTouched()", "mousedown": "onMouseDown($event)", "touchstart": "onTouchStart($event)" }, properties: { "disabled": "slider?.isDisabled()", "attr.min": "slider?.min()", "attr.max": "slider?.max()", "attr.step": "slider?.step()", "value": "slider?.value()", "attr.aria-valuetext": "ariaValueText()", "attr.aria-label": "ariaLabel()", "attr.aria-labelledby": "ariaLabelledby()" }, classAttribute: "tn-slider-thumb" }, providers: [
13685
13817
  {
13686
13818
  provide: NG_VALUE_ACCESSOR,
13687
13819
  useExisting: forwardRef(() => TnSliderThumbDirective),
@@ -13709,15 +13841,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
13709
13841
  '[attr.max]': 'slider?.max()',
13710
13842
  '[attr.step]': 'slider?.step()',
13711
13843
  '[value]': 'slider?.value()',
13844
+ '[attr.aria-valuetext]': 'ariaValueText()',
13845
+ '[attr.aria-label]': 'ariaLabel()',
13846
+ '[attr.aria-labelledby]': 'ariaLabelledby()',
13712
13847
  '(input)': 'onInput($event)',
13713
13848
  '(change)': 'onChange($event)',
13714
- '(blur)': 'onTouched()',
13849
+ '(blur)': 'notifyTouched()',
13715
13850
  '(mousedown)': 'onMouseDown($event)',
13716
13851
  '(touchstart)': 'onTouchStart($event)'
13717
13852
  }
13718
13853
  }]
13719
13854
  }] });
13720
13855
 
13856
+ /**
13857
+ * Range slider with an optional value label.
13858
+ *
13859
+ * Form binding: both this component and the inner `input[tnSliderThumb]`
13860
+ * directive are `NG_VALUE_ACCESSOR` providers, so a `formControl`/`ngModel` can
13861
+ * be attached to either element. Bind to the `tn-slider` host for the simplest
13862
+ * usage; binding to the inner thumb input also works and the slider adopts that
13863
+ * value on init (see {@link ngAfterContentInit}). Avoid binding to both at once —
13864
+ * pick one element per control to keep a single source of truth.
13865
+ */
13721
13866
  class TnSliderComponent {
13722
13867
  min = input(0, ...(ngDevMode ? [{ debugName: "min" }] : []));
13723
13868
  max = input(100, ...(ngDevMode ? [{ debugName: "max" }] : []));
@@ -13731,9 +13876,18 @@ class TnSliderComponent {
13731
13876
  * is configured via `TN_TEST_ATTR` (default `data-testid`).
13732
13877
  */
13733
13878
  testId = input(undefined, ...(ngDevMode ? [{ debugName: "testId" }] : []));
13879
+ /**
13880
+ * Accessible name forwarded to the inner range input — the focusable element
13881
+ * screen readers actually announce. Set this (or `aria-labelledby`) when the
13882
+ * slider isn't already labelled by a `tn-form-field`/`<label>`, otherwise a
13883
+ * standalone `<tn-slider><input tnSliderThumb></tn-slider>` announces only
13884
+ * "slider". A label set directly on the `input[tnSliderThumb]` is used as a
13885
+ * fallback when neither is provided here.
13886
+ */
13887
+ ariaLabel = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabel" } : {}), alias: 'aria-label' });
13888
+ ariaLabelledby = input(undefined, { ...(ngDevMode ? { debugName: "ariaLabelledby" } : {}), alias: 'aria-labelledby' });
13734
13889
  thumbDirective = contentChild.required(TnSliderThumbDirective);
13735
13890
  sliderContainer = viewChild.required('sliderContainer');
13736
- thumbVisual = viewChild.required('thumbVisual');
13737
13891
  onChange = (_value) => { };
13738
13892
  onTouched = () => { };
13739
13893
  value = signal(0, ...(ngDevMode ? [{ debugName: "value" }] : []));
@@ -13754,13 +13908,6 @@ class TnSliderComponent {
13754
13908
  fillScale = computed(() => {
13755
13909
  return this.fillPercentage() / 100;
13756
13910
  }, ...(ngDevMode ? [{ debugName: "fillScale" }] : []));
13757
- // Computed position for thumb (in pixels from left)
13758
- thumbPosition = computed(() => {
13759
- const containerWidth = this.sliderContainer()?.nativeElement?.offsetWidth || 0;
13760
- const percentage = this.fillPercentage();
13761
- // Center the thumb (20px width, so -10px offset)
13762
- return (containerWidth * percentage / 100) - 10;
13763
- }, ...(ngDevMode ? [{ debugName: "thumbPosition" }] : []));
13764
13911
  // Public signals for label management
13765
13912
  showLabel = this._showLabel.asReadonly();
13766
13913
  labelVisible = this._labelVisible.asReadonly();
@@ -13782,13 +13929,24 @@ class TnSliderComponent {
13782
13929
  }
13783
13930
  });
13784
13931
  }
13785
- ngAfterViewInit() {
13786
- // Initialize thumb directive if present
13932
+ ngAfterContentInit() {
13933
+ // Link the projected thumb directive. Done in AfterContentInit (not
13934
+ // AfterViewInit) so the link exists before the thumb's host bindings settle,
13935
+ // avoiding a null→value flip on its [disabled]/[min]/[value] bindings.
13787
13936
  const thumbDirective = this.thumbDirective();
13788
13937
  if (thumbDirective) {
13789
13938
  thumbDirective.slider = this;
13939
+ // When the form is bound to the inner thumb input, its initial writeValue()
13940
+ // may run before this link exists, so adopt the value the thumb received —
13941
+ // otherwise the slider keeps its default 0 and the thumb/fill render at the
13942
+ // wrong position. Only adopt when the thumb was actually written to, so a
13943
+ // value bound directly on the slider isn't clobbered by the thumb's default.
13944
+ if (thumbDirective.hasFormValue()) {
13945
+ this.value.set(this.clampValue(thumbDirective.getValue()));
13946
+ }
13790
13947
  }
13791
- this.updateThumbPosition();
13948
+ }
13949
+ ngAfterViewInit() {
13792
13950
  // Set up handle interaction listeners if labelType is handle or both
13793
13951
  const currentLabelType = this.labelType();
13794
13952
  if ((currentLabelType === 'handle' || currentLabelType === 'both') && this._showLabel()) {
@@ -13810,6 +13968,15 @@ class TnSliderComponent {
13810
13968
  registerOnTouched(fn) {
13811
13969
  this.onTouched = fn;
13812
13970
  }
13971
+ /**
13972
+ * Marks a slider-host-bound control as touched. The inner thumb is the only
13973
+ * interactive element, so it forwards its touch events here (on blur / pointer
13974
+ * release) — otherwise a control bound to the `tn-slider` host would never
13975
+ * transition to touched and touched-gated validation would never show.
13976
+ */
13977
+ markTouched() {
13978
+ this.onTouched();
13979
+ }
13813
13980
  setDisabledState(isDisabled) {
13814
13981
  this.formDisabled.set(isDisabled);
13815
13982
  }
@@ -13818,7 +13985,6 @@ class TnSliderComponent {
13818
13985
  const clampedValue = this.clampValue(newValue);
13819
13986
  this.value.set(clampedValue);
13820
13987
  this.onChange(clampedValue);
13821
- this.updateThumbPosition();
13822
13988
  }
13823
13989
  enableLabel() {
13824
13990
  this._showLabel.set(true);
@@ -13832,24 +13998,6 @@ class TnSliderComponent {
13832
13998
  getSliderRect() {
13833
13999
  return this.sliderContainer().nativeElement.getBoundingClientRect();
13834
14000
  }
13835
- onTrackClick(event) {
13836
- if (this.isDisabled()) {
13837
- return;
13838
- }
13839
- event.preventDefault();
13840
- const rect = this.getSliderRect();
13841
- const clientX = event instanceof MouseEvent ? event.clientX : event.touches[0].clientX;
13842
- const percentage = (clientX - rect.left) / rect.width;
13843
- const minVal = this.min();
13844
- const maxVal = this.max();
13845
- const newValue = minVal + (percentage * (maxVal - minVal));
13846
- this.updateValue(newValue);
13847
- this.onTouched();
13848
- }
13849
- updateThumbPosition() {
13850
- // Thumb position is now handled by computed signal and template binding
13851
- // No manual DOM manipulation needed
13852
- }
13853
14001
  clampValue(value) {
13854
14002
  const minVal = this.min();
13855
14003
  const maxVal = this.max();
@@ -13907,13 +14055,13 @@ class TnSliderComponent {
13907
14055
  }
13908
14056
  };
13909
14057
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSliderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13910
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnSliderComponent, isStandalone: true, selector: "tn-slider", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, labelPrefix: { classPropertyName: "labelPrefix", publicName: "labelPrefix", isSignal: true, isRequired: false, transformFunction: null }, labelSuffix: { classPropertyName: "labelSuffix", publicName: "labelSuffix", isSignal: true, isRequired: false, transformFunction: null }, labelType: { classPropertyName: "labelType", publicName: "labelType", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.aria-disabled": "isDisabled()" }, classAttribute: "tn-slider" }, providers: [
14058
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: TnSliderComponent, isStandalone: true, selector: "tn-slider", inputs: { min: { classPropertyName: "min", publicName: "min", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, labelPrefix: { classPropertyName: "labelPrefix", publicName: "labelPrefix", isSignal: true, isRequired: false, transformFunction: null }, labelSuffix: { classPropertyName: "labelSuffix", publicName: "labelSuffix", isSignal: true, isRequired: false, transformFunction: null }, labelType: { classPropertyName: "labelType", publicName: "labelType", isSignal: true, isRequired: false, transformFunction: null }, testId: { classPropertyName: "testId", publicName: "testId", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "aria-label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "aria-labelledby", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.aria-disabled": "isDisabled()" }, classAttribute: "tn-slider" }, providers: [
13911
14059
  {
13912
14060
  provide: NG_VALUE_ACCESSOR,
13913
14061
  useExisting: forwardRef(() => TnSliderComponent),
13914
14062
  multi: true
13915
14063
  }
13916
- ], queries: [{ propertyName: "thumbDirective", first: true, predicate: TnSliderThumbDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "sliderContainer", first: true, predicate: ["sliderContainer"], descendants: true, isSignal: true }, { propertyName: "thumbVisual", first: true, predicate: ["thumbVisual"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n #sliderContainer\n class=\"tn-slider-container\"\n tnTestIdType=\"slider\"\n [tnTestId]=\"testId()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.data-disabled]=\"isDisabled()\"\n (mousedown)=\"onTrackClick($event)\"\n (touchstart)=\"onTrackClick($event)\">\n\n <div class=\"tn-slider-track\">\n <div class=\"tn-slider-track-inactive\"></div>\n <div class=\"tn-slider-track-active\">\n <div\n class=\"tn-slider-track-active-fill\"\n [style.transform]=\"'scaleX(' + fillScale() + ')'\">\n </div>\n </div>\n @if ((labelType() === 'track' || labelType() === 'both') && showLabel()) {\n <div class=\"tn-slider-track-label\">\n {{ labelPrefix() }}{{ value() }}{{ labelSuffix() }}\n </div>\n }\n </div>\n\n <div\n #thumbVisual\n class=\"tn-slider-thumb-visual\"\n [style.transform]=\"'translateX(' + thumbPosition() + 'px)'\">\n <div class=\"tn-slider-thumb-knob\"></div>\n @if ((labelType() === 'handle' || labelType() === 'both') && showLabel()) {\n <div\n class=\"tn-slider-thumb-label\"\n [class.visible]=\"labelVisible()\">\n {{ labelPrefix() }}{{ value() }}{{ labelSuffix() }}\n </div>\n }\n </div>\n\n <ng-content />\n</div>\n", styles: [":host{display:block;width:100%;height:48px;position:relative;touch-action:pan-x}.tn-slider-container{position:relative;width:100%;height:100%;display:flex;align-items:center;cursor:pointer}.tn-slider-container[data-disabled=true]{cursor:not-allowed;opacity:.6}.tn-slider-track{position:relative;width:100%;height:4px}.tn-slider-track-inactive{position:absolute;top:0;left:0;width:100%;height:100%;background:var(--tn-lines, #e0e0e0);border-radius:2px}.tn-slider-track-active{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;border-radius:2px}.tn-slider-track-active-fill{position:absolute;top:0;left:0;width:100%;height:100%;background:var(--tn-primary, #007bff);border-radius:2px;transform-origin:left center;transition:transform .1s ease-out}:host ::ng-deep .tn-slider-thumb{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;margin:0;padding:0;cursor:pointer;z-index:2;-webkit-appearance:none;appearance:none;background:none;border:none;outline:none}:host ::ng-deep .tn-slider-thumb:disabled{cursor:not-allowed}:host ::ng-deep .tn-slider-thumb:focus{outline:none}:host ::ng-deep .tn-slider-thumb:focus-visible{outline:none}:host ::ng-deep .tn-slider-thumb:focus-visible+.tn-slider-visual-thumb{outline:2px solid var(--tn-primary, #007bff);outline-offset:2px}.tn-slider-thumb-visual{position:absolute;top:50%;left:0;pointer-events:none;z-index:3;transition:transform .1s ease-out}.tn-slider-thumb-knob{width:20px;height:24px;background:var(--tn-primary, #007bff);border:2px solid var(--tn-bg1, white);border-radius:4px;box-shadow:0 2px 4px #0003;transition:box-shadow .15s ease;transform:translateY(-50%)}.tn-slider-container:hover .tn-slider-thumb-knob{box-shadow:0 4px 8px #0000004d}.tn-slider-container[data-disabled=true] .tn-slider-thumb-knob{background:var(--tn-fg2, #999);box-shadow:0 1px 2px #0000001a}.tn-slider-thumb-label{position:absolute;bottom:calc(100% + 16px);left:50%;transform:translate(-50%) translateY(-50%);padding:8px 12px;background:var(--tn-primary, #007bff);color:var(--tn-primary-txt, white);border-radius:6px;font-size:12px;font-weight:500;line-height:1.2;white-space:nowrap;opacity:0;pointer-events:none;-webkit-user-select:none;user-select:none;transition:opacity .15s ease;z-index:4;box-shadow:0 2px 8px #00000026}.tn-slider-thumb-label:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid var(--tn-primary, #007bff)}.tn-slider-thumb-label.visible{opacity:1}.tn-slider-track-label{position:absolute;top:-28px;right:0;padding:4px 0;background:transparent;color:var(--tn-fg1, #000);font-size:12px;font-weight:500;line-height:1.2;white-space:nowrap;-webkit-user-select:none;user-select:none;z-index:2}@media(prefers-reduced-motion:reduce){.tn-slider-track-active-fill,.tn-slider-thumb-visual,.tn-slider-thumb-knob,.tn-slider-thumb-label{transition:none}}@media(prefers-contrast:high){.tn-slider-track-inactive{border:1px solid var(--tn-fg1, #000)}.tn-slider-thumb-knob{border-width:3px;border-color:var(--tn-fg1, #000)}}\n"], dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "directive", type: TnTestIdDirective, selector: "[tnTestId]", inputs: ["tnTestId", "tnTestIdType"] }] });
14064
+ ], queries: [{ propertyName: "thumbDirective", first: true, predicate: TnSliderThumbDirective, descendants: true, isSignal: true }], viewQueries: [{ propertyName: "sliderContainer", first: true, predicate: ["sliderContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<!--\n Pointer interaction (click-to-position and press-drag, anywhere on the track)\n is handled by the projected native range input, which overlays the whole\n container (see TnSliderThumbDirective): a click jumps the thumb and fires\n `input` \u2192 onInput; a press-and-move runs the directive's global drag handlers.\n No container-level click handler is needed \u2014 and one wouldn't fire anyway, as\n the overlay calls stopPropagation() on its own pointer events.\n-->\n<div\n #sliderContainer\n class=\"tn-slider-container\"\n tnTestIdType=\"slider\"\n [tnTestId]=\"testId()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.data-disabled]=\"isDisabled()\">\n\n <div class=\"tn-slider-track\">\n <div class=\"tn-slider-track-inactive\"></div>\n <div class=\"tn-slider-track-active\">\n <div\n class=\"tn-slider-track-active-fill\"\n [style.transform]=\"'scaleX(' + fillScale() + ')'\">\n </div>\n </div>\n @if ((labelType() === 'track' || labelType() === 'both') && showLabel()) {\n <div class=\"tn-slider-track-label\">\n {{ labelPrefix() }}{{ value() }}{{ labelSuffix() }}\n </div>\n }\n </div>\n\n <div\n class=\"tn-slider-thumb-visual\"\n [style.left.%]=\"fillPercentage()\">\n <div class=\"tn-slider-thumb-knob\"></div>\n @if ((labelType() === 'handle' || labelType() === 'both') && showLabel()) {\n <div\n class=\"tn-slider-thumb-label\"\n [class.visible]=\"labelVisible()\">\n {{ labelPrefix() }}{{ value() }}{{ labelSuffix() }}\n </div>\n }\n </div>\n\n <ng-content />\n</div>\n", styles: [":host{display:block;width:100%;height:48px;position:relative;touch-action:pan-x}.tn-slider-container{position:relative;width:100%;height:100%;display:flex;align-items:center;cursor:pointer}.tn-slider-container[data-disabled=true]{cursor:not-allowed;opacity:.6}.tn-slider-track{position:relative;width:100%;height:4px}.tn-slider-track-inactive{position:absolute;top:0;left:0;width:100%;height:100%;background:var(--tn-lines, #e0e0e0);border-radius:2px}.tn-slider-track-active{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;border-radius:2px}.tn-slider-track-active-fill{position:absolute;top:0;left:0;width:100%;height:100%;background:var(--tn-primary, #007bff);border-radius:2px;transform-origin:left center;transition:transform .1s ease-out}:host ::ng-deep .tn-slider-thumb{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;margin:0;padding:0;cursor:pointer;z-index:2;-webkit-appearance:none;appearance:none;background:none;border:none;outline:none}:host ::ng-deep .tn-slider-thumb:disabled{cursor:not-allowed}:host ::ng-deep .tn-slider-thumb:focus{outline:none}:host ::ng-deep .tn-slider-thumb:focus-visible{outline:none}:host ::ng-deep .tn-slider-container:has(.tn-slider-thumb:focus-visible) .tn-slider-thumb-knob{outline:2px solid var(--tn-primary, #007bff);outline-offset:2px}.tn-slider-thumb-visual{position:absolute;top:50%;left:0;margin-left:-10px;pointer-events:none;z-index:3;transition:left .1s ease-out}.tn-slider-thumb-knob{width:20px;height:24px;background:var(--tn-primary, #007bff);border:2px solid var(--tn-bg1, white);border-radius:4px;box-shadow:0 2px 4px #0003;transition:box-shadow .15s ease;transform:translateY(-50%)}.tn-slider-container:hover .tn-slider-thumb-knob{box-shadow:0 4px 8px #0000004d}.tn-slider-container[data-disabled=true] .tn-slider-thumb-knob{background:var(--tn-fg2, #999);box-shadow:0 1px 2px #0000001a}.tn-slider-thumb-label{position:absolute;bottom:calc(100% + 16px);left:50%;transform:translate(-50%) translateY(-50%);padding:8px 12px;background:var(--tn-primary, #007bff);color:var(--tn-primary-txt, white);border-radius:6px;font-size:12px;font-weight:500;line-height:1.2;white-space:nowrap;opacity:0;pointer-events:none;-webkit-user-select:none;user-select:none;transition:opacity .15s ease;z-index:4;box-shadow:0 2px 8px #00000026}.tn-slider-thumb-label:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid var(--tn-primary, #007bff)}.tn-slider-thumb-label.visible{opacity:1}.tn-slider-track-label{position:absolute;top:-28px;right:0;padding:4px 0;background:transparent;color:var(--tn-fg1, #000);font-size:12px;font-weight:500;line-height:1.2;white-space:nowrap;-webkit-user-select:none;user-select:none;z-index:2}@media(prefers-reduced-motion:reduce){.tn-slider-track-active-fill,.tn-slider-thumb-visual,.tn-slider-thumb-knob,.tn-slider-thumb-label{transition:none}}@media(prefers-contrast:high){.tn-slider-track-inactive{border:1px solid var(--tn-fg1, #000)}.tn-slider-thumb-knob{border-width:3px;border-color:var(--tn-fg1, #000)}}\n"], dependencies: [{ kind: "ngmodule", type: A11yModule }, { kind: "directive", type: TnTestIdDirective, selector: "[tnTestId]", inputs: ["tnTestId", "tnTestIdType"] }] });
13917
14065
  }
13918
14066
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: TnSliderComponent, decorators: [{
13919
14067
  type: Component,
@@ -13926,8 +14074,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
13926
14074
  ], host: {
13927
14075
  'class': 'tn-slider',
13928
14076
  '[attr.aria-disabled]': 'isDisabled()'
13929
- }, template: "<div\n #sliderContainer\n class=\"tn-slider-container\"\n tnTestIdType=\"slider\"\n [tnTestId]=\"testId()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.data-disabled]=\"isDisabled()\"\n (mousedown)=\"onTrackClick($event)\"\n (touchstart)=\"onTrackClick($event)\">\n\n <div class=\"tn-slider-track\">\n <div class=\"tn-slider-track-inactive\"></div>\n <div class=\"tn-slider-track-active\">\n <div\n class=\"tn-slider-track-active-fill\"\n [style.transform]=\"'scaleX(' + fillScale() + ')'\">\n </div>\n </div>\n @if ((labelType() === 'track' || labelType() === 'both') && showLabel()) {\n <div class=\"tn-slider-track-label\">\n {{ labelPrefix() }}{{ value() }}{{ labelSuffix() }}\n </div>\n }\n </div>\n\n <div\n #thumbVisual\n class=\"tn-slider-thumb-visual\"\n [style.transform]=\"'translateX(' + thumbPosition() + 'px)'\">\n <div class=\"tn-slider-thumb-knob\"></div>\n @if ((labelType() === 'handle' || labelType() === 'both') && showLabel()) {\n <div\n class=\"tn-slider-thumb-label\"\n [class.visible]=\"labelVisible()\">\n {{ labelPrefix() }}{{ value() }}{{ labelSuffix() }}\n </div>\n }\n </div>\n\n <ng-content />\n</div>\n", styles: [":host{display:block;width:100%;height:48px;position:relative;touch-action:pan-x}.tn-slider-container{position:relative;width:100%;height:100%;display:flex;align-items:center;cursor:pointer}.tn-slider-container[data-disabled=true]{cursor:not-allowed;opacity:.6}.tn-slider-track{position:relative;width:100%;height:4px}.tn-slider-track-inactive{position:absolute;top:0;left:0;width:100%;height:100%;background:var(--tn-lines, #e0e0e0);border-radius:2px}.tn-slider-track-active{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;border-radius:2px}.tn-slider-track-active-fill{position:absolute;top:0;left:0;width:100%;height:100%;background:var(--tn-primary, #007bff);border-radius:2px;transform-origin:left center;transition:transform .1s ease-out}:host ::ng-deep .tn-slider-thumb{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;margin:0;padding:0;cursor:pointer;z-index:2;-webkit-appearance:none;appearance:none;background:none;border:none;outline:none}:host ::ng-deep .tn-slider-thumb:disabled{cursor:not-allowed}:host ::ng-deep .tn-slider-thumb:focus{outline:none}:host ::ng-deep .tn-slider-thumb:focus-visible{outline:none}:host ::ng-deep .tn-slider-thumb:focus-visible+.tn-slider-visual-thumb{outline:2px solid var(--tn-primary, #007bff);outline-offset:2px}.tn-slider-thumb-visual{position:absolute;top:50%;left:0;pointer-events:none;z-index:3;transition:transform .1s ease-out}.tn-slider-thumb-knob{width:20px;height:24px;background:var(--tn-primary, #007bff);border:2px solid var(--tn-bg1, white);border-radius:4px;box-shadow:0 2px 4px #0003;transition:box-shadow .15s ease;transform:translateY(-50%)}.tn-slider-container:hover .tn-slider-thumb-knob{box-shadow:0 4px 8px #0000004d}.tn-slider-container[data-disabled=true] .tn-slider-thumb-knob{background:var(--tn-fg2, #999);box-shadow:0 1px 2px #0000001a}.tn-slider-thumb-label{position:absolute;bottom:calc(100% + 16px);left:50%;transform:translate(-50%) translateY(-50%);padding:8px 12px;background:var(--tn-primary, #007bff);color:var(--tn-primary-txt, white);border-radius:6px;font-size:12px;font-weight:500;line-height:1.2;white-space:nowrap;opacity:0;pointer-events:none;-webkit-user-select:none;user-select:none;transition:opacity .15s ease;z-index:4;box-shadow:0 2px 8px #00000026}.tn-slider-thumb-label:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid var(--tn-primary, #007bff)}.tn-slider-thumb-label.visible{opacity:1}.tn-slider-track-label{position:absolute;top:-28px;right:0;padding:4px 0;background:transparent;color:var(--tn-fg1, #000);font-size:12px;font-weight:500;line-height:1.2;white-space:nowrap;-webkit-user-select:none;user-select:none;z-index:2}@media(prefers-reduced-motion:reduce){.tn-slider-track-active-fill,.tn-slider-thumb-visual,.tn-slider-thumb-knob,.tn-slider-thumb-label{transition:none}}@media(prefers-contrast:high){.tn-slider-track-inactive{border:1px solid var(--tn-fg1, #000)}.tn-slider-thumb-knob{border-width:3px;border-color:var(--tn-fg1, #000)}}\n"] }]
13930
- }], ctorParameters: () => [], propDecorators: { min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], labelPrefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPrefix", required: false }] }], labelSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelSuffix", required: false }] }], labelType: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelType", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], thumbDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TnSliderThumbDirective), { isSignal: true }] }], sliderContainer: [{ type: i0.ViewChild, args: ['sliderContainer', { isSignal: true }] }], thumbVisual: [{ type: i0.ViewChild, args: ['thumbVisual', { isSignal: true }] }] } });
14077
+ }, template: "<!--\n Pointer interaction (click-to-position and press-drag, anywhere on the track)\n is handled by the projected native range input, which overlays the whole\n container (see TnSliderThumbDirective): a click jumps the thumb and fires\n `input` \u2192 onInput; a press-and-move runs the directive's global drag handlers.\n No container-level click handler is needed \u2014 and one wouldn't fire anyway, as\n the overlay calls stopPropagation() on its own pointer events.\n-->\n<div\n #sliderContainer\n class=\"tn-slider-container\"\n tnTestIdType=\"slider\"\n [tnTestId]=\"testId()\"\n [attr.aria-disabled]=\"isDisabled()\"\n [attr.data-disabled]=\"isDisabled()\">\n\n <div class=\"tn-slider-track\">\n <div class=\"tn-slider-track-inactive\"></div>\n <div class=\"tn-slider-track-active\">\n <div\n class=\"tn-slider-track-active-fill\"\n [style.transform]=\"'scaleX(' + fillScale() + ')'\">\n </div>\n </div>\n @if ((labelType() === 'track' || labelType() === 'both') && showLabel()) {\n <div class=\"tn-slider-track-label\">\n {{ labelPrefix() }}{{ value() }}{{ labelSuffix() }}\n </div>\n }\n </div>\n\n <div\n class=\"tn-slider-thumb-visual\"\n [style.left.%]=\"fillPercentage()\">\n <div class=\"tn-slider-thumb-knob\"></div>\n @if ((labelType() === 'handle' || labelType() === 'both') && showLabel()) {\n <div\n class=\"tn-slider-thumb-label\"\n [class.visible]=\"labelVisible()\">\n {{ labelPrefix() }}{{ value() }}{{ labelSuffix() }}\n </div>\n }\n </div>\n\n <ng-content />\n</div>\n", styles: [":host{display:block;width:100%;height:48px;position:relative;touch-action:pan-x}.tn-slider-container{position:relative;width:100%;height:100%;display:flex;align-items:center;cursor:pointer}.tn-slider-container[data-disabled=true]{cursor:not-allowed;opacity:.6}.tn-slider-track{position:relative;width:100%;height:4px}.tn-slider-track-inactive{position:absolute;top:0;left:0;width:100%;height:100%;background:var(--tn-lines, #e0e0e0);border-radius:2px}.tn-slider-track-active{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;border-radius:2px}.tn-slider-track-active-fill{position:absolute;top:0;left:0;width:100%;height:100%;background:var(--tn-primary, #007bff);border-radius:2px;transform-origin:left center;transition:transform .1s ease-out}:host ::ng-deep .tn-slider-thumb{position:absolute;top:0;left:0;width:100%;height:100%;opacity:0;margin:0;padding:0;cursor:pointer;z-index:2;-webkit-appearance:none;appearance:none;background:none;border:none;outline:none}:host ::ng-deep .tn-slider-thumb:disabled{cursor:not-allowed}:host ::ng-deep .tn-slider-thumb:focus{outline:none}:host ::ng-deep .tn-slider-thumb:focus-visible{outline:none}:host ::ng-deep .tn-slider-container:has(.tn-slider-thumb:focus-visible) .tn-slider-thumb-knob{outline:2px solid var(--tn-primary, #007bff);outline-offset:2px}.tn-slider-thumb-visual{position:absolute;top:50%;left:0;margin-left:-10px;pointer-events:none;z-index:3;transition:left .1s ease-out}.tn-slider-thumb-knob{width:20px;height:24px;background:var(--tn-primary, #007bff);border:2px solid var(--tn-bg1, white);border-radius:4px;box-shadow:0 2px 4px #0003;transition:box-shadow .15s ease;transform:translateY(-50%)}.tn-slider-container:hover .tn-slider-thumb-knob{box-shadow:0 4px 8px #0000004d}.tn-slider-container[data-disabled=true] .tn-slider-thumb-knob{background:var(--tn-fg2, #999);box-shadow:0 1px 2px #0000001a}.tn-slider-thumb-label{position:absolute;bottom:calc(100% + 16px);left:50%;transform:translate(-50%) translateY(-50%);padding:8px 12px;background:var(--tn-primary, #007bff);color:var(--tn-primary-txt, white);border-radius:6px;font-size:12px;font-weight:500;line-height:1.2;white-space:nowrap;opacity:0;pointer-events:none;-webkit-user-select:none;user-select:none;transition:opacity .15s ease;z-index:4;box-shadow:0 2px 8px #00000026}.tn-slider-thumb-label:after{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);width:0;height:0;border-left:8px solid transparent;border-right:8px solid transparent;border-top:8px solid var(--tn-primary, #007bff)}.tn-slider-thumb-label.visible{opacity:1}.tn-slider-track-label{position:absolute;top:-28px;right:0;padding:4px 0;background:transparent;color:var(--tn-fg1, #000);font-size:12px;font-weight:500;line-height:1.2;white-space:nowrap;-webkit-user-select:none;user-select:none;z-index:2}@media(prefers-reduced-motion:reduce){.tn-slider-track-active-fill,.tn-slider-thumb-visual,.tn-slider-thumb-knob,.tn-slider-thumb-label{transition:none}}@media(prefers-contrast:high){.tn-slider-track-inactive{border:1px solid var(--tn-fg1, #000)}.tn-slider-thumb-knob{border-width:3px;border-color:var(--tn-fg1, #000)}}\n"] }]
14078
+ }], ctorParameters: () => [], propDecorators: { min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], step: [{ type: i0.Input, args: [{ isSignal: true, alias: "step", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], labelPrefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelPrefix", required: false }] }], labelSuffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelSuffix", required: false }] }], labelType: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelType", required: false }] }], testId: [{ type: i0.Input, args: [{ isSignal: true, alias: "testId", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-label", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "aria-labelledby", required: false }] }], thumbDirective: [{ type: i0.ContentChild, args: [i0.forwardRef(() => TnSliderThumbDirective), { isSignal: true }] }], sliderContainer: [{ type: i0.ViewChild, args: ['sliderContainer', { isSignal: true }] }] } });
13931
14079
 
13932
14080
  class TnSliderWithLabelDirective {
13933
14081
  enabled = input(true, { ...(ngDevMode ? { debugName: "enabled" } : {}), alias: 'tnSliderWithLabel' });