ng-blatui 1.20.0 → 1.22.0

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.
@@ -77,7 +77,7 @@ const SIZES$3 = {
77
77
  default: 'px-2 py-0.5 text-xs',
78
78
  lg: 'px-3 py-1 text-sm [&>svg]:size-3.5',
79
79
  };
80
- const VARIANTS = {
80
+ const VARIANTS$1 = {
81
81
  default: 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90',
82
82
  secondary: 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',
83
83
  destructive: 'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
@@ -113,16 +113,16 @@ const TONES$2 = {
113
113
  function brandClass(variant) {
114
114
  switch (variant) {
115
115
  case 'secondary': {
116
- return VARIANTS.secondary;
116
+ return VARIANTS$1.secondary;
117
117
  }
118
118
  case 'destructive': {
119
- return VARIANTS.destructive;
119
+ return VARIANTS$1.destructive;
120
120
  }
121
121
  case 'outline': {
122
- return VARIANTS.outline;
122
+ return VARIANTS$1.outline;
123
123
  }
124
124
  default: {
125
- return VARIANTS.default;
125
+ return VARIANTS$1.default;
126
126
  }
127
127
  }
128
128
  }
@@ -5673,6 +5673,457 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
5673
5673
  }]
5674
5674
  }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
5675
5675
 
