ng-blatui 1.30.0 → 1.32.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.
- package/fesm2022/ng-blatui.mjs +413 -166
- package/fesm2022/ng-blatui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ng-blatui.d.ts +71 -24
package/fesm2022/ng-blatui.mjs
CHANGED
|
@@ -86,6 +86,8 @@ const BUI_DEFAULT_LABELS = {
|
|
|
86
86
|
sonnerDismiss: 'Dismiss notification',
|
|
87
87
|
themeCustomizer: 'Theme customizer',
|
|
88
88
|
treeTableToggle: 'Toggle row',
|
|
89
|
+
treeTableCopy: 'Copy as tree',
|
|
90
|
+
treeTableCopied: 'Copied',
|
|
89
91
|
videoPlay: 'Play video',
|
|
90
92
|
};
|
|
91
93
|
/**
|
|
@@ -174,8 +176,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
174
176
|
}]
|
|
175
177
|
}], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
176
178
|
|
|
177
|
-
const BASE$
|
|
178
|
-
const SIZES$
|
|
179
|
+
const BASE$1 = 'inline-flex items-center justify-center rounded-md border font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden';
|
|
180
|
+
const SIZES$4 = {
|
|
179
181
|
sm: 'px-1.5 py-px text-[0.625rem]',
|
|
180
182
|
default: 'px-2 py-0.5 text-xs',
|
|
181
183
|
lg: 'px-3 py-1 text-sm [&>svg]:size-3.5',
|
|
@@ -252,7 +254,7 @@ class BuiBadge {
|
|
|
252
254
|
computedClass = computed(() => {
|
|
253
255
|
const tone = this.tone();
|
|
254
256
|
const toneOrVariant = tone === null ? brandClass(this.variant()) : TONES$2[tone][intensityFor(this.variant())];
|
|
255
|
-
return cn(BASE$
|
|
257
|
+
return cn(BASE$1, SIZES$4[this.size()], toneOrVariant, this.userClass());
|
|
256
258
|
}, /* @ts-ignore */
|
|
257
259
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
258
260
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiBadge, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
@@ -558,16 +560,36 @@ const TEXTAREA_SIZES = {
|
|
|
558
560
|
default: 'min-h-16 px-3 py-2 text-base md:text-sm',
|
|
559
561
|
lg: 'min-h-20 px-4 py-2.5 text-base',
|
|
560
562
|
};
|
|
561
|
-
|
|
563
|
+
// Vertical padding (top + bottom) baked into each size preset, used to compute the `maxRows`
|
|
564
|
+
// height cap. Mirrors the `py-*` utilities in TEXTAREA_SIZES.
|
|
565
|
+
const TEXTAREA_PADDING_Y = {
|
|
566
|
+
sm: '0.75rem',
|
|
567
|
+
default: '1rem',
|
|
568
|
+
lg: '1.25rem',
|
|
569
|
+
};
|
|
570
|
+
/**
|
|
571
|
+
* Applies BlatUI textarea styling to a native `<textarea>`. Auto-grows with its content via CSS
|
|
572
|
+
* `field-sizing-content` (no JS). Set `[maxRows]` to cap the growth — past it the field scrolls.
|
|
573
|
+
*/
|
|
562
574
|
class BuiTextarea {
|
|
563
575
|
/** Size preset controlling minimum height, padding and text size. */
|
|
564
576
|
size = input('default', /* @ts-ignore */
|
|
565
577
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
578
|
+
/** Maximum number of rows before the textarea scrolls instead of growing (null = unlimited). */
|
|
579
|
+
maxRows = input(null, /* @ts-ignore */
|
|
580
|
+
...(ngDevMode ? [{ debugName: "maxRows" }] : /* istanbul ignore next */ []));
|
|
566
581
|
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
567
582
|
computedClass = computed(() => cn(TEXTAREA_BASE, TEXTAREA_SIZES[this.size()], this.userClass()), /* @ts-ignore */
|
|
568
583
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
584
|
+
// Cap the auto-grow at `maxRows` lines using the `lh` unit (one line-height) plus the size's
|
|
585
|
+
// vertical padding and the 1px borders — purely declarative, so it stays SSR-safe.
|
|
586
|
+
maxHeight = computed(() => {
|
|
587
|
+
const rows = this.maxRows();
|
|
588
|
+
return rows === null ? null : `calc(${rows} * 1lh + ${TEXTAREA_PADDING_Y[this.size()]} + 2px)`;
|
|
589
|
+
}, /* @ts-ignore */
|
|
590
|
+
...(ngDevMode ? [{ debugName: "maxHeight" }] : /* istanbul ignore next */ []));
|
|
569
591
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiTextarea, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
570
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: BuiTextarea, isStandalone: true, selector: "textarea[buiTextarea]", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "textarea" }, properties: { "attr.data-size": "size()", "class": "computedClass()" } }, ngImport: i0 });
|
|
592
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: BuiTextarea, isStandalone: true, selector: "textarea[buiTextarea]", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "textarea" }, properties: { "attr.data-size": "size()", "class": "computedClass()", "style.max-height": "maxHeight()", "style.overflow-y": "maxRows() === null ? null : 'auto'" } }, ngImport: i0 });
|
|
571
593
|
}
|
|
572
594
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiTextarea, decorators: [{
|
|
573
595
|
type: Directive,
|
|
@@ -577,9 +599,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
577
599
|
'data-slot': 'textarea',
|
|
578
600
|
'[attr.data-size]': 'size()',
|
|
579
601
|
'[class]': 'computedClass()',
|
|
602
|
+
'[style.max-height]': 'maxHeight()',
|
|
603
|
+
'[style.overflow-y]': "maxRows() === null ? null : 'auto'",
|
|
580
604
|
},
|
|
581
605
|
}]
|
|
582
|
-
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
606
|
+
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], maxRows: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxRows", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
583
607
|
|
|
584
608
|
/**
|
|
585
609
|
* BlatUI linear progress bar. Exposes the full `progressbar` ARIA contract
|
|
@@ -1071,7 +1095,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
1071
1095
|
}]
|
|
1072
1096
|
}], propDecorators: { checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], iconOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOn", required: false }] }], iconOff: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconOff", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
1073
1097
|
|
|
1074
|
-
const TRIGGER = '
|
|
1098
|
+
const TRIGGER = 'flex flex-1 cursor-pointer items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-default disabled:opacity-50 [&>svg]:pointer-events-none [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:translate-y-0.5 [&>svg]:text-muted-foreground [&>svg]:transition-transform [&>svg]:duration-200 [&[aria-expanded=true]>svg]:rotate-180';
|
|
1075
1099
|
class BuiAccordion {
|
|
1076
1100
|
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
1077
1101
|
computedClass = computed(() => cn('w-full', this.userClass()), /* @ts-ignore */
|
|
@@ -2720,7 +2744,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2720
2744
|
}]
|
|
2721
2745
|
}], propDecorators: { userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
2722
2746
|
|
|
2723
|
-
const SIZES$
|
|
2747
|
+
const SIZES$3 = {
|
|
2724
2748
|
sm: 'max-w-3xl',
|
|
2725
2749
|
md: 'max-w-5xl',
|
|
2726
2750
|
lg: 'max-w-6xl',
|
|
@@ -2734,7 +2758,7 @@ class BuiContainer {
|
|
|
2734
2758
|
size = input('lg', /* @ts-ignore */
|
|
2735
2759
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
2736
2760
|
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
2737
|
-
computedClass = computed(() => cn('mx-auto w-full px-4 sm:px-6 lg:px-8', SIZES$
|
|
2761
|
+
computedClass = computed(() => cn('mx-auto w-full px-4 sm:px-6 lg:px-8', SIZES$3[this.size()], this.userClass()), /* @ts-ignore */
|
|
2738
2762
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
2739
2763
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiContainer, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2740
2764
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: BuiContainer, isStandalone: true, selector: "[buiContainer]", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "container" }, properties: { "class": "computedClass()" } }, ngImport: i0 });
|
|
@@ -3477,7 +3501,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3477
3501
|
}]
|
|
3478
3502
|
}], propDecorators: { userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
3479
3503
|
|
|
3480
|
-
const SIZES$
|
|
3504
|
+
const SIZES$2 = {
|
|
3481
3505
|
sm: { box: 'size-6', overlap: '-ms-2', ring: 'ring-1', text: 'text-xs' },
|
|
3482
3506
|
default: { box: 'size-8', overlap: '-ms-2.5', ring: 'ring-2', text: 'text-sm' },
|
|
3483
3507
|
lg: { box: 'size-12', overlap: '-ms-3', ring: 'ring-2', text: 'text-base' },
|
|
@@ -3512,11 +3536,11 @@ class BuiAvatarGroup {
|
|
|
3512
3536
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
3513
3537
|
toInitials = initials;
|
|
3514
3538
|
itemClass(index) {
|
|
3515
|
-
const size = SIZES$
|
|
3539
|
+
const size = SIZES$2[this.size()];
|
|
3516
3540
|
return cn(size.box, size.ring, 'ring-background', index > 0 && size.overlap);
|
|
3517
3541
|
}
|
|
3518
3542
|
moreClass() {
|
|
3519
|
-
const size = SIZES$
|
|
3543
|
+
const size = SIZES$2[this.size()];
|
|
3520
3544
|
return cn('relative z-10 flex shrink-0 items-center justify-center rounded-full bg-muted font-medium text-foreground', size.box, size.ring, 'ring-background', size.text, this.shown().length > 0 && size.overlap);
|
|
3521
3545
|
}
|
|
3522
3546
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiAvatarGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -3750,7 +3774,9 @@ class BuiPopover {
|
|
|
3750
3774
|
.withPositions([POPOVER_POSITIONS[side], POPOVER_POSITIONS[POPOVER_FALLBACK[side]]]);
|
|
3751
3775
|
const overlayReference = this.overlay.create({
|
|
3752
3776
|
positionStrategy,
|
|
3753
|
-
|
|
3777
|
+
// Close (not reposition) on scroll, so the popover doesn't hang detached over the page
|
|
3778
|
+
// once its trigger scrolls out of view.
|
|
3779
|
+
scrollStrategy: this.overlay.scrollStrategies.close(),
|
|
3754
3780
|
});
|
|
3755
3781
|
overlayReference.attach(new TemplatePortal(this.content(), this.viewContainerRef));
|
|
3756
3782
|
overlayReference.outsidePointerEvents().subscribe((event) => {
|
|
@@ -5024,7 +5050,13 @@ const BTN_SIZE$1 = {
|
|
|
5024
5050
|
lg: 'w-9 [&_svg]:size-4',
|
|
5025
5051
|
};
|
|
5026
5052
|
const FIELD_WIDTH = { sm: 'w-9', default: 'w-10', lg: 'w-12' };
|
|
5027
|
-
/**
|
|
5053
|
+
/**
|
|
5054
|
+
* @deprecated Use `<bui-number-input [min]="1" size="sm">` instead — it is the same numeric
|
|
5055
|
+
* stepper, so this duplicate was dropped from the registry and docs. Still exported as a thin
|
|
5056
|
+
* compatibility shim; existing usages keep working.
|
|
5057
|
+
*
|
|
5058
|
+
* A compact − [n] + quantity stepper (`role="group"` with a `spinbutton` field).
|
|
5059
|
+
*/
|
|
5028
5060
|
class BuiQuantitySelector {
|
|
5029
5061
|
/** Current quantity. Two-way bindable with `[(value)]`. */
|
|
5030
5062
|
value = model(1, /* @ts-ignore */
|
|
@@ -5314,79 +5346,39 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
5314
5346
|
}]
|
|
5315
5347
|
}], propDecorators: { userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
5316
5348
|
|
|
5317
|
-
const BASE$1 = 'border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 flex w-full resize-none overflow-hidden rounded-md border bg-transparent shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50';
|
|
5318
|
-
const SIZES$3 = {
|
|
5319
|
-
sm: 'min-h-14 px-2.5 py-1.5 text-sm',
|
|
5320
|
-
default: 'min-h-16 px-3 py-2 text-base md:text-sm',
|
|
5321
|
-
lg: 'min-h-20 px-4 py-2.5 text-base',
|
|
5322
|
-
};
|
|
5323
5349
|
/**
|
|
5324
|
-
*
|
|
5325
|
-
*
|
|
5350
|
+
* @deprecated Use `<textarea buiTextarea [maxRows]="…">` instead — `buiTextarea` already auto-grows
|
|
5351
|
+
* (CSS `field-sizing-content`) and now supports `maxRows`. Kept as a thin alias so existing
|
|
5352
|
+
* `buiAutosizeTextarea` markup keeps working; it inherits every input from {@link BuiTextarea}.
|
|
5353
|
+
*
|
|
5354
|
+
* A textarea that grows with its content, capped at `maxRows`.
|
|
5326
5355
|
*/
|
|
5327
|
-
class BuiAutosizeTextarea {
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
5331
|
-
/** Maximum number of rows before the textarea scrolls instead of growing (null = unlimited). */
|
|
5332
|
-
maxRows = input(null, /* @ts-ignore */
|
|
5333
|
-
...(ngDevMode ? [{ debugName: "maxRows" }] : /* istanbul ignore next */ []));
|
|
5334
|
-
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
5335
|
-
host = inject(ElementRef);
|
|
5336
|
-
computedClass = computed(() => cn(BASE$1, SIZES$3[this.size()], this.userClass()), /* @ts-ignore */
|
|
5337
|
-
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
5338
|
-
constructor() {
|
|
5339
|
-
afterNextRender(() => {
|
|
5340
|
-
this.resize();
|
|
5341
|
-
});
|
|
5342
|
-
}
|
|
5343
|
-
resize() {
|
|
5344
|
-
const element = this.host.nativeElement;
|
|
5345
|
-
element.style.height = 'auto';
|
|
5346
|
-
let target = element.scrollHeight;
|
|
5347
|
-
const maxRows = this.maxRows();
|
|
5348
|
-
if (maxRows !== null) {
|
|
5349
|
-
const styles = getComputedStyle(element);
|
|
5350
|
-
let lineHeight = Number.parseFloat(styles.lineHeight);
|
|
5351
|
-
if (Number.isNaN(lineHeight)) {
|
|
5352
|
-
lineHeight = Number.parseFloat(styles.fontSize) * 1.2;
|
|
5353
|
-
}
|
|
5354
|
-
const padding = Number.parseFloat(styles.paddingTop) + Number.parseFloat(styles.paddingBottom);
|
|
5355
|
-
const border = Number.parseFloat(styles.borderTopWidth) + Number.parseFloat(styles.borderBottomWidth);
|
|
5356
|
-
const cap = lineHeight * maxRows + padding + border;
|
|
5357
|
-
if (target > cap) {
|
|
5358
|
-
target = cap;
|
|
5359
|
-
element.style.overflowY = 'auto';
|
|
5360
|
-
}
|
|
5361
|
-
else {
|
|
5362
|
-
element.style.overflowY = 'hidden';
|
|
5363
|
-
}
|
|
5364
|
-
}
|
|
5365
|
-
element.style.height = `${target}px`;
|
|
5366
|
-
}
|
|
5367
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiAutosizeTextarea, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
5368
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: BuiAutosizeTextarea, isStandalone: true, selector: "textarea[buiAutosizeTextarea]", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, maxRows: { classPropertyName: "maxRows", publicName: "maxRows", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "autosize-textarea" }, listeners: { "input": "resize()" }, properties: { "attr.data-size": "size()", "class": "computedClass()" } }, ngImport: i0 });
|
|
5356
|
+
class BuiAutosizeTextarea extends BuiTextarea {
|
|
5357
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiAutosizeTextarea, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
5358
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.2", type: BuiAutosizeTextarea, isStandalone: true, selector: "textarea[buiAutosizeTextarea]", host: { attributes: { "data-slot": "autosize-textarea" } }, usesInheritance: true, ngImport: i0 });
|
|
5369
5359
|
}
|
|
5370
5360
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiAutosizeTextarea, decorators: [{
|
|
5371
5361
|
type: Directive,
|
|
5372
5362
|
args: [{
|
|
5373
5363
|
selector: 'textarea[buiAutosizeTextarea]',
|
|
5374
|
-
host: {
|
|
5375
|
-
'data-slot': 'autosize-textarea',
|
|
5376
|
-
'[attr.data-size]': 'size()',
|
|
5377
|
-
'[class]': 'computedClass()',
|
|
5378
|
-
'(input)': 'resize()',
|
|
5379
|
-
},
|
|
5364
|
+
host: { 'data-slot': 'autosize-textarea' },
|
|
5380
5365
|
}]
|
|
5381
|
-
}]
|
|
5366
|
+
}] });
|
|
5382
5367
|
|
|
5383
5368
|
class BuiDropdownMenu {
|
|
5384
5369
|
menu = inject(Menu);
|
|
5385
5370
|
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
5386
5371
|
computedClass = computed(() => cn('absolute z-50 mt-1 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-md', this.userClass()), /* @ts-ignore */
|
|
5387
5372
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
5373
|
+
// The menu is absolutely anchored to its trigger; once the page scrolls it would otherwise
|
|
5374
|
+
// drift across the layout (e.g. over a sticky navbar). Closing on scroll matches native menus.
|
|
5375
|
+
onScroll() {
|
|
5376
|
+
if (this.menu.visible()) {
|
|
5377
|
+
this.menu.close();
|
|
5378
|
+
}
|
|
5379
|
+
}
|
|
5388
5380
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiDropdownMenu, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
5389
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: BuiDropdownMenu, isStandalone: true, selector: "[buiDropdownMenu]", inputs: { userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "dropdown-menu" }, properties: { "hidden": "!menu.visible()", "class": "computedClass()" } }, ngImport: i0 });
|
|
5381
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: BuiDropdownMenu, isStandalone: true, selector: "[buiDropdownMenu]", inputs: { userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "dropdown-menu" }, listeners: { "window:scroll": "onScroll()" }, properties: { "hidden": "!menu.visible()", "class": "computedClass()" } }, ngImport: i0 });
|
|
5390
5382
|
}
|
|
5391
5383
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiDropdownMenu, decorators: [{
|
|
5392
5384
|
type: Directive,
|
|
@@ -5396,6 +5388,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
5396
5388
|
'data-slot': 'dropdown-menu',
|
|
5397
5389
|
'[hidden]': '!menu.visible()',
|
|
5398
5390
|
'[class]': 'computedClass()',
|
|
5391
|
+
'(window:scroll)': 'onScroll()',
|
|
5399
5392
|
},
|
|
5400
5393
|
}]
|
|
5401
5394
|
}], propDecorators: { userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
@@ -5447,11 +5440,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
5447
5440
|
* `ngMenuTrigger` opening a `ngMenu` (style the menus with `buiDropdownMenu` /
|
|
5448
5441
|
* `buiDropdownMenuItem`). `MenuBar` is re-exported from `ng-blatui`.
|
|
5449
5442
|
*
|
|
5443
|
+
* Wrap each trigger + its menu in a `relative` element so the menu anchors under its own
|
|
5444
|
+
* trigger (otherwise the absolutely-positioned panel lands over the bar itself).
|
|
5445
|
+
*
|
|
5450
5446
|
* ```html
|
|
5451
5447
|
* <div ngMenuBar buiMenubar>
|
|
5452
|
-
* <
|
|
5453
|
-
*
|
|
5454
|
-
* <div
|
|
5448
|
+
* <div class="relative">
|
|
5449
|
+
* <button ngMenuTrigger [menu]="file" buiMenubarTrigger>File</button>
|
|
5450
|
+
* <div ngMenu #file="ngMenu" buiDropdownMenu>
|
|
5451
|
+
* <div ngMenuItem value="new" buiDropdownMenuItem>New</div>
|
|
5452
|
+
* </div>
|
|
5455
5453
|
* </div>
|
|
5456
5454
|
* </div>
|
|
5457
5455
|
* ```
|
|
@@ -6857,11 +6855,24 @@ class BuiCombobox {
|
|
|
6857
6855
|
[disabled]="disabled()"
|
|
6858
6856
|
[readonly]="!searchable()"
|
|
6859
6857
|
[class.cursor-pointer]="!searchable()"
|
|
6860
|
-
class="flex h-9 w-full rounded-md border border-input bg-transparent
|
|
6858
|
+
class="flex h-9 w-full rounded-md border border-input bg-transparent py-2 ps-3 pe-9 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"
|
|
6861
6859
|
(input)="onInput($event)"
|
|
6862
6860
|
(focus)="openList()"
|
|
6863
6861
|
(keydown)="onKeydown($event)"
|
|
6864
6862
|
/>
|
|
6863
|
+
<svg
|
|
6864
|
+
viewBox="0 0 24 24"
|
|
6865
|
+
fill="none"
|
|
6866
|
+
stroke="currentColor"
|
|
6867
|
+
stroke-width="2"
|
|
6868
|
+
stroke-linecap="round"
|
|
6869
|
+
stroke-linejoin="round"
|
|
6870
|
+
aria-hidden="true"
|
|
6871
|
+
class="pointer-events-none absolute end-3 top-[1.125rem] size-4 -translate-y-1/2 text-muted-foreground transition-transform"
|
|
6872
|
+
[class.rotate-180]="open()"
|
|
6873
|
+
>
|
|
6874
|
+
<path d="m6 9 6 6 6-6" />
|
|
6875
|
+
</svg>
|
|
6865
6876
|
@if (open() && filtered().length > 0) {
|
|
6866
6877
|
<ul
|
|
6867
6878
|
[id]="listId"
|
|
@@ -6941,11 +6952,24 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
6941
6952
|
[disabled]="disabled()"
|
|
6942
6953
|
[readonly]="!searchable()"
|
|
6943
6954
|
[class.cursor-pointer]="!searchable()"
|
|
6944
|
-
class="flex h-9 w-full rounded-md border border-input bg-transparent
|
|
6955
|
+
class="flex h-9 w-full rounded-md border border-input bg-transparent py-2 ps-3 pe-9 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"
|
|
6945
6956
|
(input)="onInput($event)"
|
|
6946
6957
|
(focus)="openList()"
|
|
6947
6958
|
(keydown)="onKeydown($event)"
|
|
6948
6959
|
/>
|
|
6960
|
+
<svg
|
|
6961
|
+
viewBox="0 0 24 24"
|
|
6962
|
+
fill="none"
|
|
6963
|
+
stroke="currentColor"
|
|
6964
|
+
stroke-width="2"
|
|
6965
|
+
stroke-linecap="round"
|
|
6966
|
+
stroke-linejoin="round"
|
|
6967
|
+
aria-hidden="true"
|
|
6968
|
+
class="pointer-events-none absolute end-3 top-[1.125rem] size-4 -translate-y-1/2 text-muted-foreground transition-transform"
|
|
6969
|
+
[class.rotate-180]="open()"
|
|
6970
|
+
>
|
|
6971
|
+
<path d="m6 9 6 6 6-6" />
|
|
6972
|
+
</svg>
|
|
6949
6973
|
@if (open() && filtered().length > 0) {
|
|
6950
6974
|
<ul
|
|
6951
6975
|
[id]="listId"
|
|
@@ -7431,7 +7455,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
7431
7455
|
}]
|
|
7432
7456
|
}], propDecorators: { author: [{ type: i0.Input, args: [{ isSignal: true, alias: "author", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }], avatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatar", required: false }] }], cite: [{ type: i0.Input, args: [{ isSignal: true, alias: "cite", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
7433
7457
|
|
|
7434
|
-
const SIZES$
|
|
7458
|
+
const SIZES$1 = { sm: 'text-sm', default: 'text-base', lg: 'text-2xl' };
|
|
7435
7459
|
const COMPARE_SIZES = { sm: 'text-xs', default: 'text-sm', lg: 'text-base' };
|
|
7436
7460
|
/** A price display with optional compare-at (strikethrough) and a discount badge. */
|
|
7437
7461
|
class BuiPrice {
|
|
@@ -7463,7 +7487,7 @@ class BuiPrice {
|
|
|
7463
7487
|
: 0;
|
|
7464
7488
|
}, /* @ts-ignore */
|
|
7465
7489
|
...(ngDevMode ? [{ debugName: "discount" }] : /* istanbul ignore next */ []));
|
|
7466
|
-
currentClass = computed(() => cn(SIZES$
|
|
7490
|
+
currentClass = computed(() => cn(SIZES$1[this.size()], this.onSale() ? 'text-emerald-700 dark:text-emerald-400' : 'text-foreground'), /* @ts-ignore */
|
|
7467
7491
|
...(ngDevMode ? [{ debugName: "currentClass" }] : /* istanbul ignore next */ []));
|
|
7468
7492
|
compareClass = computed(() => cn(COMPARE_SIZES[this.size()], 'text-muted-foreground'), /* @ts-ignore */
|
|
7469
7493
|
...(ngDevMode ? [{ debugName: "compareClass" }] : /* istanbul ignore next */ []));
|
|
@@ -7626,7 +7650,7 @@ const COLORS = {
|
|
|
7626
7650
|
offline: 'bg-gray-400',
|
|
7627
7651
|
};
|
|
7628
7652
|
const LABELS = { online: 'Online', away: 'Away', busy: 'Busy', offline: 'Offline' };
|
|
7629
|
-
const SIZES
|
|
7653
|
+
const SIZES = { sm: 'size-2', default: 'size-2.5', lg: 'size-3' };
|
|
7630
7654
|
/** A small status dot (online/away/busy/offline). Status is never colour-only — the label is always present. */
|
|
7631
7655
|
class BuiPresence {
|
|
7632
7656
|
/** Presence state, which sets the dot color and default label. */
|
|
@@ -7647,7 +7671,7 @@ class BuiPresence {
|
|
|
7647
7671
|
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
7648
7672
|
colorClass = computed(() => COLORS[this.status()], /* @ts-ignore */
|
|
7649
7673
|
...(ngDevMode ? [{ debugName: "colorClass" }] : /* istanbul ignore next */ []));
|
|
7650
|
-
sizeClass = computed(() => SIZES
|
|
7674
|
+
sizeClass = computed(() => SIZES[this.size()], /* @ts-ignore */
|
|
7651
7675
|
...(ngDevMode ? [{ debugName: "sizeClass" }] : /* istanbul ignore next */ []));
|
|
7652
7676
|
labelText = computed(() => this.label() || LABELS[this.status()], /* @ts-ignore */
|
|
7653
7677
|
...(ngDevMode ? [{ debugName: "labelText" }] : /* istanbul ignore next */ []));
|
|
@@ -8563,7 +8587,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
8563
8587
|
}]
|
|
8564
8588
|
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], width: [{ type: i0.Input, args: [{ isSignal: true, alias: "width", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], area: [{ type: i0.Input, args: [{ isSignal: true, alias: "area", required: false }] }], strokeWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "strokeWidth", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
8565
8589
|
|
|
8566
|
-
const SIZES = { default: 'h-9 px-4 py-2', sm: 'h-8 gap-1.5 px-3', lg: 'h-10 px-6' };
|
|
8567
8590
|
/** A stateful add-to-cart button: idle → adding → added → idle. Emits `triggered` on click. */
|
|
8568
8591
|
class BuiAddToCart {
|
|
8569
8592
|
/** Button text shown in the idle and adding states. */
|
|
@@ -8581,9 +8604,9 @@ class BuiAddToCart {
|
|
|
8581
8604
|
state = signal('idle', /* @ts-ignore */
|
|
8582
8605
|
...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
|
|
8583
8606
|
timers = [];
|
|
8584
|
-
|
|
8585
|
-
|
|
8586
|
-
|
|
8607
|
+
// Composes the button's styling (single source of truth via `buttonVariants`); the busy/added
|
|
8608
|
+
// states only recolor on top — tailwind-merge drops the conflicting base background.
|
|
8609
|
+
btnClass = computed(() => cn(buttonVariants({ size: this.size() }), 'disabled:opacity-90', this.state() === 'added' ? 'bg-emerald-600 text-white hover:bg-emerald-600' : '', this.userClass()), /* @ts-ignore */
|
|
8587
8610
|
...(ngDevMode ? [{ debugName: "btnClass" }] : /* istanbul ignore next */ []));
|
|
8588
8611
|
add() {
|
|
8589
8612
|
if (this.state() !== 'idle') {
|
|
@@ -11303,6 +11326,12 @@ class BuiConfetti {
|
|
|
11303
11326
|
/** Horizontal spread factor of the burst. */
|
|
11304
11327
|
spread = input(70, /* @ts-ignore */
|
|
11305
11328
|
...(ngDevMode ? [{ debugName: "spread" }] : /* istanbul ignore next */ []));
|
|
11329
|
+
/** Direction the particles fly out from the origin. */
|
|
11330
|
+
direction = input('down', /* @ts-ignore */
|
|
11331
|
+
...(ngDevMode ? [{ debugName: "direction" }] : /* istanbul ignore next */ []));
|
|
11332
|
+
/** Rain confetti across the whole viewport instead of bursting from the trigger. */
|
|
11333
|
+
fullscreen = input(false, /* @ts-ignore */
|
|
11334
|
+
...(ngDevMode ? [{ debugName: "fullscreen" }] : /* istanbul ignore next */ []));
|
|
11306
11335
|
/** Particle colours; defaults to the built-in palette. */
|
|
11307
11336
|
colors = input(null, /* @ts-ignore */
|
|
11308
11337
|
...(ngDevMode ? [{ debugName: "colors" }] : /* istanbul ignore next */ []));
|
|
@@ -11313,18 +11342,25 @@ class BuiConfetti {
|
|
|
11313
11342
|
seq = 0;
|
|
11314
11343
|
computedClass = computed(() => cn('relative inline-block', this.userClass()), /* @ts-ignore */
|
|
11315
11344
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
11345
|
+
// Fullscreen rains over a fixed, viewport-covering layer; otherwise particles burst from the
|
|
11346
|
+
// trigger's centre (a zero-size anchor at 50%/50%).
|
|
11347
|
+
layerClass = computed(() => this.fullscreen()
|
|
11348
|
+
? 'pointer-events-none fixed inset-0 z-[100]'
|
|
11349
|
+
: 'pointer-events-none absolute top-1/2 left-1/2 size-0', /* @ts-ignore */
|
|
11350
|
+
...(ngDevMode ? [{ debugName: "layerClass" }] : /* istanbul ignore next */ []));
|
|
11316
11351
|
fire() {
|
|
11317
11352
|
const colors = this.colors() ?? PALETTE$1;
|
|
11353
|
+
const isFullscreen = this.fullscreen();
|
|
11354
|
+
const direction = this.direction();
|
|
11318
11355
|
const batch = Array.from({ length: this.count() }, () => {
|
|
11319
|
-
const
|
|
11320
|
-
const dy = 80 + Math.random() * 120;
|
|
11321
|
-
const rot = Math.random() * 720 - 360;
|
|
11356
|
+
const rot = (Math.random() * 720 - 360).toFixed(0);
|
|
11322
11357
|
const color = colors[Math.floor(Math.random() * colors.length)];
|
|
11323
|
-
const delay = (Math.random() * 0.
|
|
11358
|
+
const delay = (Math.random() * 0.15).toFixed(2);
|
|
11324
11359
|
this.seq += 1;
|
|
11360
|
+
const motion = isFullscreen ? this.rain() : this.burst(direction);
|
|
11325
11361
|
return {
|
|
11326
11362
|
id: this.seq,
|
|
11327
|
-
style:
|
|
11363
|
+
style: `${motion}--rot:${rot}deg;background:${color};animation-delay:${delay}s`,
|
|
11328
11364
|
};
|
|
11329
11365
|
});
|
|
11330
11366
|
this.particles.set(batch);
|
|
@@ -11333,7 +11369,49 @@ class BuiConfetti {
|
|
|
11333
11369
|
}
|
|
11334
11370
|
this.timer = setTimeout(() => {
|
|
11335
11371
|
this.particles.set([]);
|
|
11336
|
-
}, 1200);
|
|
11372
|
+
}, isFullscreen ? 2600 : 1200);
|
|
11373
|
+
}
|
|
11374
|
+
/** Translation vars for a burst from the origin, by direction. */
|
|
11375
|
+
burst(direction) {
|
|
11376
|
+
const spread = this.spread();
|
|
11377
|
+
const rand = Math.random;
|
|
11378
|
+
let dx;
|
|
11379
|
+
let dy;
|
|
11380
|
+
switch (direction) {
|
|
11381
|
+
case 'up': {
|
|
11382
|
+
dx = (rand() - 0.5) * spread * 4;
|
|
11383
|
+
dy = -(80 + rand() * 120);
|
|
11384
|
+
break;
|
|
11385
|
+
}
|
|
11386
|
+
case 'left': {
|
|
11387
|
+
dx = -(100 + rand() * spread * 3);
|
|
11388
|
+
dy = (rand() - 0.5) * spread * 2;
|
|
11389
|
+
break;
|
|
11390
|
+
}
|
|
11391
|
+
case 'right': {
|
|
11392
|
+
dx = 100 + rand() * spread * 3;
|
|
11393
|
+
dy = (rand() - 0.5) * spread * 2;
|
|
11394
|
+
break;
|
|
11395
|
+
}
|
|
11396
|
+
case 'radial': {
|
|
11397
|
+
const angle = rand() * Math.PI * 2;
|
|
11398
|
+
const distance = 80 + rand() * 120;
|
|
11399
|
+
dx = Math.cos(angle) * distance;
|
|
11400
|
+
dy = Math.sin(angle) * distance;
|
|
11401
|
+
break;
|
|
11402
|
+
}
|
|
11403
|
+
default: {
|
|
11404
|
+
dx = (rand() - 0.5) * spread * 4;
|
|
11405
|
+
dy = 80 + rand() * 120;
|
|
11406
|
+
}
|
|
11407
|
+
}
|
|
11408
|
+
return `--dx:${dx.toFixed(0)}px;--dy:${dy.toFixed(0)}px;`;
|
|
11409
|
+
}
|
|
11410
|
+
/** Position + fall vars for a particle raining from the top of the viewport. */
|
|
11411
|
+
rain() {
|
|
11412
|
+
const startX = (Math.random() * 100).toFixed(2);
|
|
11413
|
+
const drift = ((Math.random() - 0.5) * 160).toFixed(0);
|
|
11414
|
+
return `left:${startX}vw;top:-5vh;--dx:${drift}px;--dy:110vh;animation-duration:2.4s;`;
|
|
11337
11415
|
}
|
|
11338
11416
|
ngOnDestroy() {
|
|
11339
11417
|
if (this.timer) {
|
|
@@ -11341,7 +11419,7 @@ class BuiConfetti {
|
|
|
11341
11419
|
}
|
|
11342
11420
|
}
|
|
11343
11421
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiConfetti, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
11344
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiConfetti, isStandalone: true, selector: "bui-confetti", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, spread: { classPropertyName: "spread", publicName: "spread", isSignal: true, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "confetti" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
11422
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiConfetti, isStandalone: true, selector: "bui-confetti", inputs: { count: { classPropertyName: "count", publicName: "count", isSignal: true, isRequired: false, transformFunction: null }, spread: { classPropertyName: "spread", publicName: "spread", isSignal: true, isRequired: false, transformFunction: null }, direction: { classPropertyName: "direction", publicName: "direction", isSignal: true, isRequired: false, transformFunction: null }, fullscreen: { classPropertyName: "fullscreen", publicName: "fullscreen", isSignal: true, isRequired: false, transformFunction: null }, colors: { classPropertyName: "colors", publicName: "colors", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "confetti" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
11345
11423
|
<span (click)="fire()" (keydown.enter)="fire()" (keydown.space)="fire()">
|
|
11346
11424
|
<ng-content>
|
|
11347
11425
|
<button
|
|
@@ -11352,7 +11430,7 @@ class BuiConfetti {
|
|
|
11352
11430
|
</button>
|
|
11353
11431
|
</ng-content>
|
|
11354
11432
|
</span>
|
|
11355
|
-
<div class="
|
|
11433
|
+
<div [class]="layerClass()" aria-hidden="true">
|
|
11356
11434
|
@for (particle of particles(); track particle.id) {
|
|
11357
11435
|
<span
|
|
11358
11436
|
class="bui-confetti-particle absolute size-2 rounded-sm"
|
|
@@ -11375,7 +11453,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
11375
11453
|
</button>
|
|
11376
11454
|
</ng-content>
|
|
11377
11455
|
</span>
|
|
11378
|
-
<div class="
|
|
11456
|
+
<div [class]="layerClass()" aria-hidden="true">
|
|
11379
11457
|
@for (particle of particles(); track particle.id) {
|
|
11380
11458
|
<span
|
|
11381
11459
|
class="bui-confetti-particle absolute size-2 rounded-sm"
|
|
@@ -11384,7 +11462,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
11384
11462
|
}
|
|
11385
11463
|
</div>
|
|
11386
11464
|
`, styles: ["@keyframes bui-confetti-fall{to{transform:translate(var(--dx),var(--dy)) rotate(var(--rot));opacity:0}}.bui-confetti-particle{animation:bui-confetti-fall 1s ease-out forwards}@media(prefers-reduced-motion:reduce){.bui-confetti-particle{animation:none;opacity:0}}\n"] }]
|
|
11387
|
-
}], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], spread: [{ type: i0.Input, args: [{ isSignal: true, alias: "spread", required: false }] }], colors: [{ type: i0.Input, args: [{ isSignal: true, alias: "colors", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
11465
|
+
}], propDecorators: { count: [{ type: i0.Input, args: [{ isSignal: true, alias: "count", required: false }] }], spread: [{ type: i0.Input, args: [{ isSignal: true, alias: "spread", required: false }] }], direction: [{ type: i0.Input, args: [{ isSignal: true, alias: "direction", required: false }] }], fullscreen: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullscreen", required: false }] }], colors: [{ type: i0.Input, args: [{ isSignal: true, alias: "colors", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
11388
11466
|
|
|
11389
11467
|
/** A step indicator. The `value` (1-based) marks the active step. Use `li[buiStepperItem]`. */
|
|
11390
11468
|
class BuiStepper {
|
|
@@ -12859,7 +12937,7 @@ class BuiAudioPlayer {
|
|
|
12859
12937
|
...(ngDevMode ? [{ debugName: "duration" }] : /* istanbul ignore next */ []));
|
|
12860
12938
|
muted = signal(false, /* @ts-ignore */
|
|
12861
12939
|
...(ngDevMode ? [{ debugName: "muted" }] : /* istanbul ignore next */ []));
|
|
12862
|
-
computedClass = computed(() => cn('flex items-center gap-
|
|
12940
|
+
computedClass = computed(() => cn('flex min-w-0 items-center gap-2 rounded-lg border bg-card p-2 sm:gap-3 sm:p-3', this.userClass()), /* @ts-ignore */
|
|
12863
12941
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
12864
12942
|
toggle() {
|
|
12865
12943
|
const element = this.a()?.nativeElement;
|
|
@@ -12950,7 +13028,7 @@ class BuiAudioPlayer {
|
|
|
12950
13028
|
step="0.1"
|
|
12951
13029
|
[max]="duration() || 0"
|
|
12952
13030
|
[value]="current()"
|
|
12953
|
-
class="h-1 flex-1 accent-primary"
|
|
13031
|
+
class="h-1 min-w-0 flex-1 accent-primary"
|
|
12954
13032
|
[attr.aria-label]="seekText()"
|
|
12955
13033
|
(input)="seek($event)"
|
|
12956
13034
|
/>
|
|
@@ -13022,7 +13100,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
13022
13100
|
step="0.1"
|
|
13023
13101
|
[max]="duration() || 0"
|
|
13024
13102
|
[value]="current()"
|
|
13025
|
-
class="h-1 flex-1 accent-primary"
|
|
13103
|
+
class="h-1 min-w-0 flex-1 accent-primary"
|
|
13026
13104
|
[attr.aria-label]="seekText()"
|
|
13027
13105
|
(input)="seek($event)"
|
|
13028
13106
|
/>
|
|
@@ -13686,12 +13764,20 @@ class BuiNotificationCenter {
|
|
|
13686
13764
|
unreadText = buiLabel('notificationCenterUnread', this.unreadLabel);
|
|
13687
13765
|
markAllReadText = buiLabel('notificationCenterMarkAllRead', this.markAllReadLabel);
|
|
13688
13766
|
emptyText = buiLabel('notificationCenterEmpty', this.emptyLabel);
|
|
13767
|
+
host = inject(ElementRef);
|
|
13689
13768
|
markedRead = signal(new Set(), /* @ts-ignore */
|
|
13690
13769
|
...(ngDevMode ? [{ debugName: "markedRead" }] : /* istanbul ignore next */ []));
|
|
13691
13770
|
unread = computed(() => this.notifications().filter((_, index) => !this.isRead(index)).length, /* @ts-ignore */
|
|
13692
13771
|
...(ngDevMode ? [{ debugName: "unread" }] : /* istanbul ignore next */ []));
|
|
13693
13772
|
computedClass = computed(() => cn('relative inline-block', this.userClass()), /* @ts-ignore */
|
|
13694
13773
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
13774
|
+
// Close when a click lands outside the bell + panel. The trigger's own click is contained in
|
|
13775
|
+
// the host, so it toggles open without this handler immediately closing it again.
|
|
13776
|
+
onDocumentClick(event) {
|
|
13777
|
+
if (this.open() && !this.host.nativeElement.contains(event.target)) {
|
|
13778
|
+
this.open.set(false);
|
|
13779
|
+
}
|
|
13780
|
+
}
|
|
13695
13781
|
isRead(index) {
|
|
13696
13782
|
return this.markedRead().has(index) || (this.notifications()[index]?.read ?? false);
|
|
13697
13783
|
}
|
|
@@ -13699,7 +13785,7 @@ class BuiNotificationCenter {
|
|
|
13699
13785
|
this.markedRead.set(new Set(this.notifications().map((_, index) => index)));
|
|
13700
13786
|
}
|
|
13701
13787
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiNotificationCenter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13702
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiNotificationCenter, isStandalone: true, selector: "bui-notification-center", inputs: { notifications: { classPropertyName: "notifications", publicName: "notifications", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, unreadLabel: { classPropertyName: "unreadLabel", publicName: "unreadLabel", isSignal: true, isRequired: false, transformFunction: null }, markAllReadLabel: { classPropertyName: "markAllReadLabel", publicName: "markAllReadLabel", isSignal: true, isRequired: false, transformFunction: null }, emptyLabel: { classPropertyName: "emptyLabel", publicName: "emptyLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { attributes: { "data-slot": "notification-center" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
13788
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiNotificationCenter, isStandalone: true, selector: "bui-notification-center", inputs: { notifications: { classPropertyName: "notifications", publicName: "notifications", isSignal: true, isRequired: false, transformFunction: null }, open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, unreadLabel: { classPropertyName: "unreadLabel", publicName: "unreadLabel", isSignal: true, isRequired: false, transformFunction: null }, markAllReadLabel: { classPropertyName: "markAllReadLabel", publicName: "markAllReadLabel", isSignal: true, isRequired: false, transformFunction: null }, emptyLabel: { classPropertyName: "emptyLabel", publicName: "emptyLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { attributes: { "data-slot": "notification-center" }, listeners: { "document:click": "onDocumentClick($event)", "document:keydown.escape": "open.set(false)", "window:scroll": "open.set(false)" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
13703
13789
|
<button
|
|
13704
13790
|
type="button"
|
|
13705
13791
|
class="relative inline-flex size-9 items-center justify-center rounded-md border border-input hover:bg-accent"
|
|
@@ -13774,7 +13860,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
13774
13860
|
type: Component,
|
|
13775
13861
|
args: [{
|
|
13776
13862
|
selector: 'bui-notification-center',
|
|
13777
|
-
host: {
|
|
13863
|
+
host: {
|
|
13864
|
+
'data-slot': 'notification-center',
|
|
13865
|
+
'[class]': 'computedClass()',
|
|
13866
|
+
'(document:click)': 'onDocumentClick($event)',
|
|
13867
|
+
'(document:keydown.escape)': 'open.set(false)',
|
|
13868
|
+
'(window:scroll)': 'open.set(false)',
|
|
13869
|
+
},
|
|
13778
13870
|
template: `
|
|
13779
13871
|
<button
|
|
13780
13872
|
type="button"
|
|
@@ -14606,7 +14698,21 @@ class BuiTreeTable {
|
|
|
14606
14698
|
/** Accessible label for the expand/collapse toggle button. */
|
|
14607
14699
|
toggleLabel = input(/* @ts-ignore */
|
|
14608
14700
|
...(ngDevMode ? [undefined, { debugName: "toggleLabel" }] : /* istanbul ignore next */ []));
|
|
14701
|
+
/** Show a button that copies the full hierarchy as a markdown ASCII tree. */
|
|
14702
|
+
copyable = input(false, /* @ts-ignore */
|
|
14703
|
+
...(ngDevMode ? [{ debugName: "copyable" }] : /* istanbul ignore next */ []));
|
|
14704
|
+
/** Label override for the copy button (idle state). */
|
|
14705
|
+
copyLabel = input(/* @ts-ignore */
|
|
14706
|
+
...(ngDevMode ? [undefined, { debugName: "copyLabel" }] : /* istanbul ignore next */ []));
|
|
14707
|
+
/** Label override for the copy button after copying. */
|
|
14708
|
+
copiedLabel = input(/* @ts-ignore */
|
|
14709
|
+
...(ngDevMode ? [undefined, { debugName: "copiedLabel" }] : /* istanbul ignore next */ []));
|
|
14609
14710
|
toggleText = buiLabel('treeTableToggle', this.toggleLabel);
|
|
14711
|
+
copyText = buiLabel('treeTableCopy', this.copyLabel);
|
|
14712
|
+
copiedText = buiLabel('treeTableCopied', this.copiedLabel);
|
|
14713
|
+
copied = signal(false, /* @ts-ignore */
|
|
14714
|
+
...(ngDevMode ? [{ debugName: "copied" }] : /* istanbul ignore next */ []));
|
|
14715
|
+
copiedTimer;
|
|
14610
14716
|
overrides = signal(new Map(), /* @ts-ignore */
|
|
14611
14717
|
...(ngDevMode ? [{ debugName: "overrides" }] : /* istanbul ignore next */ []));
|
|
14612
14718
|
defaults = computed(() => {
|
|
@@ -14651,6 +14757,47 @@ class BuiTreeTable {
|
|
|
14651
14757
|
next.set(path, !this.isOpen(path));
|
|
14652
14758
|
this.overrides.set(next);
|
|
14653
14759
|
}
|
|
14760
|
+
/**
|
|
14761
|
+
* Render the full row hierarchy as a markdown ASCII tree (`├──`/`└──`), using the first
|
|
14762
|
+
* column's value as each node's label and a trailing `/` for rows that have children.
|
|
14763
|
+
*/
|
|
14764
|
+
toMarkdownTree() {
|
|
14765
|
+
const key = this.columns()[0]?.key ?? '';
|
|
14766
|
+
const lines = [];
|
|
14767
|
+
const render = (rows, prefix, isRoot) => {
|
|
14768
|
+
for (const [index, row] of rows.entries()) {
|
|
14769
|
+
const children = row.children ?? [];
|
|
14770
|
+
const hasChildren = children.length > 0;
|
|
14771
|
+
const label = this.cell(row, key) + (hasChildren ? '/' : '');
|
|
14772
|
+
if (isRoot) {
|
|
14773
|
+
lines.push(label);
|
|
14774
|
+
if (hasChildren) {
|
|
14775
|
+
render(children, '', false);
|
|
14776
|
+
}
|
|
14777
|
+
continue;
|
|
14778
|
+
}
|
|
14779
|
+
const isLast = index === rows.length - 1;
|
|
14780
|
+
lines.push(`${prefix}${isLast ? '└── ' : '├── '}${label}`);
|
|
14781
|
+
if (hasChildren) {
|
|
14782
|
+
const childIndent = isLast ? ' '.repeat(4) : `│${' '.repeat(3)}`;
|
|
14783
|
+
render(children, prefix + childIndent, false);
|
|
14784
|
+
}
|
|
14785
|
+
}
|
|
14786
|
+
};
|
|
14787
|
+
render(this.rows(), '', true);
|
|
14788
|
+
return lines.join('\n');
|
|
14789
|
+
}
|
|
14790
|
+
copyTree() {
|
|
14791
|
+
void navigator.clipboard.writeText(this.toMarkdownTree());
|
|
14792
|
+
this.copied.set(true);
|
|
14793
|
+
clearTimeout(this.copiedTimer);
|
|
14794
|
+
this.copiedTimer = setTimeout(() => {
|
|
14795
|
+
this.copied.set(false);
|
|
14796
|
+
}, 1500);
|
|
14797
|
+
}
|
|
14798
|
+
ngOnDestroy() {
|
|
14799
|
+
clearTimeout(this.copiedTimer);
|
|
14800
|
+
}
|
|
14654
14801
|
alignClass(align) {
|
|
14655
14802
|
return ALIGN$2[align ?? 'left'];
|
|
14656
14803
|
}
|
|
@@ -14665,7 +14812,47 @@ class BuiTreeTable {
|
|
|
14665
14812
|
return '';
|
|
14666
14813
|
}
|
|
14667
14814
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiTreeTable, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
14668
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiTreeTable, isStandalone: true, selector: "bui-tree-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, toggleLabel: { classPropertyName: "toggleLabel", publicName: "toggleLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "tree-table" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
14815
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiTreeTable, isStandalone: true, selector: "bui-tree-table", inputs: { columns: { classPropertyName: "columns", publicName: "columns", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, toggleLabel: { classPropertyName: "toggleLabel", publicName: "toggleLabel", isSignal: true, isRequired: false, transformFunction: null }, copyable: { classPropertyName: "copyable", publicName: "copyable", isSignal: true, isRequired: false, transformFunction: null }, copyLabel: { classPropertyName: "copyLabel", publicName: "copyLabel", isSignal: true, isRequired: false, transformFunction: null }, copiedLabel: { classPropertyName: "copiedLabel", publicName: "copiedLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "tree-table" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
14816
|
+
@if (copyable()) {
|
|
14817
|
+
<div class="mb-2 flex justify-end">
|
|
14818
|
+
<button
|
|
14819
|
+
type="button"
|
|
14820
|
+
class="inline-flex items-center gap-1.5 rounded-md border border-input px-2.5 py-1 text-xs font-medium hover:bg-accent"
|
|
14821
|
+
(click)="copyTree()"
|
|
14822
|
+
>
|
|
14823
|
+
@if (copied()) {
|
|
14824
|
+
<svg
|
|
14825
|
+
class="size-3.5 text-emerald-500"
|
|
14826
|
+
viewBox="0 0 24 24"
|
|
14827
|
+
fill="none"
|
|
14828
|
+
stroke="currentColor"
|
|
14829
|
+
stroke-width="2"
|
|
14830
|
+
stroke-linecap="round"
|
|
14831
|
+
stroke-linejoin="round"
|
|
14832
|
+
aria-hidden="true"
|
|
14833
|
+
>
|
|
14834
|
+
<path d="M20 6 9 17l-5-5" />
|
|
14835
|
+
</svg>
|
|
14836
|
+
{{ copiedText() }}
|
|
14837
|
+
} @else {
|
|
14838
|
+
<svg
|
|
14839
|
+
class="size-3.5"
|
|
14840
|
+
viewBox="0 0 24 24"
|
|
14841
|
+
fill="none"
|
|
14842
|
+
stroke="currentColor"
|
|
14843
|
+
stroke-width="2"
|
|
14844
|
+
stroke-linecap="round"
|
|
14845
|
+
stroke-linejoin="round"
|
|
14846
|
+
aria-hidden="true"
|
|
14847
|
+
>
|
|
14848
|
+
<rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
|
|
14849
|
+
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
|
|
14850
|
+
</svg>
|
|
14851
|
+
{{ copyText() }}
|
|
14852
|
+
}
|
|
14853
|
+
</button>
|
|
14854
|
+
</div>
|
|
14855
|
+
}
|
|
14669
14856
|
<table class="w-full text-sm">
|
|
14670
14857
|
<thead>
|
|
14671
14858
|
<tr class="border-b">
|
|
@@ -14728,6 +14915,46 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
14728
14915
|
selector: 'bui-tree-table',
|
|
14729
14916
|
host: { 'data-slot': 'tree-table', '[class]': 'computedClass()' },
|
|
14730
14917
|
template: `
|
|
14918
|
+
@if (copyable()) {
|
|
14919
|
+
<div class="mb-2 flex justify-end">
|
|
14920
|
+
<button
|
|
14921
|
+
type="button"
|
|
14922
|
+
class="inline-flex items-center gap-1.5 rounded-md border border-input px-2.5 py-1 text-xs font-medium hover:bg-accent"
|
|
14923
|
+
(click)="copyTree()"
|
|
14924
|
+
>
|
|
14925
|
+
@if (copied()) {
|
|
14926
|
+
<svg
|
|
14927
|
+
class="size-3.5 text-emerald-500"
|
|
14928
|
+
viewBox="0 0 24 24"
|
|
14929
|
+
fill="none"
|
|
14930
|
+
stroke="currentColor"
|
|
14931
|
+
stroke-width="2"
|
|
14932
|
+
stroke-linecap="round"
|
|
14933
|
+
stroke-linejoin="round"
|
|
14934
|
+
aria-hidden="true"
|
|
14935
|
+
>
|
|
14936
|
+
<path d="M20 6 9 17l-5-5" />
|
|
14937
|
+
</svg>
|
|
14938
|
+
{{ copiedText() }}
|
|
14939
|
+
} @else {
|
|
14940
|
+
<svg
|
|
14941
|
+
class="size-3.5"
|
|
14942
|
+
viewBox="0 0 24 24"
|
|
14943
|
+
fill="none"
|
|
14944
|
+
stroke="currentColor"
|
|
14945
|
+
stroke-width="2"
|
|
14946
|
+
stroke-linecap="round"
|
|
14947
|
+
stroke-linejoin="round"
|
|
14948
|
+
aria-hidden="true"
|
|
14949
|
+
>
|
|
14950
|
+
<rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
|
|
14951
|
+
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
|
|
14952
|
+
</svg>
|
|
14953
|
+
{{ copyText() }}
|
|
14954
|
+
}
|
|
14955
|
+
</button>
|
|
14956
|
+
</div>
|
|
14957
|
+
}
|
|
14731
14958
|
<table class="w-full text-sm">
|
|
14732
14959
|
<thead>
|
|
14733
14960
|
<tr class="border-b">
|
|
@@ -14784,7 +15011,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
14784
15011
|
</table>
|
|
14785
15012
|
`,
|
|
14786
15013
|
}]
|
|
14787
|
-
}], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], toggleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggleLabel", required: false }] }] } });
|
|
15014
|
+
}], propDecorators: { columns: [{ type: i0.Input, args: [{ isSignal: true, alias: "columns", required: false }] }], rows: [{ type: i0.Input, args: [{ isSignal: true, alias: "rows", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], toggleLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "toggleLabel", required: false }] }], copyable: [{ type: i0.Input, args: [{ isSignal: true, alias: "copyable", required: false }] }], copyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "copyLabel", required: false }] }], copiedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "copiedLabel", required: false }] }] } });
|
|
14788
15015
|
|
|
14789
15016
|
// HTML is escaped first, then a safe subset of markdown is applied, so user input can't inject markup.
|
|
14790
15017
|
function renderMarkdown(markdown) {
|
|
@@ -16088,7 +16315,7 @@ class BuiContextMenu {
|
|
|
16088
16315
|
this.open.set(false);
|
|
16089
16316
|
}
|
|
16090
16317
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiContextMenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
16091
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiContextMenu, isStandalone: true, selector: "bui-context-menu", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selected" }, host: { attributes: { "data-slot": "context-menu" }, listeners: { "contextmenu": "onContext($event)", "document:click": "open.set(false)", "document:keydown.escape": "open.set(false)" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
16318
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiContextMenu, isStandalone: true, selector: "bui-context-menu", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { selected: "selected" }, host: { attributes: { "data-slot": "context-menu" }, listeners: { "contextmenu": "onContext($event)", "document:click": "open.set(false)", "document:keydown.escape": "open.set(false)", "window:scroll": "open.set(false)" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
16092
16319
|
<ng-content />
|
|
16093
16320
|
@if (open()) {
|
|
16094
16321
|
<div
|
|
@@ -16201,6 +16428,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
16201
16428
|
'(contextmenu)': 'onContext($event)',
|
|
16202
16429
|
'(document:click)': 'open.set(false)',
|
|
16203
16430
|
'(document:keydown.escape)': 'open.set(false)',
|
|
16431
|
+
// The menu is fixed to viewport coordinates captured at open time; close it on scroll
|
|
16432
|
+
// instead of letting it hang at a now-wrong position.
|
|
16433
|
+
'(window:scroll)': 'open.set(false)',
|
|
16204
16434
|
},
|
|
16205
16435
|
template: `
|
|
16206
16436
|
<ng-content />
|
|
@@ -18345,36 +18575,38 @@ class BuiNavigationMenu {
|
|
|
18345
18575
|
</svg>
|
|
18346
18576
|
</button>
|
|
18347
18577
|
@if (active() === i) {
|
|
18348
|
-
|
|
18349
|
-
|
|
18350
|
-
>
|
|
18351
|
-
|
|
18352
|
-
|
|
18353
|
-
|
|
18354
|
-
|
|
18355
|
-
|
|
18356
|
-
|
|
18357
|
-
|
|
18358
|
-
|
|
18359
|
-
|
|
18360
|
-
|
|
18361
|
-
|
|
18362
|
-
|
|
18363
|
-
|
|
18364
|
-
<ul class="space-y-1">
|
|
18365
|
-
@for (link of item.links; track link.label) {
|
|
18366
|
-
<li>
|
|
18367
|
-
<a [href]="href(link.href)" class="block rounded-md p-2 hover:bg-accent">
|
|
18368
|
-
<span class="text-sm font-medium">{{ link.label }}</span>
|
|
18369
|
-
@if (link.description) {
|
|
18370
|
-
<span class="block text-xs text-muted-foreground">{{
|
|
18371
|
-
link.description
|
|
18372
|
-
}}</span>
|
|
18373
|
-
}
|
|
18374
|
-
</a>
|
|
18375
|
-
</li>
|
|
18578
|
+
<!-- pt-1.5 (not mt-1.5) keeps the gap below the trigger hoverable, so moving the
|
|
18579
|
+
cursor onto the panel doesn't leave the menu and snap it shut. -->
|
|
18580
|
+
<div class="absolute start-0 top-full z-50 w-64 pt-1.5">
|
|
18581
|
+
<div class="rounded-lg border bg-popover p-2 shadow-md">
|
|
18582
|
+
@if (item.featured; as featured) {
|
|
18583
|
+
<a
|
|
18584
|
+
[href]="href(featured.href)"
|
|
18585
|
+
class="mb-1 block rounded-md bg-accent/50 p-3 hover:bg-accent"
|
|
18586
|
+
>
|
|
18587
|
+
<span class="text-sm font-semibold">{{ featured.label }}</span>
|
|
18588
|
+
@if (featured.description) {
|
|
18589
|
+
<span class="mt-0.5 block text-xs text-muted-foreground">{{
|
|
18590
|
+
featured.description
|
|
18591
|
+
}}</span>
|
|
18592
|
+
}
|
|
18593
|
+
</a>
|
|
18376
18594
|
}
|
|
18377
|
-
|
|
18595
|
+
<ul class="space-y-1">
|
|
18596
|
+
@for (link of item.links; track link.label) {
|
|
18597
|
+
<li>
|
|
18598
|
+
<a [href]="href(link.href)" class="block rounded-md p-2 hover:bg-accent">
|
|
18599
|
+
<span class="text-sm font-medium">{{ link.label }}</span>
|
|
18600
|
+
@if (link.description) {
|
|
18601
|
+
<span class="block text-xs text-muted-foreground">{{
|
|
18602
|
+
link.description
|
|
18603
|
+
}}</span>
|
|
18604
|
+
}
|
|
18605
|
+
</a>
|
|
18606
|
+
</li>
|
|
18607
|
+
}
|
|
18608
|
+
</ul>
|
|
18609
|
+
</div>
|
|
18378
18610
|
</div>
|
|
18379
18611
|
}
|
|
18380
18612
|
} @else {
|
|
@@ -18425,36 +18657,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
18425
18657
|
</svg>
|
|
18426
18658
|
</button>
|
|
18427
18659
|
@if (active() === i) {
|
|
18428
|
-
|
|
18429
|
-
|
|
18430
|
-
>
|
|
18431
|
-
|
|
18432
|
-
|
|
18433
|
-
|
|
18434
|
-
|
|
18435
|
-
|
|
18436
|
-
|
|
18437
|
-
|
|
18438
|
-
|
|
18439
|
-
|
|
18440
|
-
|
|
18441
|
-
|
|
18442
|
-
|
|
18443
|
-
|
|
18444
|
-
<ul class="space-y-1">
|
|
18445
|
-
@for (link of item.links; track link.label) {
|
|
18446
|
-
<li>
|
|
18447
|
-
<a [href]="href(link.href)" class="block rounded-md p-2 hover:bg-accent">
|
|
18448
|
-
<span class="text-sm font-medium">{{ link.label }}</span>
|
|
18449
|
-
@if (link.description) {
|
|
18450
|
-
<span class="block text-xs text-muted-foreground">{{
|
|
18451
|
-
link.description
|
|
18452
|
-
}}</span>
|
|
18453
|
-
}
|
|
18454
|
-
</a>
|
|
18455
|
-
</li>
|
|
18660
|
+
<!-- pt-1.5 (not mt-1.5) keeps the gap below the trigger hoverable, so moving the
|
|
18661
|
+
cursor onto the panel doesn't leave the menu and snap it shut. -->
|
|
18662
|
+
<div class="absolute start-0 top-full z-50 w-64 pt-1.5">
|
|
18663
|
+
<div class="rounded-lg border bg-popover p-2 shadow-md">
|
|
18664
|
+
@if (item.featured; as featured) {
|
|
18665
|
+
<a
|
|
18666
|
+
[href]="href(featured.href)"
|
|
18667
|
+
class="mb-1 block rounded-md bg-accent/50 p-3 hover:bg-accent"
|
|
18668
|
+
>
|
|
18669
|
+
<span class="text-sm font-semibold">{{ featured.label }}</span>
|
|
18670
|
+
@if (featured.description) {
|
|
18671
|
+
<span class="mt-0.5 block text-xs text-muted-foreground">{{
|
|
18672
|
+
featured.description
|
|
18673
|
+
}}</span>
|
|
18674
|
+
}
|
|
18675
|
+
</a>
|
|
18456
18676
|
}
|
|
18457
|
-
|
|
18677
|
+
<ul class="space-y-1">
|
|
18678
|
+
@for (link of item.links; track link.label) {
|
|
18679
|
+
<li>
|
|
18680
|
+
<a [href]="href(link.href)" class="block rounded-md p-2 hover:bg-accent">
|
|
18681
|
+
<span class="text-sm font-medium">{{ link.label }}</span>
|
|
18682
|
+
@if (link.description) {
|
|
18683
|
+
<span class="block text-xs text-muted-foreground">{{
|
|
18684
|
+
link.description
|
|
18685
|
+
}}</span>
|
|
18686
|
+
}
|
|
18687
|
+
</a>
|
|
18688
|
+
</li>
|
|
18689
|
+
}
|
|
18690
|
+
</ul>
|
|
18691
|
+
</div>
|
|
18458
18692
|
</div>
|
|
18459
18693
|
}
|
|
18460
18694
|
} @else {
|
|
@@ -18556,11 +18790,11 @@ class BuiMentionInput {
|
|
|
18556
18790
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiMentionInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18557
18791
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiMentionInput, isStandalone: true, selector: "bui-mention-input", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, mentions: { classPropertyName: "mentions", publicName: "mentions", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, rows: { classPropertyName: "rows", publicName: "rows", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { attributes: { "data-slot": "mention-input" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
18558
18792
|
<textarea
|
|
18793
|
+
buiTextarea
|
|
18559
18794
|
[value]="value()"
|
|
18560
18795
|
[placeholder]="placeholder()"
|
|
18561
18796
|
[rows]="rows()"
|
|
18562
18797
|
[attr.name]="name() || null"
|
|
18563
|
-
class="w-full resize-y rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50"
|
|
18564
18798
|
(input)="onInput($event)"
|
|
18565
18799
|
(keydown)="onKeydown($event)"
|
|
18566
18800
|
></textarea>
|
|
@@ -18583,20 +18817,21 @@ class BuiMentionInput {
|
|
|
18583
18817
|
}
|
|
18584
18818
|
</ul>
|
|
18585
18819
|
}
|
|
18586
|
-
`, isInline: true });
|
|
18820
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: BuiTextarea, selector: "textarea[buiTextarea]", inputs: ["size", "maxRows", "class"] }] });
|
|
18587
18821
|
}
|
|
18588
18822
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiMentionInput, decorators: [{
|
|
18589
18823
|
type: Component,
|
|
18590
18824
|
args: [{
|
|
18591
18825
|
selector: 'bui-mention-input',
|
|
18592
18826
|
host: { 'data-slot': 'mention-input', '[class]': 'computedClass()' },
|
|
18827
|
+
imports: [BuiTextarea],
|
|
18593
18828
|
template: `
|
|
18594
18829
|
<textarea
|
|
18830
|
+
buiTextarea
|
|
18595
18831
|
[value]="value()"
|
|
18596
18832
|
[placeholder]="placeholder()"
|
|
18597
18833
|
[rows]="rows()"
|
|
18598
18834
|
[attr.name]="name() || null"
|
|
18599
|
-
class="w-full resize-y rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50"
|
|
18600
18835
|
(input)="onInput($event)"
|
|
18601
18836
|
(keydown)="onKeydown($event)"
|
|
18602
18837
|
></textarea>
|
|
@@ -19398,6 +19633,11 @@ class BuiOnboardingTour {
|
|
|
19398
19633
|
prev() {
|
|
19399
19634
|
this.step.set(Math.max(0, this.step() - 1));
|
|
19400
19635
|
}
|
|
19636
|
+
onViewportChange() {
|
|
19637
|
+
if (this.open()) {
|
|
19638
|
+
this.measure();
|
|
19639
|
+
}
|
|
19640
|
+
}
|
|
19401
19641
|
finish() {
|
|
19402
19642
|
this.open.set(false);
|
|
19403
19643
|
this.step.set(0);
|
|
@@ -19414,7 +19654,7 @@ class BuiOnboardingTour {
|
|
|
19414
19654
|
}
|
|
19415
19655
|
}
|
|
19416
19656
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiOnboardingTour, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
19417
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiOnboardingTour, isStandalone: true, selector: "bui-onboarding-tour", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { attributes: { "data-slot": "onboarding-tour" }, listeners: { "document:keydown.escape": "finish()" } }, ngImport: i0, template: `
|
|
19657
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiOnboardingTour, isStandalone: true, selector: "bui-onboarding-tour", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, steps: { classPropertyName: "steps", publicName: "steps", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange" }, host: { attributes: { "data-slot": "onboarding-tour" }, listeners: { "document:keydown.escape": "finish()", "window:scroll": "onViewportChange()", "window:resize": "onViewportChange()" } }, ngImport: i0, template: `
|
|
19418
19658
|
@if (open() && current()) {
|
|
19419
19659
|
<div
|
|
19420
19660
|
class="pointer-events-none fixed z-[60] rounded-md ring-2 ring-primary transition-all"
|
|
@@ -19467,7 +19707,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
19467
19707
|
type: Component,
|
|
19468
19708
|
args: [{
|
|
19469
19709
|
selector: 'bui-onboarding-tour',
|
|
19470
|
-
host: {
|
|
19710
|
+
host: {
|
|
19711
|
+
'data-slot': 'onboarding-tour',
|
|
19712
|
+
'(document:keydown.escape)': 'finish()',
|
|
19713
|
+
// The spotlight/card use viewport (fixed) coordinates; re-measure on scroll & resize so the
|
|
19714
|
+
// highlight tracks its target instead of drifting out of alignment.
|
|
19715
|
+
'(window:scroll)': 'onViewportChange()',
|
|
19716
|
+
'(window:resize)': 'onViewportChange()',
|
|
19717
|
+
},
|
|
19471
19718
|
template: `
|
|
19472
19719
|
@if (open() && current()) {
|
|
19473
19720
|
<div
|