ng-blatui 1.9.0 → 1.11.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 +387 -5
- package/fesm2022/ng-blatui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/ng-blatui.d.ts +86 -1
package/fesm2022/ng-blatui.mjs
CHANGED
|
@@ -81,7 +81,7 @@ const VARIANTS = {
|
|
|
81
81
|
destructive: 'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
|
82
82
|
outline: 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',
|
|
83
83
|
};
|
|
84
|
-
const TONES$
|
|
84
|
+
const TONES$2 = {
|
|
85
85
|
success: {
|
|
86
86
|
soft: 'border-transparent bg-success/10 text-success dark:bg-success/15',
|
|
87
87
|
solid: 'border-transparent bg-success text-success-foreground',
|
|
@@ -143,7 +143,7 @@ class BuiBadge {
|
|
|
143
143
|
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
144
144
|
computedClass = computed(() => {
|
|
145
145
|
const tone = this.tone();
|
|
146
|
-
const toneOrVariant = tone === null ? brandClass(this.variant()) : TONES$
|
|
146
|
+
const toneOrVariant = tone === null ? brandClass(this.variant()) : TONES$2[tone][intensityFor(this.variant())];
|
|
147
147
|
return cn(BASE, SIZES$2[this.size()], toneOrVariant, this.userClass());
|
|
148
148
|
}, /* @ts-ignore */
|
|
149
149
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
@@ -2801,7 +2801,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
2801
2801
|
}]
|
|
2802
2802
|
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
2803
2803
|
|
|
2804
|
-
const TONES = {
|
|
2804
|
+
const TONES$1 = {
|
|
2805
2805
|
default: 'bg-muted text-foreground border-border',
|
|
2806
2806
|
primary: 'bg-primary text-primary-foreground border-transparent',
|
|
2807
2807
|
info: 'bg-info/10 text-info border-info/25',
|
|
@@ -2824,7 +2824,7 @@ class BuiBanner {
|
|
|
2824
2824
|
show = signal(true, /* @ts-ignore */
|
|
2825
2825
|
...(ngDevMode ? [{ debugName: "show" }] : /* istanbul ignore next */ []));
|
|
2826
2826
|
isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
2827
|
-
computedClass = computed(() => cn('relative flex w-full items-center gap-3 border-b px-4 py-2.5 text-sm', TONES[this.tone()], this.userClass()), /* @ts-ignore */
|
|
2827
|
+
computedClass = computed(() => cn('relative flex w-full items-center gap-3 border-b px-4 py-2.5 text-sm', TONES$1[this.tone()], this.userClass()), /* @ts-ignore */
|
|
2828
2828
|
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
2829
2829
|
ngOnInit() {
|
|
2830
2830
|
const key = this.persistKey();
|
|
@@ -3613,6 +3613,388 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3613
3613
|
}]
|
|
3614
3614
|
}], 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 }] }] } });
|
|
3615
3615
|
|
|
3616
|
+
/** Visually hides content while keeping it available to assistive tech (sr-only). */
|
|
3617
|
+
class BuiVisuallyHidden {
|
|
3618
|
+
focusable = input(false, /* @ts-ignore */
|
|
3619
|
+
...(ngDevMode ? [{ debugName: "focusable" }] : /* istanbul ignore next */ []));
|
|
3620
|
+
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3621
|
+
computedClass = computed(() => cn('sr-only', this.focusable() &&
|
|
3622
|
+
'focus:not-sr-only focus:fixed focus:start-4 focus:top-4 focus:z-50 focus:rounded-md focus:bg-primary focus:px-4 focus:py-2 focus:text-primary-foreground focus:shadow-md', this.userClass()), /* @ts-ignore */
|
|
3623
|
+
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
3624
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiVisuallyHidden, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3625
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: BuiVisuallyHidden, isStandalone: true, selector: "[buiVisuallyHidden]", inputs: { focusable: { classPropertyName: "focusable", publicName: "focusable", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "visually-hidden" }, properties: { "class": "computedClass()" } }, ngImport: i0 });
|
|
3626
|
+
}
|
|
3627
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiVisuallyHidden, decorators: [{
|
|
3628
|
+
type: Directive,
|
|
3629
|
+
args: [{
|
|
3630
|
+
selector: '[buiVisuallyHidden]',
|
|
3631
|
+
host: { 'data-slot': 'visually-hidden', '[class]': 'computedClass()' },
|
|
3632
|
+
}]
|
|
3633
|
+
}], propDecorators: { focusable: [{ type: i0.Input, args: [{ isSignal: true, alias: "focusable", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
3634
|
+
|
|
3635
|
+
const TONES = {
|
|
3636
|
+
good: 'bg-emerald-600',
|
|
3637
|
+
warning: 'bg-amber-500',
|
|
3638
|
+
danger: 'bg-destructive',
|
|
3639
|
+
default: 'bg-primary',
|
|
3640
|
+
};
|
|
3641
|
+
/** A labelled meter (`role="meter"`) for a measurement within a known range. */
|
|
3642
|
+
class BuiMeter {
|
|
3643
|
+
value = input(0, /* @ts-ignore */
|
|
3644
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
3645
|
+
min = input(0, /* @ts-ignore */
|
|
3646
|
+
...(ngDevMode ? [{ debugName: "min" }] : /* istanbul ignore next */ []));
|
|
3647
|
+
max = input(100, /* @ts-ignore */
|
|
3648
|
+
...(ngDevMode ? [{ debugName: "max" }] : /* istanbul ignore next */ []));
|
|
3649
|
+
label = input(null, /* @ts-ignore */
|
|
3650
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
3651
|
+
tone = input('default', /* @ts-ignore */
|
|
3652
|
+
...(ngDevMode ? [{ debugName: "tone" }] : /* istanbul ignore next */ []));
|
|
3653
|
+
showValue = input(true, /* @ts-ignore */
|
|
3654
|
+
...(ngDevMode ? [{ debugName: "showValue" }] : /* istanbul ignore next */ []));
|
|
3655
|
+
unit = input('%', /* @ts-ignore */
|
|
3656
|
+
...(ngDevMode ? [{ debugName: "unit" }] : /* istanbul ignore next */ []));
|
|
3657
|
+
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3658
|
+
clamped = computed(() => Math.max(this.min(), Math.min(this.max(), this.value())), /* @ts-ignore */
|
|
3659
|
+
...(ngDevMode ? [{ debugName: "clamped" }] : /* istanbul ignore next */ []));
|
|
3660
|
+
pct = computed(() => {
|
|
3661
|
+
const range = this.max() - this.min() || 1;
|
|
3662
|
+
return ((this.clamped() - this.min()) / range) * 100;
|
|
3663
|
+
}, /* @ts-ignore */
|
|
3664
|
+
...(ngDevMode ? [{ debugName: "pct" }] : /* istanbul ignore next */ []));
|
|
3665
|
+
valueText = computed(() => `${this.value()}${this.unit()}`, /* @ts-ignore */
|
|
3666
|
+
...(ngDevMode ? [{ debugName: "valueText" }] : /* istanbul ignore next */ []));
|
|
3667
|
+
fillClass = computed(() => TONES[this.tone()], /* @ts-ignore */
|
|
3668
|
+
...(ngDevMode ? [{ debugName: "fillClass" }] : /* istanbul ignore next */ []));
|
|
3669
|
+
computedClass = computed(() => cn('grid w-full gap-1.5', this.userClass()), /* @ts-ignore */
|
|
3670
|
+
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
3671
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiMeter, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3672
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiMeter, isStandalone: true, selector: "bui-meter", 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 }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, tone: { classPropertyName: "tone", publicName: "tone", isSignal: true, isRequired: false, transformFunction: null }, showValue: { classPropertyName: "showValue", publicName: "showValue", isSignal: true, isRequired: false, transformFunction: null }, unit: { classPropertyName: "unit", publicName: "unit", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "meter" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
3673
|
+
@if (label() || showValue()) {
|
|
3674
|
+
<div class="flex items-center justify-between gap-2 text-sm">
|
|
3675
|
+
@if (label()) {
|
|
3676
|
+
<span class="font-medium text-foreground">{{ label() }}</span>
|
|
3677
|
+
} @else {
|
|
3678
|
+
<span aria-hidden="true"></span>
|
|
3679
|
+
}
|
|
3680
|
+
@if (showValue()) {
|
|
3681
|
+
<span class="text-muted-foreground tabular-nums">{{ valueText() }}</span>
|
|
3682
|
+
}
|
|
3683
|
+
</div>
|
|
3684
|
+
}
|
|
3685
|
+
<div
|
|
3686
|
+
role="meter"
|
|
3687
|
+
[attr.aria-label]="label() ?? 'Meter'"
|
|
3688
|
+
[attr.aria-valuenow]="clamped()"
|
|
3689
|
+
[attr.aria-valuemin]="min()"
|
|
3690
|
+
[attr.aria-valuemax]="max()"
|
|
3691
|
+
[attr.aria-valuetext]="valueText()"
|
|
3692
|
+
class="relative h-2 w-full overflow-hidden rounded-full bg-muted"
|
|
3693
|
+
>
|
|
3694
|
+
<div
|
|
3695
|
+
class="absolute inset-y-0 start-0 rounded-full transition-[width] duration-500 ease-out"
|
|
3696
|
+
[class]="fillClass()"
|
|
3697
|
+
[style.width.%]="pct()"
|
|
3698
|
+
></div>
|
|
3699
|
+
</div>
|
|
3700
|
+
`, isInline: true });
|
|
3701
|
+
}
|
|
3702
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiMeter, decorators: [{
|
|
3703
|
+
type: Component,
|
|
3704
|
+
args: [{
|
|
3705
|
+
selector: 'bui-meter',
|
|
3706
|
+
host: { 'data-slot': 'meter', '[class]': 'computedClass()' },
|
|
3707
|
+
template: `
|
|
3708
|
+
@if (label() || showValue()) {
|
|
3709
|
+
<div class="flex items-center justify-between gap-2 text-sm">
|
|
3710
|
+
@if (label()) {
|
|
3711
|
+
<span class="font-medium text-foreground">{{ label() }}</span>
|
|
3712
|
+
} @else {
|
|
3713
|
+
<span aria-hidden="true"></span>
|
|
3714
|
+
}
|
|
3715
|
+
@if (showValue()) {
|
|
3716
|
+
<span class="text-muted-foreground tabular-nums">{{ valueText() }}</span>
|
|
3717
|
+
}
|
|
3718
|
+
</div>
|
|
3719
|
+
}
|
|
3720
|
+
<div
|
|
3721
|
+
role="meter"
|
|
3722
|
+
[attr.aria-label]="label() ?? 'Meter'"
|
|
3723
|
+
[attr.aria-valuenow]="clamped()"
|
|
3724
|
+
[attr.aria-valuemin]="min()"
|
|
3725
|
+
[attr.aria-valuemax]="max()"
|
|
3726
|
+
[attr.aria-valuetext]="valueText()"
|
|
3727
|
+
class="relative h-2 w-full overflow-hidden rounded-full bg-muted"
|
|
3728
|
+
>
|
|
3729
|
+
<div
|
|
3730
|
+
class="absolute inset-y-0 start-0 rounded-full transition-[width] duration-500 ease-out"
|
|
3731
|
+
[class]="fillClass()"
|
|
3732
|
+
[style.width.%]="pct()"
|
|
3733
|
+
></div>
|
|
3734
|
+
</div>
|
|
3735
|
+
`,
|
|
3736
|
+
}]
|
|
3737
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], min: [{ type: i0.Input, args: [{ isSignal: true, alias: "min", required: false }] }], max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], tone: [{ type: i0.Input, args: [{ isSignal: true, alias: "tone", required: false }] }], showValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "showValue", required: false }] }], unit: [{ type: i0.Input, args: [{ isSignal: true, alias: "unit", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
3738
|
+
|
|
3739
|
+
const TREND_CLASS = {
|
|
3740
|
+
up: 'text-emerald-600 font-medium',
|
|
3741
|
+
down: 'text-destructive font-medium',
|
|
3742
|
+
neutral: 'text-muted-foreground font-medium',
|
|
3743
|
+
};
|
|
3744
|
+
/** A KPI / statistic card: label, big value, and a trend-coloured change. */
|
|
3745
|
+
class BuiStat {
|
|
3746
|
+
label = input(null, /* @ts-ignore */
|
|
3747
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
3748
|
+
value = input('', /* @ts-ignore */
|
|
3749
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
3750
|
+
change = input(null, /* @ts-ignore */
|
|
3751
|
+
...(ngDevMode ? [{ debugName: "change" }] : /* istanbul ignore next */ []));
|
|
3752
|
+
trend = input(null, /* @ts-ignore */
|
|
3753
|
+
...(ngDevMode ? [{ debugName: "trend" }] : /* istanbul ignore next */ []));
|
|
3754
|
+
caption = input(null, /* @ts-ignore */
|
|
3755
|
+
...(ngDevMode ? [{ debugName: "caption" }] : /* istanbul ignore next */ []));
|
|
3756
|
+
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3757
|
+
resolvedTrend = computed(() => {
|
|
3758
|
+
const explicit = this.trend();
|
|
3759
|
+
if (explicit) {
|
|
3760
|
+
return explicit;
|
|
3761
|
+
}
|
|
3762
|
+
const change = (this.change() ?? '').trim();
|
|
3763
|
+
if (change.startsWith('+')) {
|
|
3764
|
+
return 'up';
|
|
3765
|
+
}
|
|
3766
|
+
if (change.startsWith('-') || change.startsWith('−')) {
|
|
3767
|
+
return 'down';
|
|
3768
|
+
}
|
|
3769
|
+
return 'neutral';
|
|
3770
|
+
}, /* @ts-ignore */
|
|
3771
|
+
...(ngDevMode ? [{ debugName: "resolvedTrend" }] : /* istanbul ignore next */ []));
|
|
3772
|
+
trendClass = computed(() => TREND_CLASS[this.resolvedTrend()], /* @ts-ignore */
|
|
3773
|
+
...(ngDevMode ? [{ debugName: "trendClass" }] : /* istanbul ignore next */ []));
|
|
3774
|
+
computedClass = computed(() => cn('flex flex-col gap-1 rounded-lg border bg-card p-4', this.userClass()), /* @ts-ignore */
|
|
3775
|
+
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
3776
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiStat, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3777
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiStat, isStandalone: true, selector: "bui-stat", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, change: { classPropertyName: "change", publicName: "change", isSignal: true, isRequired: false, transformFunction: null }, trend: { classPropertyName: "trend", publicName: "trend", isSignal: true, isRequired: false, transformFunction: null }, caption: { classPropertyName: "caption", publicName: "caption", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "stat" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
3778
|
+
@if (label()) {
|
|
3779
|
+
<span class="text-sm font-medium text-muted-foreground">{{ label() }}</span>
|
|
3780
|
+
}
|
|
3781
|
+
<span class="text-2xl font-semibold tabular-nums">{{ value() }}</span>
|
|
3782
|
+
@if (change()) {
|
|
3783
|
+
<span class="flex items-center gap-1.5 text-sm">
|
|
3784
|
+
<span [class]="trendClass()">{{ change() }}</span>
|
|
3785
|
+
@if (caption()) {
|
|
3786
|
+
<span class="text-muted-foreground">{{ caption() }}</span>
|
|
3787
|
+
}
|
|
3788
|
+
</span>
|
|
3789
|
+
}
|
|
3790
|
+
`, isInline: true });
|
|
3791
|
+
}
|
|
3792
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiStat, decorators: [{
|
|
3793
|
+
type: Component,
|
|
3794
|
+
args: [{
|
|
3795
|
+
selector: 'bui-stat',
|
|
3796
|
+
host: { 'data-slot': 'stat', '[class]': 'computedClass()' },
|
|
3797
|
+
template: `
|
|
3798
|
+
@if (label()) {
|
|
3799
|
+
<span class="text-sm font-medium text-muted-foreground">{{ label() }}</span>
|
|
3800
|
+
}
|
|
3801
|
+
<span class="text-2xl font-semibold tabular-nums">{{ value() }}</span>
|
|
3802
|
+
@if (change()) {
|
|
3803
|
+
<span class="flex items-center gap-1.5 text-sm">
|
|
3804
|
+
<span [class]="trendClass()">{{ change() }}</span>
|
|
3805
|
+
@if (caption()) {
|
|
3806
|
+
<span class="text-muted-foreground">{{ caption() }}</span>
|
|
3807
|
+
}
|
|
3808
|
+
</span>
|
|
3809
|
+
}
|
|
3810
|
+
`,
|
|
3811
|
+
}]
|
|
3812
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], change: [{ type: i0.Input, args: [{ isSignal: true, alias: "change", required: false }] }], trend: [{ type: i0.Input, args: [{ isSignal: true, alias: "trend", required: false }] }], caption: [{ type: i0.Input, args: [{ isSignal: true, alias: "caption", required: false }] }], userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
3813
|
+
|
|
3814
|
+
/**
|
|
3815
|
+
* Hover-triggered card on the Angular CDK overlay. Opens on hover/focus after a delay
|
|
3816
|
+
* and stays open while the pointer is over the card. SSR-safe (browser-only, on hover).
|
|
3817
|
+
*/
|
|
3818
|
+
class BuiHoverCard {
|
|
3819
|
+
content = input.required({ ...(ngDevMode ? { debugName: "content" } : /* istanbul ignore next */ {}), alias: 'buiHoverCard' });
|
|
3820
|
+
openDelay = input(400, /* @ts-ignore */
|
|
3821
|
+
...(ngDevMode ? [{ debugName: "openDelay" }] : /* istanbul ignore next */ []));
|
|
3822
|
+
closeDelay = input(100, /* @ts-ignore */
|
|
3823
|
+
...(ngDevMode ? [{ debugName: "closeDelay" }] : /* istanbul ignore next */ []));
|
|
3824
|
+
overlay = inject(Overlay);
|
|
3825
|
+
host = inject(ElementRef);
|
|
3826
|
+
viewContainerRef = inject(ViewContainerRef);
|
|
3827
|
+
overlayRef = null;
|
|
3828
|
+
timer;
|
|
3829
|
+
scheduleOpen() {
|
|
3830
|
+
this.clearTimer();
|
|
3831
|
+
this.timer = setTimeout(() => {
|
|
3832
|
+
this.open();
|
|
3833
|
+
}, this.openDelay());
|
|
3834
|
+
}
|
|
3835
|
+
scheduleClose() {
|
|
3836
|
+
this.clearTimer();
|
|
3837
|
+
this.timer = setTimeout(() => {
|
|
3838
|
+
this.close();
|
|
3839
|
+
}, this.closeDelay());
|
|
3840
|
+
}
|
|
3841
|
+
clearTimer() {
|
|
3842
|
+
if (this.timer === undefined) {
|
|
3843
|
+
return;
|
|
3844
|
+
}
|
|
3845
|
+
clearTimeout(this.timer);
|
|
3846
|
+
this.timer = undefined;
|
|
3847
|
+
}
|
|
3848
|
+
open() {
|
|
3849
|
+
if (this.overlayRef) {
|
|
3850
|
+
return;
|
|
3851
|
+
}
|
|
3852
|
+
const positionStrategy = this.overlay
|
|
3853
|
+
.position()
|
|
3854
|
+
.flexibleConnectedTo(this.host)
|
|
3855
|
+
.withPositions([
|
|
3856
|
+
{ originX: 'center', originY: 'bottom', overlayX: 'center', overlayY: 'top', offsetY: 4 },
|
|
3857
|
+
{ originX: 'center', originY: 'top', overlayX: 'center', overlayY: 'bottom', offsetY: -4 },
|
|
3858
|
+
]);
|
|
3859
|
+
const overlayReference = this.overlay.create({
|
|
3860
|
+
positionStrategy,
|
|
3861
|
+
scrollStrategy: this.overlay.scrollStrategies.reposition(),
|
|
3862
|
+
});
|
|
3863
|
+
overlayReference.attach(new TemplatePortal(this.content(), this.viewContainerRef));
|
|
3864
|
+
overlayReference.overlayElement.addEventListener('mouseenter', () => {
|
|
3865
|
+
this.clearTimer();
|
|
3866
|
+
});
|
|
3867
|
+
overlayReference.overlayElement.addEventListener('mouseleave', () => {
|
|
3868
|
+
this.scheduleClose();
|
|
3869
|
+
});
|
|
3870
|
+
this.overlayRef = overlayReference;
|
|
3871
|
+
}
|
|
3872
|
+
close() {
|
|
3873
|
+
this.overlayRef?.dispose();
|
|
3874
|
+
this.overlayRef = null;
|
|
3875
|
+
}
|
|
3876
|
+
ngOnDestroy() {
|
|
3877
|
+
this.clearTimer();
|
|
3878
|
+
this.close();
|
|
3879
|
+
}
|
|
3880
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiHoverCard, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3881
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: BuiHoverCard, isStandalone: true, selector: "[buiHoverCard]", inputs: { content: { classPropertyName: "content", publicName: "buiHoverCard", isSignal: true, isRequired: true, transformFunction: null }, openDelay: { classPropertyName: "openDelay", publicName: "openDelay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "mouseenter": "scheduleOpen()", "mouseleave": "scheduleClose()", "focusin": "scheduleOpen()", "focusout": "scheduleClose()" } }, ngImport: i0 });
|
|
3882
|
+
}
|
|
3883
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiHoverCard, decorators: [{
|
|
3884
|
+
type: Directive,
|
|
3885
|
+
args: [{
|
|
3886
|
+
selector: '[buiHoverCard]',
|
|
3887
|
+
host: {
|
|
3888
|
+
'(mouseenter)': 'scheduleOpen()',
|
|
3889
|
+
'(mouseleave)': 'scheduleClose()',
|
|
3890
|
+
'(focusin)': 'scheduleOpen()',
|
|
3891
|
+
'(focusout)': 'scheduleClose()',
|
|
3892
|
+
},
|
|
3893
|
+
}]
|
|
3894
|
+
}], propDecorators: { content: [{ type: i0.Input, args: [{ isSignal: true, alias: "buiHoverCard", required: true }] }], openDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "openDelay", required: false }] }], closeDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeDelay", required: false }] }] } });
|
|
3895
|
+
/** Styling for the hover-card content root (inside the bound template). */
|
|
3896
|
+
class BuiHoverCardContent {
|
|
3897
|
+
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3898
|
+
computedClass = computed(() => cn('z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none', this.userClass()), /* @ts-ignore */
|
|
3899
|
+
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
3900
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiHoverCardContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3901
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.2", type: BuiHoverCardContent, isStandalone: true, selector: "[buiHoverCardContent]", inputs: { userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "hover-card-content", "tabindex": "-1" }, properties: { "class": "computedClass()" } }, ngImport: i0 });
|
|
3902
|
+
}
|
|
3903
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiHoverCardContent, decorators: [{
|
|
3904
|
+
type: Directive,
|
|
3905
|
+
args: [{
|
|
3906
|
+
selector: '[buiHoverCardContent]',
|
|
3907
|
+
host: { 'data-slot': 'hover-card-content', tabindex: '-1', '[class]': 'computedClass()' },
|
|
3908
|
+
}]
|
|
3909
|
+
}], propDecorators: { userClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }] } });
|
|
3910
|
+
|
|
3911
|
+
/** A dark code panel with an optional filename header and a copy button. */
|
|
3912
|
+
class BuiCodeBlock {
|
|
3913
|
+
code = input('', /* @ts-ignore */
|
|
3914
|
+
...(ngDevMode ? [{ debugName: "code" }] : /* istanbul ignore next */ []));
|
|
3915
|
+
filename = input(null, /* @ts-ignore */
|
|
3916
|
+
...(ngDevMode ? [{ debugName: "filename" }] : /* istanbul ignore next */ []));
|
|
3917
|
+
userClass = input('', { ...(ngDevMode ? { debugName: "userClass" } : /* istanbul ignore next */ {}), alias: 'class' });
|
|
3918
|
+
copied = signal(false, /* @ts-ignore */
|
|
3919
|
+
...(ngDevMode ? [{ debugName: "copied" }] : /* istanbul ignore next */ []));
|
|
3920
|
+
computedClass = computed(() => cn('group/code-block relative block overflow-hidden rounded-lg border border-zinc-800 bg-zinc-950 text-zinc-100', this.userClass()), /* @ts-ignore */
|
|
3921
|
+
...(ngDevMode ? [{ debugName: "computedClass" }] : /* istanbul ignore next */ []));
|
|
3922
|
+
async copy() {
|
|
3923
|
+
try {
|
|
3924
|
+
await navigator.clipboard.writeText(this.code());
|
|
3925
|
+
this.copied.set(true);
|
|
3926
|
+
setTimeout(() => {
|
|
3927
|
+
this.copied.set(false);
|
|
3928
|
+
}, 1600);
|
|
3929
|
+
}
|
|
3930
|
+
catch {
|
|
3931
|
+
// Clipboard unavailable — ignore.
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiCodeBlock, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3935
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.2", type: BuiCodeBlock, isStandalone: true, selector: "bui-code-block", inputs: { code: { classPropertyName: "code", publicName: "code", isSignal: true, isRequired: false, transformFunction: null }, filename: { classPropertyName: "filename", publicName: "filename", isSignal: true, isRequired: false, transformFunction: null }, userClass: { classPropertyName: "userClass", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "data-slot": "code-block" }, properties: { "class": "computedClass()" } }, ngImport: i0, template: `
|
|
3936
|
+
@if (filename()) {
|
|
3937
|
+
<div class="flex items-center justify-between border-b border-white/10 px-4 py-2">
|
|
3938
|
+
<span class="font-mono text-xs text-zinc-400">{{ filename() }}</span>
|
|
3939
|
+
<button
|
|
3940
|
+
type="button"
|
|
3941
|
+
aria-label="Copy code"
|
|
3942
|
+
class="text-xs text-zinc-400 transition-colors hover:text-zinc-100"
|
|
3943
|
+
(click)="copy()"
|
|
3944
|
+
>
|
|
3945
|
+
{{ copied() ? 'Copied' : 'Copy' }}
|
|
3946
|
+
</button>
|
|
3947
|
+
</div>
|
|
3948
|
+
} @else {
|
|
3949
|
+
<button
|
|
3950
|
+
type="button"
|
|
3951
|
+
aria-label="Copy code"
|
|
3952
|
+
class="absolute end-2 top-2 z-10 rounded-md px-1.5 py-1 text-xs text-zinc-400 opacity-0 transition-all group-hover/code-block:opacity-100 hover:bg-white/10 hover:text-zinc-100 focus-visible:opacity-100"
|
|
3953
|
+
(click)="copy()"
|
|
3954
|
+
>
|
|
3955
|
+
{{ copied() ? 'Copied' : 'Copy' }}
|
|
3956
|
+
</button>
|
|
3957
|
+
}
|
|
3958
|
+
<pre
|
|
3959
|
+
class="overflow-x-auto p-4 text-[13px] leading-relaxed"
|
|
3960
|
+
><code class="font-mono">{{ code() }}</code></pre>
|
|
3961
|
+
`, isInline: true });
|
|
3962
|
+
}
|
|
3963
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImport: i0, type: BuiCodeBlock, decorators: [{
|
|
3964
|
+
type: Component,
|
|
3965
|
+
args: [{
|
|
3966
|
+
selector: 'bui-code-block',
|
|
3967
|
+
host: { 'data-slot': 'code-block', '[class]': 'computedClass()' },
|
|
3968
|
+
template: `
|
|
3969
|
+
@if (filename()) {
|
|
3970
|
+
<div class="flex items-center justify-between border-b border-white/10 px-4 py-2">
|
|
3971
|
+
<span class="font-mono text-xs text-zinc-400">{{ filename() }}</span>
|
|
3972
|
+
<button
|
|
3973
|
+
type="button"
|
|
3974
|
+
aria-label="Copy code"
|
|
3975
|
+
class="text-xs text-zinc-400 transition-colors hover:text-zinc-100"
|
|
3976
|
+
(click)="copy()"
|
|
3977
|
+
>
|
|
3978
|
+
{{ copied() ? 'Copied' : 'Copy' }}
|
|
3979
|
+
</button>
|
|
3980
|
+
</div>
|
|
3981
|
+
} @else {
|
|
3982
|
+
<button
|
|
3983
|
+
type="button"
|
|
3984
|
+
aria-label="Copy code"
|
|
3985
|
+
class="absolute end-2 top-2 z-10 rounded-md px-1.5 py-1 text-xs text-zinc-400 opacity-0 transition-all group-hover/code-block:opacity-100 hover:bg-white/10 hover:text-zinc-100 focus-visible:opacity-100"
|
|
3986
|
+
(click)="copy()"
|
|
3987
|
+
>
|
|
3988
|
+
{{ copied() ? 'Copied' : 'Copy' }}
|
|
3989
|
+
</button>
|
|
3990
|
+
}
|
|
3991
|
+
<pre
|
|
3992
|
+
class="overflow-x-auto p-4 text-[13px] leading-relaxed"
|
|
3993
|
+
><code class="font-mono">{{ code() }}</code></pre>
|
|
3994
|
+
`,
|
|
3995
|
+
}]
|
|
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
|
+
|
|
3616
3998
|
/*
|
|
3617
3999
|
* Public API Surface of ng-blatui
|
|
3618
4000
|
*/
|
|
@@ -3621,5 +4003,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.2", ngImpor
|
|
|
3621
4003
|
* Generated bundle index. Do not edit.
|
|
3622
4004
|
*/
|
|
3623
4005
|
|
|
3624
|
-
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, 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, BuiInput, BuiInputGroup, BuiInputGroupAddon, BuiInputGroupButton, BuiInputGroupInput, BuiInputGroupText, BuiItem, BuiItemActions, BuiItemContent, BuiItemDescription, BuiItemGroup, BuiItemMedia, BuiItemTitle, BuiKbd, BuiLabel, BuiPagination, BuiPaginationContent, BuiPaginationEllipsis, BuiPaginationItem, BuiPaginationLink, BuiPopover, BuiPopoverContent, BuiProgress, BuiRadioGroup, BuiRadioGroupItem, BuiScrollArea, BuiSeparator, BuiSkeleton, BuiSpinner, BuiSwitch, BuiTabList, BuiTabPanel, BuiTabTrigger, BuiTable, BuiTableBody, BuiTableCaption, BuiTableCell, BuiTableContainer, BuiTableFooter, BuiTableHead, BuiTableHeader, BuiTableRow, BuiTabs, BuiTextarea, BuiThemeCustomizer, BuiToggle, BuiTooltip, BuiTooltipContent, THEME_TOKENS, ThemeStore, buttonVariants, cn, toggleVariants };
|
|
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 };
|
|
3625
4007
|
//# sourceMappingURL=ng-blatui.mjs.map
|