5676
+ const VARIANTS = {
5677
+ primary: 'bg-primary text-primary-foreground hover:bg-primary/90',
5678
+ subtle: 'bg-card text-foreground hover:bg-accent hover:text-accent-foreground border',
5679
+ };
5680
+ /**
5681
+ * A floating "scroll to top" button that reveals itself once the page scrolls past
5682
+ * `threshold` px. SSR-safe — the scroll position is only read in the browser.
5683
+ */
5684
+ class BuiBackToTop {
5685
+ threshold = input(300, /* @ts-ignore */
5686
+ ...(ngDevMode ? [{ debugName: "threshold" }] : /* istanbul ignore next */ []));
5687
+ variant = input('primary', /* @ts-ignore */
5688
+ ...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
5689
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
5690
+ shown = signal(false, /* @ts-ignore */
5691
+ ...(ngDevMode ? [{ debugName: "shown" }] : /* istanbul ignore next */ []));
5692
+ variantClass = computed(() => VARIANTS[this.variant()], /* @ts-ignore */
5693
+ ...(ngDevMode ? [{ debugName: "variantClass" }] : /* istanbul ignore next */ []));
5694
+ computedClass = computed(() => cn('fixed end-6 bottom-6 z-40 block', this.userClass()), /* @ts-ignore */
5695
+ ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
5696
+ constructor() {
5697
+ afterNextRender(() => {
5698
+ this.onScroll();
5699
+ });
5700
+ }
5701
+ onScroll() {
5702
+ this.shown.set(globalThis.scrollY > this.threshold());
5703
+ }
5704
+ toTop() {
5705
+ globalThis.scrollTo({ top: 0, behavior: 'smooth' });
5706
+ }
5707
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiBackToTop, deps: [], target: i0.ɵɵFactoryTarget.Component });
5708
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: BuiBackToTop, isStandalone: true, selector: "bui-back-to-top", inputs: { threshold: { classPropertyName: "threshold", publicName: "threshold", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "back-to-top" }, listeners: { "window:scroll": "onScroll()" }, properties: { "hidden": "!shown()", "class": "computedClass()" } }, ngImport: i0, template: `
5709
+ <button
5710
+ type="button"
5711
+ aria-label="Back to top"
5712
+ class="inline-flex size-10 items-center justify-center rounded-full shadow-md transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50"
5713
+ [class]="variantClass()"
5714
+ (click)="toTop()"
5715
+ >
5716
+ <svg
5717
+ viewBox="0 0 24 24"
5718
+ fill="none"
5719
+ stroke="currentColor"
5720
+ stroke-width="2"
5721
+ stroke-linecap="round"
5722
+ stroke-linejoin="round"
5723
+ aria-hidden="true"
5724
+ class="size-5"
5725
+ >
5726
+ <path d="m5 12 7-7 7 7" />
5727
+ <path d="M12 19V5" />
5728
+ </svg>
5729
+ </button>
5730
+ `, isInline: true });
5731
+ }
5732
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiBackToTop, decorators: [{
5733
+ type: Component,
5734
+ args: [{
5735
+ selector: 'bui-back-to-top',
5736
+ host: {
5737
+ 'data-slot': 'back-to-top',
5738
+ '[hidden]': '!shown()',
5739
+ '[class]': 'computedClass()',
5740
+ '(window:scroll)': 'onScroll()',
5741
+ },
5742
+ template: `
5743
+ <button
5744
+ type="button"
5745
+ aria-label="Back to top"
5746
+ class="inline-flex size-10 items-center justify-center rounded-full shadow-md transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50"
5747
+ [class]="variantClass()"
5748
+ (click)="toTop()"
5749
+ >
5750
+ <svg
5751
+ viewBox="0 0 24 24"
5752
+ fill="none"
5753
+ stroke="currentColor"
5754
+ stroke-width="2"
5755
+ stroke-linecap="round"
5756
+ stroke-linejoin="round"
5757
+ aria-hidden="true"
5758
+ class="size-5"
5759
+ >
5760
+ <path d="m5 12 7-7 7 7" />
5761
+ <path d="M12 19V5" />
5762
+ </svg>
5763
+ </button>
5764
+ `,
5765
+ }]
5766
+ }], ctorParameters: () => [], propDecorators: { threshold: [{ type: i0.Input, args: [{ isSignal: true, alias: "threshold", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
5767
+
5768
+ /**
5769
+ * A filterable combobox: a text input (`role="combobox"`, `aria-autocomplete="list"`) over a
5770
+ * filtered listbox, using the `aria-activedescendant` pattern. Full keyboard + outside-click.
5771
+ */
5772
+ class BuiCombobox {
5773
+ value = model('', /* @ts-ignore */
5774
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
5775
+ options = input([], /* @ts-ignore */
5776
+ ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
5777
+ placeholder = input('Search…', /* @ts-ignore */
5778
+ ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
5779
+ disabled = input(false, /* @ts-ignore */
5780
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
5781
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
5782
+ listId = inject(_IdGenerator).getId('bui-combobox-');
5783
+ host = inject(ElementRef);
5784
+ open = signal(false, /* @ts-ignore */
5785
+ ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
5786
+ active = signal(0, /* @ts-ignore */
5787
+ ...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
5788
+ query = signal('', /* @ts-ignore */
5789
+ ...(ngDevMode ? [{ debugName: "query" }] : /* istanbul ignore next */ []));
5790
+ selectedLabel = computed(() => this.options().find((option) => option.value === this.value())?.label ?? '', /* @ts-ignore */
5791
+ ...(ngDevMode ? [{ debugName: "selectedLabel" }] : /* istanbul ignore next */ []));
5792
+ display = computed(() => (this.open() ? this.query() : this.selectedLabel()), /* @ts-ignore */
5793
+ ...(ngDevMode ? [{ debugName: "display" }] : /* istanbul ignore next */ []));
5794
+ filtered = computed(() => {
5795
+ const query = this.query().trim().toLowerCase();
5796
+ return query === ''
5797
+ ? this.options()
5798
+ : this.options().filter((option) => option.label.toLowerCase().includes(query));
5799
+ }, /* @ts-ignore */
5800
+ ...(ngDevMode ? [{ debugName: "filtered" }] : /* istanbul ignore next */ []));
5801
+ computedClass = computed(() => cn('relative block', this.userClass()), /* @ts-ignore */
5802
+ ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
5803
+ onInput(event) {
5804
+ this.query.set(event.target.value);
5805
+ this.active.set(0);
5806
+ this.open.set(true);
5807
+ }
5808
+ openList() {
5809
+ this.query.set('');
5810
+ this.active.set(0);
5811
+ this.open.set(true);
5812
+ }
5813
+ select(option) {
5814
+ this.value.set(option.value);
5815
+ this.query.set('');
5816
+ this.open.set(false);
5817
+ }
5818
+ onKeydown(event) {
5819
+ if (this.disabled()) {
5820
+ return;
5821
+ }
5822
+ if (event.key === 'Escape') {
5823
+ this.open.set(false);
5824
+ return;
5825
+ }
5826
+ if (!this.open() && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
5827
+ event.preventDefault();
5828
+ this.openList();
5829
+ return;
5830
+ }
5831
+ const items = this.filtered();
5832
+ switch (event.key) {
5833
+ case 'ArrowDown': {
5834
+ event.preventDefault();
5835
+ this.active.set(Math.min(items.length - 1, this.active() + 1));
5836
+ break;
5837
+ }
5838
+ case 'ArrowUp': {
5839
+ event.preventDefault();
5840
+ this.active.set(Math.max(0, this.active() - 1));
5841
+ break;
5842
+ }
5843
+ case 'Enter': {
5844
+ if (this.open() && items.length > 0) {
5845
+ event.preventDefault();
5846
+ this.select(items[this.active()]);
5847
+ }
5848
+ break;
5849
+ }
5850
+ default: {
5851
+ break;
5852
+ }
5853
+ }
5854
+ }
5855
+ onDocumentClick(event) {
5856
+ if (!(this.open() && !this.host.nativeElement.contains(event.target))) {
5857
+ return;
5858
+ }
5859
+ this.open.set(false);
5860
+ this.query.set('');
5861
+ }
5862
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiCombobox, deps: [], target: i0.ɵɵFactoryTarget.Component });
5863
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiCombobox, isStandalone: true, selector: "bui-combobox", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { attributes: { "data-slot": "combobox" }, listeners: { "document:click": "onDocumentClick($event)" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
5864
+ <input
5865
+ type="text"
5866
+ role="combobox"
5867
+ aria-autocomplete="list"
5868
+ [attr.aria-expanded]="open()"
5869
+ [attr.aria-controls]="listId"
5870
+ [attr.aria-activedescendant]="open() ? listId + '-' + active() : null"
5871
+ [value]="display()"
5872
+ [placeholder]="placeholder()"
5873
+ [disabled]="disabled()"
5874
+ class="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50"
5875
+ (input)="onInput($event)"
5876
+ (focus)="openList()"
5877
+ (keydown)="onKeydown($event)"
5878
+ />
5879
+ @if (open() && filtered().length > 0) {
5880
+ <ul
5881
+ [id]="listId"
5882
+ role="listbox"
5883
+ class="absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md"
5884
+ >
5885
+ @for (option of filtered(); track option.value; let i = $index) {
5886
+ <li
5887
+ [id]="listId + '-' + i"
5888
+ role="option"
5889
+ [attr.aria-selected]="option.value === value()"
5890
+ class="relative flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none"
5891
+ [class]="i === active() ? 'bg-accent text-accent-foreground' : ''"
5892
+ (click)="select(option)"
5893
+ (mouseenter)="active.set(i)"
5894
+ >
5895
+ {{ option.label }}
5896
+ </li>
5897
+ }
5898
+ </ul>
5899
+ }
5900
+ `, isInline: true });
5901
+ }
5902
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiCombobox, decorators: [{
5903
+ type: Component,
5904
+ args: [{
5905
+ selector: 'bui-combobox',
5906
+ host: {
5907
+ 'data-slot': 'combobox',
5908
+ '[class]': 'computedClass()',
5909
+ '(document:click)': 'onDocumentClick($event)',
5910
+ },
5911
+ template: `
5912
+ <input
5913
+ type="text"
5914
+ role="combobox"
5915
+ aria-autocomplete="list"
5916
+ [attr.aria-expanded]="open()"
5917
+ [attr.aria-controls]="listId"
5918
+ [attr.aria-activedescendant]="open() ? listId + '-' + active() : null"
5919
+ [value]="display()"
5920
+ [placeholder]="placeholder()"
5921
+ [disabled]="disabled()"
5922
+ class="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50"
5923
+ (input)="onInput($event)"
5924
+ (focus)="openList()"
5925
+ (keydown)="onKeydown($event)"
5926
+ />
5927
+ @if (open() && filtered().length > 0) {
5928
+ <ul
5929
+ [id]="listId"
5930
+ role="listbox"
5931
+ class="absolute z-50 mt-1 max-h-60 w-full overflow-auto rounded-md border bg-popover p-1 text-popover-foreground shadow-md"
5932
+ >
5933
+ @for (option of filtered(); track option.value; let i = $index) {
5934
+ <li
5935
+ [id]="listId + '-' + i"
5936
+ role="option"
5937
+ [attr.aria-selected]="option.value === value()"
5938
+ class="relative flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none"
5939
+ [class]="i === active() ? 'bg-accent text-accent-foreground' : ''"
5940
+ (click)="select(option)"
5941
+ (mouseenter)="active.set(i)"
5942
+ >
5943
+ {{ option.label }}
5944
+ </li>
5945
+ }
5946
+ </ul>
5947
+ }
5948
+ `,
5949
+ }]
5950
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
5951
+
5952
+ /** A live countdown to a target time (`role="timer"`). SSR-safe — ticks only in the browser. */
5953
+ class BuiCountdown {
5954
+ to = input.required(/* @ts-ignore */
5955
+ ...(ngDevMode ? [{ debugName: "to" }] : /* istanbul ignore next */ []));
5956
+ expired = input('Expired', /* @ts-ignore */
5957
+ ...(ngDevMode ? [{ debugName: "expired" }] : /* istanbul ignore next */ []));
5958
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
5959
+ now = signal(Date.now(), /* @ts-ignore */
5960
+ ...(ngDevMode ? [{ debugName: "now" }] : /* istanbul ignore next */ []));
5961
+ timer;
5962
+ targetMs = computed(() => new Date(this.to()).getTime(), /* @ts-ignore */
5963
+ ...(ngDevMode ? [{ debugName: "targetMs" }] : /* istanbul ignore next */ []));
5964
+ diff = computed(() => Math.max(0, this.targetMs() - this.now()), /* @ts-ignore */
5965
+ ...(ngDevMode ? [{ debugName: "diff" }] : /* istanbul ignore next */ []));
5966
+ done = computed(() => this.diff() <= 0, /* @ts-ignore */
5967
+ ...(ngDevMode ? [{ debugName: "done" }] : /* istanbul ignore next */ []));
5968
+ units = computed(() => {
5969
+ const diff = this.diff();
5970
+ const pad = (value) => String(value).padStart(2, '0');
5971
+ return [
5972
+ { key: 'days', label: 'Days', value: pad(Math.floor(diff / 86_400_000)) },
5973
+ { key: 'hours', label: 'Hrs', value: pad(Math.floor(diff / 3_600_000) % 24) },
5974
+ { key: 'minutes', label: 'Min', value: pad(Math.floor(diff / 60_000) % 60) },
5975
+ { key: 'seconds', label: 'Sec', value: pad(Math.floor(diff / 1000) % 60) },
5976
+ ];
5977
+ }, /* @ts-ignore */
5978
+ ...(ngDevMode ? [{ debugName: "units" }] : /* istanbul ignore next */ []));
5979
+ computedClass = computed(() => cn('inline-flex items-center gap-2', this.userClass()), /* @ts-ignore */
5980
+ ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
5981
+ constructor() {
5982
+ afterNextRender(() => {
5983
+ this.timer = setInterval(() => {
5984
+ this.now.set(Date.now());
5985
+ }, 1000);
5986
+ });
5987
+ }
5988
+ ngOnDestroy() {
5989
+ if (this.timer !== undefined) {
5990
+ clearInterval(this.timer);
5991
+ }
5992
+ }
5993
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiCountdown, deps: [], target: i0.ɵɵFactoryTarget.Component });
5994
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiCountdown, isStandalone: true, selector: "bui-countdown", inputs: { to: { classPropertyName: "to", publicName: "to", isSignal: true, isRequired: true, transformFunction: null }, expired: { classPropertyName: "expired", publicName: "expired", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "countdown", "role": "timer", "aria-live": "off" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
5995
+ @if (done()) {
5996
+ <span data-slot="countdown-expired" class="text-sm font-medium text-muted-foreground">
5997
+ {{ expired() }}
5998
+ </span>
5999
+ } @else {
6000
+ <div class="flex items-center gap-2">
6001
+ @for (unit of units(); track unit.key) {
6002
+ <div
6003
+ data-slot="countdown-unit"
6004
+ class="flex min-w-[3.25rem] flex-col items-center rounded-lg border bg-card px-2 py-1.5 shadow-xs"
6005
+ >
6006
+ <span class="text-xl font-bold tabular-nums">{{ unit.value }}</span>
6007
+ <span class="text-[10px] font-medium tracking-wide text-muted-foreground uppercase">
6008
+ {{ unit.label }}
6009
+ </span>
6010
+ </div>
6011
+ }
6012
+ </div>
6013
+ }
6014
+ `, isInline: true });
6015
+ }
6016
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiCountdown, decorators: [{
6017
+ type: Component,
6018
+ args: [{
6019
+ selector: 'bui-countdown',
6020
+ host: {
6021
+ 'data-slot': 'countdown',
6022
+ role: 'timer',
6023
+ 'aria-live': 'off',
6024
+ '[class]': 'computedClass()',
6025
+ },
6026
+ template: `
6027
+ @if (done()) {
6028
+ <span data-slot="countdown-expired" class="text-sm font-medium text-muted-foreground">
6029
+ {{ expired() }}
6030
+ </span>
6031
+ } @else {
6032
+ <div class="flex items-center gap-2">
6033
+ @for (unit of units(); track unit.key) {
6034
+ <div
6035
+ data-slot="countdown-unit"
6036
+ class="flex min-w-[3.25rem] flex-col items-center rounded-lg border bg-card px-2 py-1.5 shadow-xs"
6037
+ >
6038
+ <span class="text-xl font-bold tabular-nums">{{ unit.value }}</span>
6039
+ <span class="text-[10px] font-medium tracking-wide text-muted-foreground uppercase">
6040
+ {{ unit.label }}
6041
+ </span>
6042
+ </div>
6043
+ }
6044
+ </div>
6045
+ }
6046
+ `,
6047
+ }]
6048
+ }], ctorParameters: () => [], propDecorators: { to: [{ type: i0.Input, args: [{ isSignal: true, alias: "to", required: true }] }], expired: [{ type: i0.Input, args: [{ isSignal: true, alias: "expired", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
6049
+
6050
+ /**
6051
+ * Animates a number counting up to its target on first render. The animated digits are
6052
+ * `aria-hidden`; an sr-only span carries the final value (SSR/no-JS read the real number).
6053
+ */
6054
+ class BuiNumberTicker {
6055
+ value = input(0, /* @ts-ignore */
6056
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
6057
+ from = input(0, /* @ts-ignore */
6058
+ ...(ngDevMode ? [{ debugName: "from" }] : /* istanbul ignore next */ []));
6059
+ duration = input(1500, /* @ts-ignore */
6060
+ ...(ngDevMode ? [{ debugName: "duration" }] : /* istanbul ignore next */ []));
6061
+ decimals = input(0, /* @ts-ignore */
6062
+ ...(ngDevMode ? [{ debugName: "decimals" }] : /* istanbul ignore next */ []));
6063
+ prefix = input('', /* @ts-ignore */
6064
+ ...(ngDevMode ? [{ debugName: "prefix" }] : /* istanbul ignore next */ []));
6065
+ suffix = input('', /* @ts-ignore */
6066
+ ...(ngDevMode ? [{ debugName: "suffix" }] : /* istanbul ignore next */ []));
6067
+ separator = input(',', /* @ts-ignore */
6068
+ ...(ngDevMode ? [{ debugName: "separator" }] : /* istanbul ignore next */ []));
6069
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
6070
+ current = signal(0, /* @ts-ignore */
6071
+ ...(ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []));
6072
+ computedClass = computed(() => cn('tabular-nums', this.userClass()), /* @ts-ignore */
6073
+ ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
6074
+ constructor() {
6075
+ afterNextRender(() => {
6076
+ this.animate();
6077
+ });
6078
+ }
6079
+ format(value) {
6080
+ const fixed = value.toFixed(Math.max(0, this.decimals()));
6081
+ const [integer, decimal] = fixed.split('.');
6082
+ const decimalPart = decimal ? `.${decimal}` : '';
6083
+ return this.prefix() + this.group(integer) + decimalPart + this.suffix();
6084
+ }
6085
+ group(value) {
6086
+ return value.length <= 3
6087
+ ? value
6088
+ : this.group(value.slice(0, -3)) + this.separator() + value.slice(-3);
6089
+ }
6090
+ animate() {
6091
+ const start = this.from();
6092
+ const end = this.value();
6093
+ const duration = this.duration();
6094
+ if (duration <= 0) {
6095
+ this.current.set(end);
6096
+ return;
6097
+ }
6098
+ this.current.set(start);
6099
+ const startTime = performance.now();
6100
+ const step = (time) => {
6101
+ const progress = Math.min(1, (time - startTime) / duration);
6102
+ this.current.set(start + (end - start) * progress);
6103
+ if (progress < 1) {
6104
+ requestAnimationFrame(step);
6105
+ }
6106
+ };
6107
+ requestAnimationFrame(step);
6108
+ }
6109
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiNumberTicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
6110
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: BuiNumberTicker, isStandalone: true, selector: "bui-number-ticker", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, from: { classPropertyName: "from", publicName: "from", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, decimals: { classPropertyName: "decimals", publicName: "decimals", isSignal: true, isRequired: false, transformFunction: null }, prefix: { classPropertyName: "prefix", publicName: "prefix", isSignal: true, isRequired: false, transformFunction: null }, suffix: { classPropertyName: "suffix", publicName: "suffix", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "number-ticker" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
6111
+ <span aria-hidden="true">{{ format(current()) }}</span>
6112
+ <span class="sr-only">{{ format(value()) }}</span>
6113
+ `, isInline: true });
6114
+ }
6115
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiNumberTicker, decorators: [{
6116
+ type: Component,
6117
+ args: [{
6118
+ selector: 'bui-number-ticker',
6119
+ host: { 'data-slot': 'number-ticker', '[class]': 'computedClass()' },
6120
+ template: `
6121
+ <span aria-hidden="true">{{ format(current()) }}</span>
6122
+ <span class="sr-only">{{ format(value()) }}</span>
6123
+ `,
6124
+ }]
6125
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], from: [{ type: i0.Input, args: [{ isSignal: true, alias: "from", required: false }] }], duration: [{ type: i0.Input, args: [{ isSignal: true, alias: "duration", required: false }] }], decimals: [{ type: i0.Input, args: [{ isSignal: true, alias: "decimals", required: false }] }], prefix: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefix", required: false }] }], suffix: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffix", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
6126
+
5676
6127
  /*
5677
6128
  * Public API Surface of ng-blatui
5678
6129
  */
@@ -5681,5 +6132,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
5681
6132
  * Generated bundle index. Do not edit.
5682
6133
  */
5683
6134
 
5684
- export { BuiAccordion, BuiAccordionContent, BuiAccordionItem, BuiAccordionTrigger, BuiAlert, BuiAlertDescription, BuiAlertDialogAction, BuiAlertDialogCancel, BuiAlertDialogContent, BuiAlertDialogDescription, BuiAlertDialogFooter, BuiAlertDialogHeader, BuiAlertDialogTitle, BuiAlertTitle, BuiAspectRatio, BuiAutosizeTextarea, BuiAvatar, BuiAvatarGroup, BuiBadge, BuiBanner, BuiBreadcrumb, BuiBreadcrumbEllipsis, BuiBreadcrumbItem, BuiBreadcrumbLink, BuiBreadcrumbList, BuiBreadcrumbPage, BuiBreadcrumbSeparator, BuiButton, BuiButtonGroup, BuiButtonGroupText, BuiCard, BuiCardAction, BuiCardContent, BuiCardDescription, BuiCardFooter, BuiCardHeader, BuiCardTitle, BuiCheckbox, BuiCodeBlock, BuiCollapsible, BuiCollapsibleContent, BuiCollapsibleTrigger, BuiComparisonTable, BuiContainer, BuiCopyButton, BuiDialogContent, BuiDialogDescription, BuiDialogFooter, BuiDialogHeader, BuiDialogTitle, BuiDotPattern, BuiDropdownMenu, BuiDropdownMenuItem, BuiDropdownMenuLabel, BuiDropdownMenuSeparator, BuiEmpty, BuiEmptyContent, BuiEmptyDescription, BuiEmptyHeader, BuiEmptyMedia, BuiEmptyTitle, BuiField, BuiFieldContent, BuiFieldDescription, BuiFieldError, BuiFieldGroup, BuiFieldLabel, BuiFieldLegend, BuiFieldSeparator, BuiFieldSet, BuiFieldTitle, BuiFlipCard, BuiGridPattern, BuiHoverCard, BuiHoverCardContent, BuiInput, BuiInputGroup, BuiInputGroupAddon, BuiInputGroupButton, BuiInputGroupInput, BuiInputGroupText, BuiItem, BuiItemActions, BuiItemContent, BuiItemDescription, BuiItemGroup, BuiItemMedia, BuiItemTitle, BuiKbd, BuiLabel, BuiMenubar, BuiMenubarTrigger, BuiMeter, BuiPagination, BuiPaginationContent, BuiPaginationEllipsis, BuiPaginationItem, BuiPaginationLink, BuiPopover, BuiPopoverContent, BuiProgress, BuiQuantitySelector, BuiRadioGroup, BuiRadioGroupItem, BuiRating, BuiScrollArea, BuiSegmentedControl, BuiSelect, BuiSeparator, BuiSkeleton, BuiSlider, BuiSpinner, BuiSpotlightCard, BuiStat, BuiSwitch, BuiTabList, BuiTabPanel, BuiTabTrigger, BuiTable, BuiTableBody, BuiTableCaption, BuiTableCell, BuiTableContainer, BuiTableFooter, BuiTableHead, BuiTableHeader, BuiTableRow, BuiTabs, BuiTerminal, BuiTextarea, BuiThemeCustomizer, BuiTiltCard, BuiToggle, BuiTooltip, BuiTooltipContent, BuiTypography, BuiVisuallyHidden, THEME_TOKENS, ThemeStore, buttonVariants, cn, toggleVariants };
6135
+ export { BuiAccordion, BuiAccordionContent, BuiAccordionItem, BuiAccordionTrigger, BuiAlert, BuiAlertDescription, BuiAlertDialogAction, BuiAlertDialogCancel, BuiAlertDialogContent, BuiAlertDialogDescription, BuiAlertDialogFooter, BuiAlertDialogHeader, BuiAlertDialogTitle, BuiAlertTitle, BuiAspectRatio, BuiAutosizeTextarea, BuiAvatar, BuiAvatarGroup, BuiBackToTop, BuiBadge, BuiBanner, BuiBreadcrumb, BuiBreadcrumbEllipsis, BuiBreadcrumbItem, BuiBreadcrumbLink, BuiBreadcrumbList, BuiBreadcrumbPage, BuiBreadcrumbSeparator, BuiButton, BuiButtonGroup, BuiButtonGroupText, BuiCard, BuiCardAction, BuiCardContent, BuiCardDescription, BuiCardFooter, BuiCardHeader, BuiCardTitle, BuiCheckbox, BuiCodeBlock, BuiCollapsible, BuiCollapsibleContent, BuiCollapsibleTrigger, BuiCombobox, BuiComparisonTable, BuiContainer, BuiCopyButton, BuiCountdown, BuiDialogContent, BuiDialogDescription, BuiDialogFooter, BuiDialogHeader, BuiDialogTitle, BuiDotPattern, BuiDropdownMenu, BuiDropdownMenuItem, BuiDropdownMenuLabel, BuiDropdownMenuSeparator, BuiEmpty, BuiEmptyContent, BuiEmptyDescription, BuiEmptyHeader, BuiEmptyMedia, BuiEmptyTitle, BuiField, BuiFieldContent, BuiFieldDescription, BuiFieldError, BuiFieldGroup, BuiFieldLabel, BuiFieldLegend, BuiFieldSeparator, BuiFieldSet, BuiFieldTitle, BuiFlipCard, BuiGridPattern, BuiHoverCard, BuiHoverCardContent, BuiInput, BuiInputGroup, BuiInputGroupAddon, BuiInputGroupButton, BuiInputGroupInput, BuiInputGroupText, BuiItem, BuiItemActions, BuiItemContent, BuiItemDescription, BuiItemGroup, BuiItemMedia, BuiItemTitle, BuiKbd, BuiLabel, BuiMenubar, BuiMenubarTrigger, BuiMeter, BuiNumberTicker, BuiPagination, BuiPaginationContent, BuiPaginationEllipsis, BuiPaginationItem, BuiPaginationLink, BuiPopover, BuiPopoverContent, BuiProgress, BuiQuantitySelector, BuiRadioGroup, BuiRadioGroupItem, BuiRating, BuiScrollArea, BuiSegmentedControl, BuiSelect, BuiSeparator, BuiSkeleton, BuiSlider, BuiSpinner, BuiSpotlightCard, BuiStat, BuiSwitch, BuiTabList, BuiTabPanel, BuiTabTrigger, BuiTable, BuiTableBody, BuiTableCaption, BuiTableCell, BuiTableContainer, BuiTableFooter, BuiTableHead, BuiTableHeader, BuiTableRow, BuiTabs, BuiTerminal, BuiTextarea, BuiThemeCustomizer, BuiTiltCard, BuiToggle, BuiTooltip, BuiTooltipContent, BuiTypography, BuiVisuallyHidden, THEME_TOKENS, ThemeStore, buttonVariants, cn, toggleVariants };
5685
6136
  //# sourceMappingURL=ng-blatui.mjs.map