ng-blatui 1.11.0 → 1.13.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.
@@ -1,7 +1,7 @@
1
1
  import { clsx } from 'clsx';
2
2
  import { twMerge } from 'tailwind-merge';
3
3
  import * as i0 from '@angular/core';
4
- import { input, computed, Directive, Component, signal, model, inject, PLATFORM_ID, effect, Injectable, ElementRef, ViewContainerRef } from '@angular/core';
4
+ import { input, computed, Directive, Component, signal, model, inject, PLATFORM_ID, effect, Injectable, ElementRef, ViewContainerRef, viewChild } from '@angular/core';
5
5
  import { cva } from 'class-variance-authority';
6
6
  export { AccordionContent, AccordionGroup, AccordionPanel, AccordionTrigger, ɵɵDeferredContent, ɵɵDeferredContentAware } from '@angular/aria/accordion';
7
7
  export { Tab, TabContent, TabList, TabPanel, Tabs } from '@angular/aria/tabs';
@@ -3995,6 +3995,509 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
3995
3995
  }]
3996
3996
  }], propDecorators: { code: [{ type: i0.Input, args: [{ isSignal: true, alias: "code", required: false }] }], filename: [{ type: i0.Input, args: [{ isSignal: true, alias: "filename", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
3997
3997
 
3998
+ /**
3999
+ * A single-value slider (`role="slider"`) with pointer drag and full keyboard support
4000
+ * (arrows, Home/End, PageUp/PageDown). Horizontal or vertical. SSR-safe — geometry is
4001
+ * only read inside browser event handlers.
4002
+ */
4003
+ class BuiSlider {
4004
+ value = model(0, /* @ts-ignore */
4005
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
4006
+ min = input(0, /* @ts-ignore */
4007
+ ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
4008
+ max = input(100, /* @ts-ignore */
4009
+ ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
4010
+ step = input(1, /* @ts-ignore */
4011
+ ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
4012
+ disabled = input(false, /* @ts-ignore */
4013
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
4014
+ orientation = input('horizontal', /* @ts-ignore */
4015
+ ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
4016
+ ariaLabel = input('Value', /* @ts-ignore */
4017
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
4018
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
4019
+ track = viewChild.required('track');
4020
+ dragging = false;
4021
+ pct = computed(() => {
4022
+ const range = this.max() - this.min() || 1;
4023
+ return ((this.value() - this.min()) / range) * 100;
4024
+ }, /* @ts-ignore */
4025
+ ...(ngDevMode ? [{ debugName: "pct" }] : /* istanbul ignore next */ []));
4026
+ computedClass = computed(() => cn('relative flex touch-none items-center select-none data-disabled:pointer-events-none data-disabled:opacity-50', this.orientation() === 'vertical' ? 'h-40 w-fit flex-col' : 'w-full', this.userClass()), /* @ts-ignore */
4027
+ ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
4028
+ onPointerDown(event) {
4029
+ if (this.disabled()) {
4030
+ return;
4031
+ }
4032
+ this.dragging = true;
4033
+ this.value.set(this.valueFromPointer(event));
4034
+ }
4035
+ onMove(event) {
4036
+ if (this.dragging) {
4037
+ this.value.set(this.valueFromPointer(event));
4038
+ }
4039
+ }
4040
+ onUp() {
4041
+ this.dragging = false;
4042
+ }
4043
+ onKeydown(event) {
4044
+ if (this.disabled()) {
4045
+ return;
4046
+ }
4047
+ const big = Math.max(this.step(), (this.max() - this.min()) / 10);
4048
+ let next;
4049
+ switch (event.key) {
4050
+ case 'ArrowRight':
4051
+ case 'ArrowUp': {
4052
+ next = this.value() + this.step();
4053
+ break;
4054
+ }
4055
+ case 'ArrowLeft':
4056
+ case 'ArrowDown': {
4057
+ next = this.value() - this.step();
4058
+ break;
4059
+ }
4060
+ case 'Home': {
4061
+ next = this.min();
4062
+ break;
4063
+ }
4064
+ case 'End': {
4065
+ next = this.max();
4066
+ break;
4067
+ }
4068
+ case 'PageUp': {
4069
+ next = this.value() + big;
4070
+ break;
4071
+ }
4072
+ case 'PageDown': {
4073
+ next = this.value() - big;
4074
+ break;
4075
+ }
4076
+ default: {
4077
+ return;
4078
+ }
4079
+ }
4080
+ event.preventDefault();
4081
+ this.value.set(this.clamp(next));
4082
+ }
4083
+ valueFromPointer(event) {
4084
+ const rect = this.track().nativeElement.getBoundingClientRect();
4085
+ const ratioRaw = this.orientation() === 'vertical'
4086
+ ? 1 - (event.clientY - rect.top) / rect.height
4087
+ : (event.clientX - rect.left) / rect.width;
4088
+ const ratio = Math.max(0, Math.min(1, ratioRaw));
4089
+ return this.snap(this.min() + ratio * (this.max() - this.min()));
4090
+ }
4091
+ snap(raw) {
4092
+ return this.clamp(Math.round(raw / this.step()) * this.step());
4093
+ }
4094
+ clamp(value) {
4095
+ return Math.max(this.min(), Math.min(this.max(), value));
4096
+ }
4097
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiSlider, deps: [], target: i0.ɵɵFactoryTarget.Component });
4098
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.0.2", type: BuiSlider, isStandalone: true, selector: "bui-slider", inputs: { value: { classPropertyName: "value", publicName: "value", 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 }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { attributes: { "data-slot": "slider" }, listeners: { "document:pointermove": "onMove($event)", "document:pointerup": "onUp()" }, properties: { "attr.data-orientation": "orientation()", "attr.data-disabled": "disabled() ? '' : null", "class": "computedClass()" } }, viewQueries: [{ propertyName: "track", first: true, predicate: ["track"], descendants: true, isSignal: true }], ngImport: i0, template: `
4099
+ <span
4100
+ #track
4101
+ data-slot="slider-track"
4102
+ class="relative grow overflow-hidden rounded-full bg-muted"
4103
+ [class]="orientation() === 'vertical' ? 'h-full w-1.5' : 'h-1.5 w-full'"
4104
+ (pointerdown)="onPointerDown($event)"
4105
+ >
4106
+ <span
4107
+ data-slot="slider-range"
4108
+ class="absolute bg-primary"
4109
+ [class]="orientation() === 'vertical' ? 'bottom-0 w-full' : 'left-0 h-full'"
4110
+ [style.height.%]="orientation() === 'vertical' ? pct() : null"
4111
+ [style.width.%]="orientation() === 'vertical' ? null : pct()"
4112
+ ></span>
4113
+ </span>
4114
+ <span
4115
+ data-slot="slider-thumb"
4116
+ role="slider"
4117
+ [attr.aria-orientation]="orientation()"
4118
+ [attr.aria-label]="ariaLabel()"
4119
+ [attr.aria-valuemin]="min()"
4120
+ [attr.aria-valuemax]="max()"
4121
+ [attr.aria-valuenow]="value()"
4122
+ [attr.aria-disabled]="disabled()"
4123
+ [attr.tabindex]="disabled() ? -1 : 0"
4124
+ class="absolute block size-4 shrink-0 rounded-full border border-primary bg-background shadow-sm ring-ring/50 transition-[color,box-shadow] outline-none hover:ring-4 focus-visible:ring-4"
4125
+ [class]="
4126
+ orientation() === 'vertical'
4127
+ ? 'left-1/2 -translate-x-1/2 translate-y-1/2'
4128
+ : 'top-1/2 -translate-x-1/2 -translate-y-1/2'
4129
+ "
4130
+ [style.bottom.%]="orientation() === 'vertical' ? pct() : null"
4131
+ [style.left.%]="orientation() === 'vertical' ? null : pct()"
4132
+ (keydown)="onKeydown($event)"
4133
+ ></span>
4134
+ `, isInline: true });
4135
+ }
4136
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiSlider, decorators: [{
4137
+ type: Component,
4138
+ args: [{
4139
+ selector: 'bui-slider',
4140
+ host: {
4141
+ 'data-slot': 'slider',
4142
+ '[attr.data-orientation]': 'orientation()',
4143
+ '[attr.data-disabled]': "disabled() ? '' : null",
4144
+ '[class]': 'computedClass()',
4145
+ '(document:pointermove)': 'onMove($event)',
4146
+ '(document:pointerup)': 'onUp()',
4147
+ },
4148
+ template: `
4149
+ <span
4150
+ #track
4151
+ data-slot="slider-track"
4152
+ class="relative grow overflow-hidden rounded-full bg-muted"
4153
+ [class]="orientation() === 'vertical' ? 'h-full w-1.5' : 'h-1.5 w-full'"
4154
+ (pointerdown)="onPointerDown($event)"
4155
+ >
4156
+ <span
4157
+ data-slot="slider-range"
4158
+ class="absolute bg-primary"
4159
+ [class]="orientation() === 'vertical' ? 'bottom-0 w-full' : 'left-0 h-full'"
4160
+ [style.height.%]="orientation() === 'vertical' ? pct() : null"
4161
+ [style.width.%]="orientation() === 'vertical' ? null : pct()"
4162
+ ></span>
4163
+ </span>
4164
+ <span
4165
+ data-slot="slider-thumb"
4166
+ role="slider"
4167
+ [attr.aria-orientation]="orientation()"
4168
+ [attr.aria-label]="ariaLabel()"
4169
+ [attr.aria-valuemin]="min()"
4170
+ [attr.aria-valuemax]="max()"
4171
+ [attr.aria-valuenow]="value()"
4172
+ [attr.aria-disabled]="disabled()"
4173
+ [attr.tabindex]="disabled() ? -1 : 0"
4174
+ class="absolute block size-4 shrink-0 rounded-full border border-primary bg-background shadow-sm ring-ring/50 transition-[color,box-shadow] outline-none hover:ring-4 focus-visible:ring-4"
4175
+ [class]="
4176
+ orientation() === 'vertical'
4177
+ ? 'left-1/2 -translate-x-1/2 translate-y-1/2'
4178
+ : 'top-1/2 -translate-x-1/2 -translate-y-1/2'
4179
+ "
4180
+ [style.bottom.%]="orientation() === 'vertical' ? pct() : null"
4181
+ [style.left.%]="orientation() === 'vertical' ? null : pct()"
4182
+ (keydown)="onKeydown($event)"
4183
+ ></span>
4184
+ `,
4185
+ }]
4186
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], 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 }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], track: [{ type: i0.ViewChild, args: ['track', { isSignal: true }] }] } });
4187
+
4188
+ const STAR_SIZE = { sm: 'size-4', default: 'size-5', lg: 'size-6' };
4189
+ /** A star rating (`role="radiogroup"`) with hover preview and keyboard support. */
4190
+ class BuiRating {
4191
+ value = model(0, /* @ts-ignore */
4192
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
4193
+ max = input(5, /* @ts-ignore */
4194
+ ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
4195
+ readonly = input(false, /* @ts-ignore */
4196
+ ...(ngDevMode ? [{ debugName: "readonly" }] : /* istanbul ignore next */ []));
4197
+ size = input('default', /* @ts-ignore */
4198
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
4199
+ color = input('text-amber-500', /* @ts-ignore */
4200
+ ...(ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []));
4201
+ ariaLabel = input(null, /* @ts-ignore */
4202
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
4203
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
4204
+ hover = signal(0, /* @ts-ignore */
4205
+ ...(ngDevMode ? [{ debugName: "hover" }] : /* istanbul ignore next */ []));
4206
+ current = computed(() => this.hover() || this.value(), /* @ts-ignore */
4207
+ ...(ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []));
4208
+ stars = computed(() => Array.from({ length: this.max() }, (_, index) => index + 1), /* @ts-ignore */
4209
+ ...(ngDevMode ? [{ debugName: "stars" }] : /* istanbul ignore next */ []));
4210
+ sizeClass = computed(() => STAR_SIZE[this.size()], /* @ts-ignore */
4211
+ ...(ngDevMode ? [{ debugName: "sizeClass" }] : /* istanbul ignore next */ []));
4212
+ computedClass = computed(() => cn('inline-flex items-center gap-0.5', this.userClass()), /* @ts-ignore */
4213
+ ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
4214
+ set(next) {
4215
+ if (!this.readonly()) {
4216
+ this.value.set(next);
4217
+ }
4218
+ }
4219
+ onHover(next) {
4220
+ if (!this.readonly()) {
4221
+ this.hover.set(next);
4222
+ }
4223
+ }
4224
+ tabindexFor(star) {
4225
+ if (this.readonly()) {
4226
+ return -1;
4227
+ }
4228
+ return star === (this.value() || 1) ? 0 : -1;
4229
+ }
4230
+ onKeydown(event) {
4231
+ if (this.readonly()) {
4232
+ return;
4233
+ }
4234
+ if (event.key === 'ArrowRight' || event.key === 'ArrowUp') {
4235
+ event.preventDefault();
4236
+ this.set(Math.min(this.max(), this.value() + 1));
4237
+ }
4238
+ else if (event.key === 'ArrowLeft' || event.key === 'ArrowDown') {
4239
+ event.preventDefault();
4240
+ this.set(Math.max(0, this.value() - 1));
4241
+ }
4242
+ }
4243
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiRating, deps: [], target: i0.ɵɵFactoryTarget.Component });
4244
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiRating, isStandalone: true, selector: "bui-rating", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { attributes: { "data-slot": "rating", "role": "radiogroup" }, listeners: { "mouseleave": "hover.set(0)", "keydown": "onKeydown($event)" }, properties: { "attr.aria-label": "ariaLabel()", "class": "computedClass()" } }, ngImport: i0, template: `
4245
+ @for (star of stars(); track star) {
4246
+ <button
4247
+ type="button"
4248
+ role="radio"
4249
+ [attr.aria-checked]="value() === star"
4250
+ [attr.aria-label]="star + ' / ' + max()"
4251
+ [attr.tabindex]="tabindexFor(star)"
4252
+ [disabled]="readonly()"
4253
+ class="rounded-sm transition-colors outline-none not-disabled:cursor-pointer focus-visible:ring-[3px] focus-visible:ring-ring/50"
4254
+ [class]="current() >= star ? color() : 'text-muted-foreground/30'"
4255
+ (click)="set(star)"
4256
+ (mouseenter)="onHover(star)"
4257
+ (focus)="onHover(star)"
4258
+ >
4259
+ <svg
4260
+ viewBox="0 0 24 24"
4261
+ stroke="currentColor"
4262
+ stroke-width="2"
4263
+ stroke-linecap="round"
4264
+ stroke-linejoin="round"
4265
+ aria-hidden="true"
4266
+ [class]="sizeClass()"
4267
+ [attr.fill]="current() >= star ? 'currentColor' : 'none'"
4268
+ >
4269
+ <polygon
4270
+ points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
4271
+ />
4272
+ </svg>
4273
+ </button>
4274
+ }
4275
+ `, isInline: true });
4276
+ }
4277
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiRating, decorators: [{
4278
+ type: Component,
4279
+ args: [{
4280
+ selector: 'bui-rating',
4281
+ host: {
4282
+ 'data-slot': 'rating',
4283
+ role: 'radiogroup',
4284
+ '[attr.aria-label]': 'ariaLabel()',
4285
+ '[class]': 'computedClass()',
4286
+ '(mouseleave)': 'hover.set(0)',
4287
+ '(keydown)': 'onKeydown($event)',
4288
+ },
4289
+ template: `
4290
+ @for (star of stars(); track star) {
4291
+ <button
4292
+ type="button"
4293
+ role="radio"
4294
+ [attr.aria-checked]="value() === star"
4295
+ [attr.aria-label]="star + ' / ' + max()"
4296
+ [attr.tabindex]="tabindexFor(star)"
4297
+ [disabled]="readonly()"
4298
+ class="rounded-sm transition-colors outline-none not-disabled:cursor-pointer focus-visible:ring-[3px] focus-visible:ring-ring/50"
4299
+ [class]="current() >= star ? color() : 'text-muted-foreground/30'"
4300
+ (click)="set(star)"
4301
+ (mouseenter)="onHover(star)"
4302
+ (focus)="onHover(star)"
4303
+ >
4304
+ <svg
4305
+ viewBox="0 0 24 24"
4306
+ stroke="currentColor"
4307
+ stroke-width="2"
4308
+ stroke-linecap="round"
4309
+ stroke-linejoin="round"
4310
+ aria-hidden="true"
4311
+ [class]="sizeClass()"
4312
+ [attr.fill]="current() >= star ? 'currentColor' : 'none'"
4313
+ >
4314
+ <polygon
4315
+ points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"
4316
+ />
4317
+ </svg>
4318
+ </button>
4319
+ }
4320
+ `,
4321
+ }]
4322
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
4323
+
4324
+ const FIELD_HEIGHT = { sm: 'h-7 text-xs', default: 'h-8 text-sm', lg: 'h-9 text-base' };
4325
+ const BTN_SIZE = {
4326
+ sm: 'w-7 [&_svg]:size-3',
4327
+ default: 'w-8 [&_svg]:size-3.5',
4328
+ lg: 'w-9 [&_svg]:size-4',
4329
+ };
4330
+ const FIELD_WIDTH = { sm: 'w-9', default: 'w-10', lg: 'w-12' };
4331
+ /** A compact − [n] + quantity stepper (`role="group"` with a `spinbutton` field). */
4332
+ class BuiQuantitySelector {
4333
+ value = model(1, /* @ts-ignore */
4334
+ ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
4335
+ min = input(1, /* @ts-ignore */
4336
+ ...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
4337
+ max = input(null, /* @ts-ignore */
4338
+ ...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
4339
+ step = input(1, /* @ts-ignore */
4340
+ ...(ngDevMode ? [{ debugName: "step" }] : /* istanbul ignore next */ []));
4341
+ size = input('default', /* @ts-ignore */
4342
+ ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
4343
+ disabled = input(false, /* @ts-ignore */
4344
+ ...(ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []));
4345
+ ariaLabel = input('Quantity', /* @ts-ignore */
4346
+ ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
4347
+ userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
4348
+ atMin = computed(() => this.value() <= this.min(), /* @ts-ignore */
4349
+ ...(ngDevMode ? [{ debugName: "atMin" }] : /* istanbul ignore next */ []));
4350
+ atMax = computed(() => {
4351
+ const max = this.max();
4352
+ return max !== null && this.value() >= max;
4353
+ }, /* @ts-ignore */
4354
+ ...(ngDevMode ? [{ debugName: "atMax" }] : /* istanbul ignore next */ []));
4355
+ computedClass = computed(() => cn('inline-flex items-stretch overflow-hidden rounded-md border border-input bg-transparent shadow-xs transition-[color,box-shadow] focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50 has-[input:disabled]:pointer-events-none has-[input:disabled]:opacity-50 dark:bg-input/30', this.userClass()), /* @ts-ignore */
4356
+ ...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
4357
+ btnClass(side) {
4358
+ return cn('flex shrink-0 items-center justify-center text-muted-foreground transition-colors outline-none not-disabled:cursor-pointer hover:bg-accent hover:text-accent-foreground disabled:pointer-events-none disabled:opacity-50', side === 'e' ? 'border-e' : 'border-s', 'border-input', BTN_SIZE[this.size()], FIELD_HEIGHT[this.size()]);
4359
+ }
4360
+ fieldClass() {
4361
+ return cn('min-w-0 border-0 bg-transparent text-center font-medium tabular-nums outline-none', FIELD_HEIGHT[this.size()], FIELD_WIDTH[this.size()]);
4362
+ }
4363
+ inc() {
4364
+ if (!this.disabled() && !this.atMax()) {
4365
+ this.value.set(this.clamp(this.value() + this.step()));
4366
+ }
4367
+ }
4368
+ dec() {
4369
+ if (!this.disabled() && !this.atMin()) {
4370
+ this.value.set(this.clamp(this.value() - this.step()));
4371
+ }
4372
+ }
4373
+ onInput(event) {
4374
+ const raw = event.target.value.replaceAll(/[^\d-]/g, '');
4375
+ this.value.set(raw === '' ? this.min() : Number(raw));
4376
+ }
4377
+ onBlur() {
4378
+ const current = this.value();
4379
+ this.value.set(this.clamp(Number.isNaN(current) ? this.min() : current));
4380
+ }
4381
+ clamp(value) {
4382
+ let result = Math.max(this.min(), value);
4383
+ const max = this.max();
4384
+ if (max !== null && result > max) {
4385
+ result = max;
4386
+ }
4387
+ return result;
4388
+ }
4389
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiQuantitySelector, deps: [], target: i0.ɵɵFactoryTarget.Component });
4390
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.2", type: BuiQuantitySelector, isStandalone: true, selector: "bui-quantity-selector", inputs: { value: { classPropertyName: "value", publicName: "value", 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 }, step: { classPropertyName: "step", publicName: "step", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { attributes: { "data-slot": "quantity-selector", "role": "group" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
4391
+ <button
4392
+ type="button"
4393
+ aria-label="Decrease quantity"
4394
+ [disabled]="disabled() || atMin()"
4395
+ [class]="btnClass('e')"
4396
+ (click)="dec()"
4397
+ >
4398
+ <svg
4399
+ viewBox="0 0 24 24"
4400
+ fill="none"
4401
+ stroke="currentColor"
4402
+ stroke-width="2"
4403
+ aria-hidden="true"
4404
+ >
4405
+ <path d="M5 12h14" />
4406
+ </svg>
4407
+ </button>
4408
+ <input
4409
+ type="text"
4410
+ inputmode="numeric"
4411
+ role="spinbutton"
4412
+ [attr.aria-label]="ariaLabel()"
4413
+ [attr.aria-valuenow]="value()"
4414
+ [attr.aria-valuemin]="min()"
4415
+ [attr.aria-valuemax]="max()"
4416
+ [disabled]="disabled()"
4417
+ [value]="value()"
4418
+ [class]="fieldClass()"
4419
+ (input)="onInput($event)"
4420
+ (blur)="onBlur()"
4421
+ />
4422
+ <button
4423
+ type="button"
4424
+ aria-label="Increase quantity"
4425
+ [disabled]="disabled() || atMax()"
4426
+ [class]="btnClass('s')"
4427
+ (click)="inc()"
4428
+ >
4429
+ <svg
4430
+ viewBox="0 0 24 24"
4431
+ fill="none"
4432
+ stroke="currentColor"
4433
+ stroke-width="2"
4434
+ aria-hidden="true"
4435
+ >
4436
+ <path d="M5 12h14" />
4437
+ <path d="M12 5v14" />
4438
+ </svg>
4439
+ </button>
4440
+ `, isInline: true });
4441
+ }
4442
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiQuantitySelector, decorators: [{
4443
+ type: Component,
4444
+ args: [{
4445
+ selector: 'bui-quantity-selector',
4446
+ host: { 'data-slot': 'quantity-selector', role: 'group', '[class]': 'computedClass()' },
4447
+ template: `
4448
+ <button
4449
+ type="button"
4450
+ aria-label="Decrease quantity"
4451
+ [disabled]="disabled() || atMin()"
4452
+ [class]="btnClass('e')"
4453
+ (click)="dec()"
4454
+ >
4455
+ <svg
4456
+ viewBox="0 0 24 24"
4457
+ fill="none"
4458
+ stroke="currentColor"
4459
+ stroke-width="2"
4460
+ aria-hidden="true"
4461
+ >
4462
+ <path d="M5 12h14" />
4463
+ </svg>
4464
+ </button>
4465
+ <input
4466
+ type="text"
4467
+ inputmode="numeric"
4468
+ role="spinbutton"
4469
+ [attr.aria-label]="ariaLabel()"
4470
+ [attr.aria-valuenow]="value()"
4471
+ [attr.aria-valuemin]="min()"
4472
+ [attr.aria-valuemax]="max()"
4473
+ [disabled]="disabled()"
4474
+ [value]="value()"
4475
+ [class]="fieldClass()"
4476
+ (input)="onInput($event)"
4477
+ (blur)="onBlur()"
4478
+ />
4479
+ <button
4480
+ type="button"
4481
+ aria-label="Increase quantity"
4482
+ [disabled]="disabled() || atMax()"
4483
+ [class]="btnClass('s')"
4484
+ (click)="inc()"
4485
+ >
4486
+ <svg
4487
+ viewBox="0 0 24 24"
4488
+ fill="none"
4489
+ stroke="currentColor"
4490
+ stroke-width="2"
4491
+ aria-hidden="true"
4492
+ >
4493
+ <path d="M5 12h14" />
4494
+ <path d="M12 5v14" />
4495
+ </svg>
4496
+ </button>
4497
+ `,
4498
+ }]
4499
+ }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], 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 }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
4500
+
3998
4501
  /*
3999
4502
  * Public API Surface of ng-blatui
4000
4503
  */
@@ -4003,5 +4506,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
4003
4506
  * Generated bundle index. Do not edit.
4004
4507
  */
4005
4508
 
4006
- export { BuiAccordion, BuiAccordionContent, BuiAccordionItem, BuiAccordionTrigger, BuiAlert, BuiAlertDescription, BuiAlertTitle, BuiAspectRatio, 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, BuiContainer, BuiCopyButton, BuiDialogContent, BuiDialogDescription, BuiDialogFooter, BuiDialogHeader, BuiDialogTitle, BuiEmpty, BuiEmptyContent, BuiEmptyDescription, BuiEmptyHeader, BuiEmptyMedia, BuiEmptyTitle, BuiField, BuiFieldContent, BuiFieldDescription, BuiFieldError, BuiFieldGroup, BuiFieldLabel, BuiFieldLegend, BuiFieldSeparator, BuiFieldSet, BuiFieldTitle, BuiHoverCard, BuiHoverCardContent, BuiInput, BuiInputGroup, BuiInputGroupAddon, BuiInputGroupButton, BuiInputGroupInput, BuiInputGroupText, BuiItem, BuiItemActions, BuiItemContent, BuiItemDescription, BuiItemGroup, BuiItemMedia, BuiItemTitle, BuiKbd, BuiLabel, BuiMeter, BuiPagination, BuiPaginationContent, BuiPaginationEllipsis, BuiPaginationItem, BuiPaginationLink, BuiPopover, BuiPopoverContent, BuiProgress, BuiRadioGroup, BuiRadioGroupItem, BuiScrollArea, BuiSeparator, BuiSkeleton, BuiSpinner, BuiStat, BuiSwitch, BuiTabList, BuiTabPanel, BuiTabTrigger, BuiTable, BuiTableBody, BuiTableCaption, BuiTableCell, BuiTableContainer, BuiTableFooter, BuiTableHead, BuiTableHeader, BuiTableRow, BuiTabs, BuiTextarea, BuiThemeCustomizer, BuiToggle, BuiTooltip, BuiTooltipContent, BuiVisuallyHidden, THEME_TOKENS, ThemeStore, buttonVariants, cn, toggleVariants };
4509
+ export { BuiAccordion, BuiAccordionContent, BuiAccordionItem, BuiAccordionTrigger, BuiAlert, BuiAlertDescription, BuiAlertTitle, BuiAspectRatio, 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, BuiContainer, BuiCopyButton, BuiDialogContent, BuiDialogDescription, BuiDialogFooter, BuiDialogHeader, BuiDialogTitle, BuiEmpty, BuiEmptyContent, BuiEmptyDescription, BuiEmptyHeader, BuiEmptyMedia, BuiEmptyTitle, BuiField, BuiFieldContent, BuiFieldDescription, BuiFieldError, BuiFieldGroup, BuiFieldLabel, BuiFieldLegend, BuiFieldSeparator, BuiFieldSet, BuiFieldTitle, BuiHoverCard, BuiHoverCardContent, BuiInput, BuiInputGroup, BuiInputGroupAddon, BuiInputGroupButton, BuiInputGroupInput, BuiInputGroupText, BuiItem, BuiItemActions, BuiItemContent, BuiItemDescription, BuiItemGroup, BuiItemMedia, BuiItemTitle, BuiKbd, BuiLabel, BuiMeter, BuiPagination, BuiPaginationContent, BuiPaginationEllipsis, BuiPaginationItem, BuiPaginationLink, BuiPopover, BuiPopoverContent, BuiProgress, BuiQuantitySelector, BuiRadioGroup, BuiRadioGroupItem, BuiRating, BuiScrollArea, BuiSeparator, BuiSkeleton, BuiSlider, BuiSpinner, BuiStat, BuiSwitch, BuiTabList, BuiTabPanel, BuiTabTrigger, BuiTable, BuiTableBody, BuiTableCaption, BuiTableCell, BuiTableContainer, BuiTableFooter, BuiTableHead, BuiTableHeader, BuiTableRow, BuiTabs, BuiTextarea, BuiThemeCustomizer, BuiToggle, BuiTooltip, BuiTooltipContent, BuiVisuallyHidden, THEME_TOKENS, ThemeStore, buttonVariants, cn, toggleVariants };
4007
4510
  //# sourceMappingURL=ng-blatui.mjs.map