@eduboxpro/studio 0.1.15 → 0.1.16
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/eduboxpro-studio.mjs +653 -3
- package/fesm2022/eduboxpro-studio.mjs.map +1 -1
- package/index.d.ts +192 -3
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, signal, effect, Injectable, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, input, computed, ChangeDetectionStrategy, Component, output, PLATFORM_ID, ElementRef,
|
|
2
|
+
import { InjectionToken, inject, signal, effect, Injectable, makeEnvironmentProviders, ENVIRONMENT_INITIALIZER, input, computed, ChangeDetectionStrategy, Component, output, PLATFORM_ID, ElementRef, contentChild, viewChild, forwardRef, DOCUMENT as DOCUMENT$1, DestroyRef, Injector, model, afterNextRender, HostListener, Renderer2, Directive } from '@angular/core';
|
|
3
3
|
import * as i1$1 from '@angular/common';
|
|
4
4
|
import { DOCUMENT, CommonModule, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
|
|
5
5
|
import * as LucideIcons from 'lucide-angular';
|
|
@@ -8,7 +8,7 @@ import * as i1 from '@angular/router';
|
|
|
8
8
|
import { Router, NavigationEnd, RouterModule, RouterLink, RouterLinkActive } from '@angular/router';
|
|
9
9
|
import { filter } from 'rxjs/operators';
|
|
10
10
|
import * as i1$2 from '@angular/forms';
|
|
11
|
-
import {
|
|
11
|
+
import { FormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
|
|
12
12
|
import { autoUpdate, offset, flip, shift, arrow, computePosition } from '@floating-ui/dom';
|
|
13
13
|
import { trigger, state, transition, style, animate } from '@angular/animations';
|
|
14
14
|
|
|
@@ -1267,6 +1267,656 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
1267
1267
|
}, template: `<ng-content select="studio-button" />`, styles: [":host{display:inline-flex;align-items:center;position:relative}:host(.studio-button-group--horizontal){flex-direction:row}:host(.studio-button-group--vertical){flex-direction:column}:host(.studio-button-group--spacing-none){gap:0}:host(.studio-button-group--spacing-xs){gap:var(--studio-spacing-xs)}:host(.studio-button-group--spacing-sm){gap:var(--studio-spacing-sm)}:host(.studio-button-group--spacing-md){gap:var(--studio-spacing-md)}:host(.studio-button-group--spacing-lg){gap:var(--studio-spacing-lg)}:host(.studio-button-group--align-start){justify-content:flex-start}:host(.studio-button-group--align-center){justify-content:center}:host(.studio-button-group--align-end){justify-content:flex-end}:host(.studio-button-group--align-stretch){align-items:stretch}:host(.studio-button-group--align-stretch) ::ng-deep studio-button{flex:1}:host(.studio-button-group--full){width:100%}:host(.studio-button-group--full) ::ng-deep studio-button{flex:1}:host(.studio-button-group--attached){gap:0}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--attached{margin:0;position:relative}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--middle{border-radius:0}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--first:not(.studio-button-group__item--last){border-top-right-radius:0;border-bottom-right-radius:0}:host(.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--last:not(.studio-button-group__item--first){border-top-left-radius:0;border-bottom-left-radius:0}:host(.studio-button-group--attached).studio-button-group--horizontal ::ng-deep studio-button.studio-button-group__item--attached:not(:last-child){border-right:1px solid rgba(0,0,0,.1)}:host(.studio-button-group--attached).studio-button-group--horizontal ::ng-deep studio-button.studio-button-group__item--attached.studio-button--outline:not(:last-child){margin-right:-1px}:host(.studio-button-group--vertical){align-items:stretch}:host(.studio-button-group--vertical) ::ng-deep studio-button{width:100%;justify-content:flex-start}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--first:not(.studio-button-group__item--last){border-top-right-radius:var(--studio-radius-sm);border-bottom-right-radius:0;border-top-left-radius:var(--studio-radius-sm);border-bottom-left-radius:0}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--last:not(.studio-button-group__item--first){border-top-left-radius:0;border-bottom-left-radius:var(--studio-radius-sm);border-top-right-radius:0;border-bottom-right-radius:var(--studio-radius-sm)}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--attached:not(:last-child){border-right:none;border-bottom:1px solid rgba(255,255,255,.2)}:host(.studio-button-group--vertical.studio-button-group--attached) ::ng-deep studio-button.studio-button-group__item--middle{border-radius:0}:host(.studio-button-group--vertical.studio-button-group--full) ::ng-deep studio-button{width:100%}\n"] }]
|
|
1268
1268
|
}], ctorParameters: () => [], propDecorators: { orientationInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], sizeInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], variantInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], colorInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], radiusInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], attached: [{ type: i0.Input, args: [{ isSignal: true, alias: "attached", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], spacing: [{ type: i0.Input, args: [{ isSignal: true, alias: "spacing", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], role: [{ type: i0.Input, args: [{ isSignal: true, alias: "role", required: false }] }] } });
|
|
1269
1269
|
|
|
1270
|
+
/**
|
|
1271
|
+
* Card component for displaying content in a container
|
|
1272
|
+
*
|
|
1273
|
+
* @example
|
|
1274
|
+
* <studio-card variant="elevated" color="primary">
|
|
1275
|
+
* <div card-header>Header</div>
|
|
1276
|
+
* <div card-body>Content</div>
|
|
1277
|
+
* <div card-footer>Footer</div>
|
|
1278
|
+
* </studio-card>
|
|
1279
|
+
*/
|
|
1280
|
+
class CardComponent {
|
|
1281
|
+
configService = inject(StudioConfigService);
|
|
1282
|
+
cardDefaults = computed(() => this.configService.config().components?.card, ...(ngDevMode ? [{ debugName: "cardDefaults" }] : []));
|
|
1283
|
+
// Style inputs with config defaults
|
|
1284
|
+
variantInput = input(undefined, ...(ngDevMode ? [{ debugName: "variantInput", alias: 'variant' }] : [{ alias: 'variant' }]));
|
|
1285
|
+
sizeInput = input(undefined, ...(ngDevMode ? [{ debugName: "sizeInput", alias: 'size' }] : [{ alias: 'size' }]));
|
|
1286
|
+
colorInput = input(undefined, ...(ngDevMode ? [{ debugName: "colorInput", alias: 'color' }] : [{ alias: 'color' }]));
|
|
1287
|
+
radiusInput = input(undefined, ...(ngDevMode ? [{ debugName: "radiusInput", alias: 'radius' }] : [{ alias: 'radius' }]));
|
|
1288
|
+
shadowInput = input(undefined, ...(ngDevMode ? [{ debugName: "shadowInput", alias: 'shadow' }] : [{ alias: 'shadow' }]));
|
|
1289
|
+
paddingInput = input(undefined, ...(ngDevMode ? [{ debugName: "paddingInput", alias: 'padding' }] : [{ alias: 'padding' }]));
|
|
1290
|
+
variant = withConfigDefault(this.variantInput, computed(() => this.cardDefaults()?.variant), 'elevated');
|
|
1291
|
+
size = withConfigDefault(this.sizeInput, computed(() => this.cardDefaults()?.size), 'md');
|
|
1292
|
+
color = withConfigDefault(this.colorInput, computed(() => this.cardDefaults()?.color), 'default');
|
|
1293
|
+
radius = withConfigDefault(this.radiusInput, computed(() => this.cardDefaults()?.radius), 'lg');
|
|
1294
|
+
shadow = withConfigDefault(this.shadowInput, computed(() => this.cardDefaults()?.shadow), 'md');
|
|
1295
|
+
padding = withConfigDefault(this.paddingInput, computed(() => this.cardDefaults()?.padding), 'md');
|
|
1296
|
+
// Layout inputs
|
|
1297
|
+
orientation = input('vertical', ...(ngDevMode ? [{ debugName: "orientation" }] : []));
|
|
1298
|
+
imagePosition = input('top', ...(ngDevMode ? [{ debugName: "imagePosition" }] : []));
|
|
1299
|
+
fullWidth = input(false, ...(ngDevMode ? [{ debugName: "fullWidth" }] : []));
|
|
1300
|
+
fullHeight = input(false, ...(ngDevMode ? [{ debugName: "fullHeight" }] : []));
|
|
1301
|
+
// Content inputs
|
|
1302
|
+
title = input(...(ngDevMode ? [undefined, { debugName: "title" }] : []));
|
|
1303
|
+
subtitle = input(...(ngDevMode ? [undefined, { debugName: "subtitle" }] : []));
|
|
1304
|
+
avatar = input(...(ngDevMode ? [undefined, { debugName: "avatar" }] : []));
|
|
1305
|
+
icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : []));
|
|
1306
|
+
image = input(...(ngDevMode ? [undefined, { debugName: "image" }] : []));
|
|
1307
|
+
imageAlt = input('', ...(ngDevMode ? [{ debugName: "imageAlt" }] : []));
|
|
1308
|
+
imageFit = input('cover', ...(ngDevMode ? [{ debugName: "imageFit" }] : []));
|
|
1309
|
+
// Visibility inputs
|
|
1310
|
+
showHeader = input(true, ...(ngDevMode ? [{ debugName: "showHeader" }] : []));
|
|
1311
|
+
showMedia = input(true, ...(ngDevMode ? [{ debugName: "showMedia" }] : []));
|
|
1312
|
+
showFooter = input(true, ...(ngDevMode ? [{ debugName: "showFooter" }] : []));
|
|
1313
|
+
divider = input(false, ...(ngDevMode ? [{ debugName: "divider" }] : []));
|
|
1314
|
+
// Interaction inputs
|
|
1315
|
+
hoverable = input(false, ...(ngDevMode ? [{ debugName: "hoverable" }] : []));
|
|
1316
|
+
pressable = input(false, ...(ngDevMode ? [{ debugName: "pressable" }] : []));
|
|
1317
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
1318
|
+
loading = input(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
|
|
1319
|
+
href = input(...(ngDevMode ? [undefined, { debugName: "href" }] : []));
|
|
1320
|
+
target = input('_self', ...(ngDevMode ? [{ debugName: "target" }] : []));
|
|
1321
|
+
// Effects
|
|
1322
|
+
blurred = input(false, ...(ngDevMode ? [{ debugName: "blurred" }] : []));
|
|
1323
|
+
blurredFooter = input(false, ...(ngDevMode ? [{ debugName: "blurredFooter" }] : []));
|
|
1324
|
+
animated = input(false, ...(ngDevMode ? [{ debugName: "animated" }] : []));
|
|
1325
|
+
// Outputs
|
|
1326
|
+
clicked = output();
|
|
1327
|
+
headerAction = output();
|
|
1328
|
+
// Template refs
|
|
1329
|
+
headerTemplate = contentChild('cardHeader', ...(ngDevMode ? [{ debugName: "headerTemplate" }] : []));
|
|
1330
|
+
headerActionsTemplate = contentChild('cardHeaderActions', ...(ngDevMode ? [{ debugName: "headerActionsTemplate" }] : []));
|
|
1331
|
+
mediaTemplate = contentChild('cardMedia', ...(ngDevMode ? [{ debugName: "mediaTemplate" }] : []));
|
|
1332
|
+
bodyTemplate = contentChild('cardBody', ...(ngDevMode ? [{ debugName: "bodyTemplate" }] : []));
|
|
1333
|
+
footerTemplate = contentChild('cardFooter', ...(ngDevMode ? [{ debugName: "footerTemplate" }] : []));
|
|
1334
|
+
// Computed
|
|
1335
|
+
iconSize = computed(() => {
|
|
1336
|
+
const sizeMap = { sm: 18, md: 20, lg: 24 };
|
|
1337
|
+
return sizeMap[this.size()];
|
|
1338
|
+
}, ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
|
|
1339
|
+
hostClasses = computed(() => classNames('studio-card', `studio-card--${this.variant()}`, `studio-card--${this.size()}`, `studio-card--${this.color()}`, `studio-card--radius-${this.radius()}`, `studio-card--shadow-${this.shadow()}`, `studio-card--padding-${this.padding()}`, `studio-card--${this.orientation()}`, this.imagePosition() !== 'top' && `studio-card--image-${this.imagePosition()}`, this.fullWidth() && 'studio-card--full-width', this.fullHeight() && 'studio-card--full-height', this.hoverable() && 'studio-card--hoverable', this.pressable() && 'studio-card--pressable', this.disabled() && 'studio-card--disabled', this.loading() && 'studio-card--loading', this.blurred() && 'studio-card--blurred', this.blurredFooter() && 'studio-card--blurred-footer', this.animated() && 'studio-card--animated', this.divider() && 'studio-card--divider', this.href() && 'studio-card--clickable'), ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
|
|
1340
|
+
handleClick(event) {
|
|
1341
|
+
if (this.disabled() || this.loading()) {
|
|
1342
|
+
event.preventDefault();
|
|
1343
|
+
event.stopPropagation();
|
|
1344
|
+
return;
|
|
1345
|
+
}
|
|
1346
|
+
const url = this.href();
|
|
1347
|
+
if (url) {
|
|
1348
|
+
const safeUrl = sanitizeUrl(url);
|
|
1349
|
+
if (safeUrl === '#') {
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
const target = this.target();
|
|
1353
|
+
if (target === '_blank') {
|
|
1354
|
+
window.open(safeUrl, '_blank', 'noopener,noreferrer');
|
|
1355
|
+
}
|
|
1356
|
+
else {
|
|
1357
|
+
window.location.href = safeUrl;
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
this.clicked.emit(event);
|
|
1361
|
+
}
|
|
1362
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1363
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: CardComponent, isStandalone: true, selector: "studio-card", inputs: { variantInput: { classPropertyName: "variantInput", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, sizeInput: { classPropertyName: "sizeInput", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, colorInput: { classPropertyName: "colorInput", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, radiusInput: { classPropertyName: "radiusInput", publicName: "radius", isSignal: true, isRequired: false, transformFunction: null }, shadowInput: { classPropertyName: "shadowInput", publicName: "shadow", isSignal: true, isRequired: false, transformFunction: null }, paddingInput: { classPropertyName: "paddingInput", publicName: "padding", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, imagePosition: { classPropertyName: "imagePosition", publicName: "imagePosition", isSignal: true, isRequired: false, transformFunction: null }, fullWidth: { classPropertyName: "fullWidth", publicName: "fullWidth", isSignal: true, isRequired: false, transformFunction: null }, fullHeight: { classPropertyName: "fullHeight", publicName: "fullHeight", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, avatar: { classPropertyName: "avatar", publicName: "avatar", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, image: { classPropertyName: "image", publicName: "image", isSignal: true, isRequired: false, transformFunction: null }, imageAlt: { classPropertyName: "imageAlt", publicName: "imageAlt", isSignal: true, isRequired: false, transformFunction: null }, imageFit: { classPropertyName: "imageFit", publicName: "imageFit", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, showMedia: { classPropertyName: "showMedia", publicName: "showMedia", isSignal: true, isRequired: false, transformFunction: null }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", isSignal: true, isRequired: false, transformFunction: null }, divider: { classPropertyName: "divider", publicName: "divider", isSignal: true, isRequired: false, transformFunction: null }, hoverable: { classPropertyName: "hoverable", publicName: "hoverable", isSignal: true, isRequired: false, transformFunction: null }, pressable: { classPropertyName: "pressable", publicName: "pressable", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: false, transformFunction: null }, blurred: { classPropertyName: "blurred", publicName: "blurred", isSignal: true, isRequired: false, transformFunction: null }, blurredFooter: { classPropertyName: "blurredFooter", publicName: "blurredFooter", isSignal: true, isRequired: false, transformFunction: null }, animated: { classPropertyName: "animated", publicName: "animated", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked", headerAction: "headerAction" }, host: { listeners: { "click": "handleClick($event)" }, properties: { "class": "hostClasses()", "attr.href": "href()", "attr.target": "href() ? target() : null", "attr.rel": "href() && target() === \"_blank\" ? \"noopener noreferrer\" : null", "attr.disabled": "disabled() ? \"\" : null" } }, queries: [{ propertyName: "headerTemplate", first: true, predicate: ["cardHeader"], descendants: true, isSignal: true }, { propertyName: "headerActionsTemplate", first: true, predicate: ["cardHeaderActions"], descendants: true, isSignal: true }, { propertyName: "mediaTemplate", first: true, predicate: ["cardMedia"], descendants: true, isSignal: true }, { propertyName: "bodyTemplate", first: true, predicate: ["cardBody"], descendants: true, isSignal: true }, { propertyName: "footerTemplate", first: true, predicate: ["cardFooter"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1364
|
+
<div class="studio-card__container">
|
|
1365
|
+
<!-- Header -->
|
|
1366
|
+
@if (showHeader() && (headerTemplate() || title() || subtitle())) {
|
|
1367
|
+
<div class="studio-card__header">
|
|
1368
|
+
@if (headerTemplate()) {
|
|
1369
|
+
<ng-container *ngTemplateOutlet="headerTemplate()!" />
|
|
1370
|
+
} @else {
|
|
1371
|
+
<div class="studio-card__header-content">
|
|
1372
|
+
@if (avatar()) {
|
|
1373
|
+
<img [src]="avatar()!" alt="" class="studio-card__avatar" />
|
|
1374
|
+
}
|
|
1375
|
+
@if (icon() && !avatar()) {
|
|
1376
|
+
<div class="studio-card__icon-wrapper">
|
|
1377
|
+
<studio-icon [name]="icon()!" [size]="iconSize()" />
|
|
1378
|
+
</div>
|
|
1379
|
+
}
|
|
1380
|
+
<div class="studio-card__header-text">
|
|
1381
|
+
@if (title()) {
|
|
1382
|
+
<h3 class="studio-card__title">{{ title() }}</h3>
|
|
1383
|
+
}
|
|
1384
|
+
@if (subtitle()) {
|
|
1385
|
+
<p class="studio-card__subtitle">{{ subtitle() }}</p>
|
|
1386
|
+
}
|
|
1387
|
+
</div>
|
|
1388
|
+
</div>
|
|
1389
|
+
@if (headerActionsTemplate()) {
|
|
1390
|
+
<div class="studio-card__header-actions">
|
|
1391
|
+
<ng-container *ngTemplateOutlet="headerActionsTemplate()!" />
|
|
1392
|
+
</div>
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
</div>
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
<!-- Media -->
|
|
1399
|
+
@if (showMedia() && (mediaTemplate() || image())) {
|
|
1400
|
+
<div class="studio-card__media">
|
|
1401
|
+
@if (mediaTemplate()) {
|
|
1402
|
+
<ng-container *ngTemplateOutlet="mediaTemplate()!" />
|
|
1403
|
+
} @else if (image()) {
|
|
1404
|
+
<img
|
|
1405
|
+
[src]="image()!"
|
|
1406
|
+
[alt]="imageAlt()"
|
|
1407
|
+
class="studio-card__image"
|
|
1408
|
+
[class.studio-card__image--cover]="imageFit() === 'cover'"
|
|
1409
|
+
[class.studio-card__image--contain]="imageFit() === 'contain'"
|
|
1410
|
+
/>
|
|
1411
|
+
}
|
|
1412
|
+
</div>
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
<!-- Body -->
|
|
1416
|
+
<div class="studio-card__body">
|
|
1417
|
+
@if (bodyTemplate()) {
|
|
1418
|
+
<ng-container *ngTemplateOutlet="bodyTemplate()!" />
|
|
1419
|
+
} @else {
|
|
1420
|
+
<ng-content />
|
|
1421
|
+
}
|
|
1422
|
+
</div>
|
|
1423
|
+
|
|
1424
|
+
<!-- Footer -->
|
|
1425
|
+
@if (showFooter() && footerTemplate()) {
|
|
1426
|
+
<div class="studio-card__footer">
|
|
1427
|
+
<ng-container *ngTemplateOutlet="footerTemplate()!" />
|
|
1428
|
+
</div>
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
<!-- Loading overlay -->
|
|
1432
|
+
@if (loading()) {
|
|
1433
|
+
<div class="studio-card__loading">
|
|
1434
|
+
<studio-icon name="loader-2" [size]="24" class="studio-card__spinner" />
|
|
1435
|
+
</div>
|
|
1436
|
+
}
|
|
1437
|
+
</div>
|
|
1438
|
+
`, isInline: true, styles: [":host{display:block;font-family:var(--studio-font-family);position:relative;transition:all var(--studio-transition-normal)}.studio-card__container{display:flex;flex-direction:column;height:100%;overflow:hidden;position:relative}:host(.studio-card--sm) .studio-card__container{min-height:8rem}:host(.studio-card--md) .studio-card__container{min-height:12rem}:host(.studio-card--lg) .studio-card__container{min-height:16rem}:host(.studio-card--radius-none) .studio-card__container{border-radius:var(--studio-radius-none)}:host(.studio-card--radius-sm) .studio-card__container{border-radius:var(--studio-radius-sm)}:host(.studio-card--radius-md) .studio-card__container{border-radius:var(--studio-radius-md)}:host(.studio-card--radius-lg) .studio-card__container{border-radius:var(--studio-radius-lg)}:host(.studio-card--radius-xl) .studio-card__container{border-radius:var(--studio-radius-xl)}:host(.studio-card--shadow-none) .studio-card__container{box-shadow:none}:host(.studio-card--shadow-sm) .studio-card__container{box-shadow:var(--studio-shadow-sm)}:host(.studio-card--shadow-md) .studio-card__container{box-shadow:var(--studio-shadow-md)}:host(.studio-card--shadow-lg) .studio-card__container{box-shadow:var(--studio-shadow-lg)}:host(.studio-card--shadow-xl) .studio-card__container{box-shadow:var(--studio-shadow-xl)}:host(.studio-card--elevated.studio-card--default) .studio-card__container{background:var(--studio-bg-primary);border:1px solid var(--studio-border-primary)}:host(.studio-card--filled.studio-card--default) .studio-card__container{background:var(--studio-bg-secondary);border:1px solid transparent}:host(.studio-card--outlined.studio-card--default) .studio-card__container{background:transparent;border:2px solid var(--studio-border-primary)}:host(.studio-card--ghost.studio-card--default) .studio-card__container{background:transparent;border:1px solid transparent}:host(.studio-card--elevated.studio-card--primary) .studio-card__container{background:var(--studio-primary-bg);border:1px solid var(--studio-primary)}:host(.studio-card--filled.studio-card--primary) .studio-card__container{background:var(--studio-primary);color:#fff;border:1px solid transparent}:host(.studio-card--outlined.studio-card--primary) .studio-card__container{background:transparent;border:2px solid var(--studio-primary);color:var(--studio-primary)}:host(.studio-card--ghost.studio-card--primary) .studio-card__container{background:var(--studio-primary-bg);border:1px solid transparent;color:var(--studio-primary)}:host(.studio-card--elevated.studio-card--secondary) .studio-card__container{background:var(--studio-bg-primary);border:1px solid var(--studio-text-secondary)}:host(.studio-card--filled.studio-card--secondary) .studio-card__container{background:var(--studio-text-secondary);color:#fff;border:1px solid transparent}:host(.studio-card--outlined.studio-card--secondary) .studio-card__container{background:transparent;border:2px solid var(--studio-text-secondary);color:var(--studio-text-secondary)}:host(.studio-card--ghost.studio-card--secondary) .studio-card__container{background:var(--studio-bg-secondary);border:1px solid transparent;color:var(--studio-text-secondary)}:host(.studio-card--elevated.studio-card--success) .studio-card__container{background:var(--studio-success-bg);border:1px solid var(--studio-success)}:host(.studio-card--filled.studio-card--success) .studio-card__container{background:var(--studio-success);color:#fff;border:1px solid transparent}:host(.studio-card--outlined.studio-card--success) .studio-card__container{background:transparent;border:2px solid var(--studio-success);color:var(--studio-success)}:host(.studio-card--ghost.studio-card--success) .studio-card__container{background:var(--studio-success-bg);border:1px solid transparent;color:var(--studio-success)}:host(.studio-card--elevated.studio-card--error) .studio-card__container{background:var(--studio-error-bg);border:1px solid var(--studio-error)}:host(.studio-card--filled.studio-card--error) .studio-card__container{background:var(--studio-error);color:#fff;border:1px solid transparent}:host(.studio-card--outlined.studio-card--error) .studio-card__container{background:transparent;border:2px solid var(--studio-error);color:var(--studio-error)}:host(.studio-card--ghost.studio-card--error) .studio-card__container{background:var(--studio-error-bg);border:1px solid transparent;color:var(--studio-error)}:host(.studio-card--elevated.studio-card--warning) .studio-card__container{background:var(--studio-warning-bg);border:1px solid var(--studio-warning)}:host(.studio-card--filled.studio-card--warning) .studio-card__container{background:var(--studio-warning);color:#fff;border:1px solid transparent}:host(.studio-card--outlined.studio-card--warning) .studio-card__container{background:transparent;border:2px solid var(--studio-warning);color:var(--studio-warning)}:host(.studio-card--ghost.studio-card--warning) .studio-card__container{background:var(--studio-warning-bg);border:1px solid transparent;color:var(--studio-warning)}:host(.studio-card--elevated.studio-card--neutral) .studio-card__container{background:var(--studio-bg-tertiary);border:1px solid var(--studio-border-secondary)}:host(.studio-card--filled.studio-card--neutral) .studio-card__container{background:var(--studio-bg-secondary);border:1px solid transparent}:host(.studio-card--outlined.studio-card--neutral) .studio-card__container{background:transparent;border:2px solid var(--studio-border-secondary)}:host(.studio-card--ghost.studio-card--neutral) .studio-card__container{background:transparent;border:1px solid transparent}:host(.studio-card--padding-none) .studio-card__header,:host(.studio-card--padding-none) .studio-card__body,:host(.studio-card--padding-none) .studio-card__footer{padding:0}:host(.studio-card--padding-sm) .studio-card__header,:host(.studio-card--padding-sm) .studio-card__footer{padding:var(--studio-spacing-sm)}:host(.studio-card--padding-sm) .studio-card__body{padding:var(--studio-spacing-sm)}:host(.studio-card--padding-md) .studio-card__header,:host(.studio-card--padding-md) .studio-card__footer{padding:var(--studio-spacing-md)}:host(.studio-card--padding-md) .studio-card__body{padding:var(--studio-spacing-md)}:host(.studio-card--padding-lg) .studio-card__header,:host(.studio-card--padding-lg) .studio-card__footer{padding:var(--studio-spacing-lg)}:host(.studio-card--padding-lg) .studio-card__body{padding:var(--studio-spacing-lg)}.studio-card__header{display:flex;align-items:center;justify-content:space-between;gap:var(--studio-spacing-md);flex-shrink:0}:host(.studio-card--divider) .studio-card__header{border-bottom:1px solid var(--studio-border-primary)}.studio-card__header-content{display:flex;align-items:center;gap:var(--studio-spacing-md);flex:1;min-width:0}.studio-card__avatar{width:2.5rem;height:2.5rem;border-radius:50%;object-fit:cover;flex-shrink:0}.studio-card__icon-wrapper{display:flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border-radius:50%;background:var(--studio-bg-secondary);flex-shrink:0}.studio-card__header-text{flex:1;min-width:0}.studio-card__title{margin:0;font-size:var(--studio-font-size-lg);font-weight:var(--studio-font-weight-semibold);color:var(--studio-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.studio-card__subtitle{margin:.25rem 0 0;font-size:var(--studio-font-size-sm);color:var(--studio-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.studio-card__header-actions{display:flex;align-items:center;gap:var(--studio-spacing-sm);flex-shrink:0}.studio-card__media{flex-shrink:0;overflow:hidden;position:relative}:host(.studio-card--padding-none) .studio-card__media{margin:0}:host(.studio-card--padding-sm) .studio-card__media{margin:var(--studio-spacing-sm);margin-top:0}:host(.studio-card--padding-md) .studio-card__media{margin:var(--studio-spacing-md);margin-top:0}:host(.studio-card--padding-lg) .studio-card__media{margin:var(--studio-spacing-lg);margin-top:0}.studio-card__image{width:100%;height:auto;display:block;border-radius:var(--studio-radius-sm)}.studio-card__image--cover{object-fit:cover;height:12rem}.studio-card__image--contain{object-fit:contain;max-height:16rem}.studio-card__body{flex:1;overflow-y:auto}.studio-card__footer{display:flex;align-items:center;gap:var(--studio-spacing-md);flex-shrink:0}:host(.studio-card--divider) .studio-card__footer{border-top:1px solid var(--studio-border-primary)}:host(.studio-card--blurred-footer) .studio-card__footer{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:#ffffff1a;border-top:1px solid rgba(255,255,255,.2)}:host(.studio-card--horizontal) .studio-card__container{flex-direction:row}:host(.studio-card--horizontal) .studio-card__media{width:40%;margin:0}:host(.studio-card--horizontal) .studio-card__body{flex:1}:host(.studio-card--full-width){width:100%}:host(.studio-card--full-height){height:100%}:host(.studio-card--full-height) .studio-card__container{height:100%}:host(.studio-card--hoverable) .studio-card__container{cursor:pointer;transition:all var(--studio-transition-normal)}:host(.studio-card--hoverable:hover:not(.studio-card--disabled)) .studio-card__container{transform:translateY(-2px);box-shadow:var(--studio-shadow-lg)}:host(.studio-card--pressable) .studio-card__container{cursor:pointer;transition:all var(--studio-transition-fast)}:host(.studio-card--pressable:active:not(.studio-card--disabled)) .studio-card__container{transform:scale(.98)}:host(.studio-card--clickable) .studio-card__container{cursor:pointer}:host(.studio-card--disabled){pointer-events:none;opacity:.5}:host(.studio-card--blurred) .studio-card__container{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:#ffffff1a!important;border:1px solid rgba(255,255,255,.2)}:host(.studio-card--animated){animation:cardFadeIn .3s ease-out}@keyframes cardFadeIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.studio-card__loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffe6;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:10}.studio-card__spinner{animation:spin 1s linear infinite;color:var(--studio-primary)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:host(.studio-card--loading) .studio-card__container{pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IconComponent, selector: "studio-icon", inputs: ["name", "size", "color", "strokeWidth", "absoluteStrokeWidth", "showFallback", "fallbackIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1439
|
+
}
|
|
1440
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: CardComponent, decorators: [{
|
|
1441
|
+
type: Component,
|
|
1442
|
+
args: [{ selector: 'studio-card', standalone: true, imports: [CommonModule, IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1443
|
+
'[class]': 'hostClasses()',
|
|
1444
|
+
'[attr.href]': 'href()',
|
|
1445
|
+
'[attr.target]': 'href() ? target() : null',
|
|
1446
|
+
'[attr.rel]': 'href() && target() === "_blank" ? "noopener noreferrer" : null',
|
|
1447
|
+
'[attr.disabled]': 'disabled() ? "" : null',
|
|
1448
|
+
'(click)': 'handleClick($event)'
|
|
1449
|
+
}, template: `
|
|
1450
|
+
<div class="studio-card__container">
|
|
1451
|
+
<!-- Header -->
|
|
1452
|
+
@if (showHeader() && (headerTemplate() || title() || subtitle())) {
|
|
1453
|
+
<div class="studio-card__header">
|
|
1454
|
+
@if (headerTemplate()) {
|
|
1455
|
+
<ng-container *ngTemplateOutlet="headerTemplate()!" />
|
|
1456
|
+
} @else {
|
|
1457
|
+
<div class="studio-card__header-content">
|
|
1458
|
+
@if (avatar()) {
|
|
1459
|
+
<img [src]="avatar()!" alt="" class="studio-card__avatar" />
|
|
1460
|
+
}
|
|
1461
|
+
@if (icon() && !avatar()) {
|
|
1462
|
+
<div class="studio-card__icon-wrapper">
|
|
1463
|
+
<studio-icon [name]="icon()!" [size]="iconSize()" />
|
|
1464
|
+
</div>
|
|
1465
|
+
}
|
|
1466
|
+
<div class="studio-card__header-text">
|
|
1467
|
+
@if (title()) {
|
|
1468
|
+
<h3 class="studio-card__title">{{ title() }}</h3>
|
|
1469
|
+
}
|
|
1470
|
+
@if (subtitle()) {
|
|
1471
|
+
<p class="studio-card__subtitle">{{ subtitle() }}</p>
|
|
1472
|
+
}
|
|
1473
|
+
</div>
|
|
1474
|
+
</div>
|
|
1475
|
+
@if (headerActionsTemplate()) {
|
|
1476
|
+
<div class="studio-card__header-actions">
|
|
1477
|
+
<ng-container *ngTemplateOutlet="headerActionsTemplate()!" />
|
|
1478
|
+
</div>
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
</div>
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
<!-- Media -->
|
|
1485
|
+
@if (showMedia() && (mediaTemplate() || image())) {
|
|
1486
|
+
<div class="studio-card__media">
|
|
1487
|
+
@if (mediaTemplate()) {
|
|
1488
|
+
<ng-container *ngTemplateOutlet="mediaTemplate()!" />
|
|
1489
|
+
} @else if (image()) {
|
|
1490
|
+
<img
|
|
1491
|
+
[src]="image()!"
|
|
1492
|
+
[alt]="imageAlt()"
|
|
1493
|
+
class="studio-card__image"
|
|
1494
|
+
[class.studio-card__image--cover]="imageFit() === 'cover'"
|
|
1495
|
+
[class.studio-card__image--contain]="imageFit() === 'contain'"
|
|
1496
|
+
/>
|
|
1497
|
+
}
|
|
1498
|
+
</div>
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
<!-- Body -->
|
|
1502
|
+
<div class="studio-card__body">
|
|
1503
|
+
@if (bodyTemplate()) {
|
|
1504
|
+
<ng-container *ngTemplateOutlet="bodyTemplate()!" />
|
|
1505
|
+
} @else {
|
|
1506
|
+
<ng-content />
|
|
1507
|
+
}
|
|
1508
|
+
</div>
|
|
1509
|
+
|
|
1510
|
+
<!-- Footer -->
|
|
1511
|
+
@if (showFooter() && footerTemplate()) {
|
|
1512
|
+
<div class="studio-card__footer">
|
|
1513
|
+
<ng-container *ngTemplateOutlet="footerTemplate()!" />
|
|
1514
|
+
</div>
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
<!-- Loading overlay -->
|
|
1518
|
+
@if (loading()) {
|
|
1519
|
+
<div class="studio-card__loading">
|
|
1520
|
+
<studio-icon name="loader-2" [size]="24" class="studio-card__spinner" />
|
|
1521
|
+
</div>
|
|
1522
|
+
}
|
|
1523
|
+
</div>
|
|
1524
|
+
`, styles: [":host{display:block;font-family:var(--studio-font-family);position:relative;transition:all var(--studio-transition-normal)}.studio-card__container{display:flex;flex-direction:column;height:100%;overflow:hidden;position:relative}:host(.studio-card--sm) .studio-card__container{min-height:8rem}:host(.studio-card--md) .studio-card__container{min-height:12rem}:host(.studio-card--lg) .studio-card__container{min-height:16rem}:host(.studio-card--radius-none) .studio-card__container{border-radius:var(--studio-radius-none)}:host(.studio-card--radius-sm) .studio-card__container{border-radius:var(--studio-radius-sm)}:host(.studio-card--radius-md) .studio-card__container{border-radius:var(--studio-radius-md)}:host(.studio-card--radius-lg) .studio-card__container{border-radius:var(--studio-radius-lg)}:host(.studio-card--radius-xl) .studio-card__container{border-radius:var(--studio-radius-xl)}:host(.studio-card--shadow-none) .studio-card__container{box-shadow:none}:host(.studio-card--shadow-sm) .studio-card__container{box-shadow:var(--studio-shadow-sm)}:host(.studio-card--shadow-md) .studio-card__container{box-shadow:var(--studio-shadow-md)}:host(.studio-card--shadow-lg) .studio-card__container{box-shadow:var(--studio-shadow-lg)}:host(.studio-card--shadow-xl) .studio-card__container{box-shadow:var(--studio-shadow-xl)}:host(.studio-card--elevated.studio-card--default) .studio-card__container{background:var(--studio-bg-primary);border:1px solid var(--studio-border-primary)}:host(.studio-card--filled.studio-card--default) .studio-card__container{background:var(--studio-bg-secondary);border:1px solid transparent}:host(.studio-card--outlined.studio-card--default) .studio-card__container{background:transparent;border:2px solid var(--studio-border-primary)}:host(.studio-card--ghost.studio-card--default) .studio-card__container{background:transparent;border:1px solid transparent}:host(.studio-card--elevated.studio-card--primary) .studio-card__container{background:var(--studio-primary-bg);border:1px solid var(--studio-primary)}:host(.studio-card--filled.studio-card--primary) .studio-card__container{background:var(--studio-primary);color:#fff;border:1px solid transparent}:host(.studio-card--outlined.studio-card--primary) .studio-card__container{background:transparent;border:2px solid var(--studio-primary);color:var(--studio-primary)}:host(.studio-card--ghost.studio-card--primary) .studio-card__container{background:var(--studio-primary-bg);border:1px solid transparent;color:var(--studio-primary)}:host(.studio-card--elevated.studio-card--secondary) .studio-card__container{background:var(--studio-bg-primary);border:1px solid var(--studio-text-secondary)}:host(.studio-card--filled.studio-card--secondary) .studio-card__container{background:var(--studio-text-secondary);color:#fff;border:1px solid transparent}:host(.studio-card--outlined.studio-card--secondary) .studio-card__container{background:transparent;border:2px solid var(--studio-text-secondary);color:var(--studio-text-secondary)}:host(.studio-card--ghost.studio-card--secondary) .studio-card__container{background:var(--studio-bg-secondary);border:1px solid transparent;color:var(--studio-text-secondary)}:host(.studio-card--elevated.studio-card--success) .studio-card__container{background:var(--studio-success-bg);border:1px solid var(--studio-success)}:host(.studio-card--filled.studio-card--success) .studio-card__container{background:var(--studio-success);color:#fff;border:1px solid transparent}:host(.studio-card--outlined.studio-card--success) .studio-card__container{background:transparent;border:2px solid var(--studio-success);color:var(--studio-success)}:host(.studio-card--ghost.studio-card--success) .studio-card__container{background:var(--studio-success-bg);border:1px solid transparent;color:var(--studio-success)}:host(.studio-card--elevated.studio-card--error) .studio-card__container{background:var(--studio-error-bg);border:1px solid var(--studio-error)}:host(.studio-card--filled.studio-card--error) .studio-card__container{background:var(--studio-error);color:#fff;border:1px solid transparent}:host(.studio-card--outlined.studio-card--error) .studio-card__container{background:transparent;border:2px solid var(--studio-error);color:var(--studio-error)}:host(.studio-card--ghost.studio-card--error) .studio-card__container{background:var(--studio-error-bg);border:1px solid transparent;color:var(--studio-error)}:host(.studio-card--elevated.studio-card--warning) .studio-card__container{background:var(--studio-warning-bg);border:1px solid var(--studio-warning)}:host(.studio-card--filled.studio-card--warning) .studio-card__container{background:var(--studio-warning);color:#fff;border:1px solid transparent}:host(.studio-card--outlined.studio-card--warning) .studio-card__container{background:transparent;border:2px solid var(--studio-warning);color:var(--studio-warning)}:host(.studio-card--ghost.studio-card--warning) .studio-card__container{background:var(--studio-warning-bg);border:1px solid transparent;color:var(--studio-warning)}:host(.studio-card--elevated.studio-card--neutral) .studio-card__container{background:var(--studio-bg-tertiary);border:1px solid var(--studio-border-secondary)}:host(.studio-card--filled.studio-card--neutral) .studio-card__container{background:var(--studio-bg-secondary);border:1px solid transparent}:host(.studio-card--outlined.studio-card--neutral) .studio-card__container{background:transparent;border:2px solid var(--studio-border-secondary)}:host(.studio-card--ghost.studio-card--neutral) .studio-card__container{background:transparent;border:1px solid transparent}:host(.studio-card--padding-none) .studio-card__header,:host(.studio-card--padding-none) .studio-card__body,:host(.studio-card--padding-none) .studio-card__footer{padding:0}:host(.studio-card--padding-sm) .studio-card__header,:host(.studio-card--padding-sm) .studio-card__footer{padding:var(--studio-spacing-sm)}:host(.studio-card--padding-sm) .studio-card__body{padding:var(--studio-spacing-sm)}:host(.studio-card--padding-md) .studio-card__header,:host(.studio-card--padding-md) .studio-card__footer{padding:var(--studio-spacing-md)}:host(.studio-card--padding-md) .studio-card__body{padding:var(--studio-spacing-md)}:host(.studio-card--padding-lg) .studio-card__header,:host(.studio-card--padding-lg) .studio-card__footer{padding:var(--studio-spacing-lg)}:host(.studio-card--padding-lg) .studio-card__body{padding:var(--studio-spacing-lg)}.studio-card__header{display:flex;align-items:center;justify-content:space-between;gap:var(--studio-spacing-md);flex-shrink:0}:host(.studio-card--divider) .studio-card__header{border-bottom:1px solid var(--studio-border-primary)}.studio-card__header-content{display:flex;align-items:center;gap:var(--studio-spacing-md);flex:1;min-width:0}.studio-card__avatar{width:2.5rem;height:2.5rem;border-radius:50%;object-fit:cover;flex-shrink:0}.studio-card__icon-wrapper{display:flex;align-items:center;justify-content:center;width:2.5rem;height:2.5rem;border-radius:50%;background:var(--studio-bg-secondary);flex-shrink:0}.studio-card__header-text{flex:1;min-width:0}.studio-card__title{margin:0;font-size:var(--studio-font-size-lg);font-weight:var(--studio-font-weight-semibold);color:var(--studio-text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.studio-card__subtitle{margin:.25rem 0 0;font-size:var(--studio-font-size-sm);color:var(--studio-text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.studio-card__header-actions{display:flex;align-items:center;gap:var(--studio-spacing-sm);flex-shrink:0}.studio-card__media{flex-shrink:0;overflow:hidden;position:relative}:host(.studio-card--padding-none) .studio-card__media{margin:0}:host(.studio-card--padding-sm) .studio-card__media{margin:var(--studio-spacing-sm);margin-top:0}:host(.studio-card--padding-md) .studio-card__media{margin:var(--studio-spacing-md);margin-top:0}:host(.studio-card--padding-lg) .studio-card__media{margin:var(--studio-spacing-lg);margin-top:0}.studio-card__image{width:100%;height:auto;display:block;border-radius:var(--studio-radius-sm)}.studio-card__image--cover{object-fit:cover;height:12rem}.studio-card__image--contain{object-fit:contain;max-height:16rem}.studio-card__body{flex:1;overflow-y:auto}.studio-card__footer{display:flex;align-items:center;gap:var(--studio-spacing-md);flex-shrink:0}:host(.studio-card--divider) .studio-card__footer{border-top:1px solid var(--studio-border-primary)}:host(.studio-card--blurred-footer) .studio-card__footer{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:#ffffff1a;border-top:1px solid rgba(255,255,255,.2)}:host(.studio-card--horizontal) .studio-card__container{flex-direction:row}:host(.studio-card--horizontal) .studio-card__media{width:40%;margin:0}:host(.studio-card--horizontal) .studio-card__body{flex:1}:host(.studio-card--full-width){width:100%}:host(.studio-card--full-height){height:100%}:host(.studio-card--full-height) .studio-card__container{height:100%}:host(.studio-card--hoverable) .studio-card__container{cursor:pointer;transition:all var(--studio-transition-normal)}:host(.studio-card--hoverable:hover:not(.studio-card--disabled)) .studio-card__container{transform:translateY(-2px);box-shadow:var(--studio-shadow-lg)}:host(.studio-card--pressable) .studio-card__container{cursor:pointer;transition:all var(--studio-transition-fast)}:host(.studio-card--pressable:active:not(.studio-card--disabled)) .studio-card__container{transform:scale(.98)}:host(.studio-card--clickable) .studio-card__container{cursor:pointer}:host(.studio-card--disabled){pointer-events:none;opacity:.5}:host(.studio-card--blurred) .studio-card__container{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);background:#ffffff1a!important;border:1px solid rgba(255,255,255,.2)}:host(.studio-card--animated){animation:cardFadeIn .3s ease-out}@keyframes cardFadeIn{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.studio-card__loading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:#ffffffe6;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:10}.studio-card__spinner{animation:spin 1s linear infinite;color:var(--studio-primary)}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:host(.studio-card--loading) .studio-card__container{pointer-events:none}\n"] }]
|
|
1525
|
+
}], propDecorators: { variantInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], sizeInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], colorInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], radiusInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], shadowInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "shadow", required: false }] }], paddingInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], imagePosition: [{ type: i0.Input, args: [{ isSignal: true, alias: "imagePosition", required: false }] }], fullWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullWidth", required: false }] }], fullHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "fullHeight", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], subtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitle", required: false }] }], avatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "avatar", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], image: [{ type: i0.Input, args: [{ isSignal: true, alias: "image", required: false }] }], imageAlt: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageAlt", required: false }] }], imageFit: [{ type: i0.Input, args: [{ isSignal: true, alias: "imageFit", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], showMedia: [{ type: i0.Input, args: [{ isSignal: true, alias: "showMedia", required: false }] }], showFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "showFooter", required: false }] }], divider: [{ type: i0.Input, args: [{ isSignal: true, alias: "divider", required: false }] }], hoverable: [{ type: i0.Input, args: [{ isSignal: true, alias: "hoverable", required: false }] }], pressable: [{ type: i0.Input, args: [{ isSignal: true, alias: "pressable", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], loading: [{ type: i0.Input, args: [{ isSignal: true, alias: "loading", required: false }] }], href: [{ type: i0.Input, args: [{ isSignal: true, alias: "href", required: false }] }], target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: false }] }], blurred: [{ type: i0.Input, args: [{ isSignal: true, alias: "blurred", required: false }] }], blurredFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "blurredFooter", required: false }] }], animated: [{ type: i0.Input, args: [{ isSignal: true, alias: "animated", required: false }] }], clicked: [{ type: i0.Output, args: ["clicked"] }], headerAction: [{ type: i0.Output, args: ["headerAction"] }], headerTemplate: [{ type: i0.ContentChild, args: ['cardHeader', { isSignal: true }] }], headerActionsTemplate: [{ type: i0.ContentChild, args: ['cardHeaderActions', { isSignal: true }] }], mediaTemplate: [{ type: i0.ContentChild, args: ['cardMedia', { isSignal: true }] }], bodyTemplate: [{ type: i0.ContentChild, args: ['cardBody', { isSignal: true }] }], footerTemplate: [{ type: i0.ContentChild, args: ['cardFooter', { isSignal: true }] }] } });
|
|
1526
|
+
|
|
1527
|
+
/**
|
|
1528
|
+
* Card component types
|
|
1529
|
+
*/
|
|
1530
|
+
|
|
1531
|
+
class ChatMessageComponent {
|
|
1532
|
+
message = input.required(...(ngDevMode ? [{ debugName: "message" }] : []));
|
|
1533
|
+
currentUserId = input.required(...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
|
|
1534
|
+
showAvatar = input(true, ...(ngDevMode ? [{ debugName: "showAvatar" }] : []));
|
|
1535
|
+
showTimestamp = input(true, ...(ngDevMode ? [{ debugName: "showTimestamp" }] : []));
|
|
1536
|
+
showUserName = input(true, ...(ngDevMode ? [{ debugName: "showUserName" }] : []));
|
|
1537
|
+
compact = input(false, ...(ngDevMode ? [{ debugName: "compact" }] : []));
|
|
1538
|
+
isOwn = computed(() => this.message().userId === this.currentUserId(), ...(ngDevMode ? [{ debugName: "isOwn" }] : []));
|
|
1539
|
+
hostClasses = computed(() => {
|
|
1540
|
+
const classes = ['studio-chat-message'];
|
|
1541
|
+
if (this.isOwn())
|
|
1542
|
+
classes.push('chat-message--own');
|
|
1543
|
+
if (this.message().type === 'system')
|
|
1544
|
+
classes.push('chat-message--system');
|
|
1545
|
+
if (this.compact())
|
|
1546
|
+
classes.push('chat-message--compact');
|
|
1547
|
+
if (this.message().status === 'read')
|
|
1548
|
+
classes.push('chat-message--status-read');
|
|
1549
|
+
if (this.message().status === 'error')
|
|
1550
|
+
classes.push('chat-message--status-error');
|
|
1551
|
+
return classes.join(' ');
|
|
1552
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
|
|
1553
|
+
getInitials(name) {
|
|
1554
|
+
return name
|
|
1555
|
+
.split(' ')
|
|
1556
|
+
.map(n => n[0])
|
|
1557
|
+
.slice(0, 2)
|
|
1558
|
+
.join('')
|
|
1559
|
+
.toUpperCase();
|
|
1560
|
+
}
|
|
1561
|
+
formatTime(date) {
|
|
1562
|
+
const now = new Date();
|
|
1563
|
+
const messageDate = new Date(date);
|
|
1564
|
+
const diff = now.getTime() - messageDate.getTime();
|
|
1565
|
+
const minutes = Math.floor(diff / 60000);
|
|
1566
|
+
const hours = Math.floor(diff / 3600000);
|
|
1567
|
+
const days = Math.floor(diff / 86400000);
|
|
1568
|
+
if (minutes < 1)
|
|
1569
|
+
return 'Just now';
|
|
1570
|
+
if (minutes < 60)
|
|
1571
|
+
return `${minutes}m ago`;
|
|
1572
|
+
if (hours < 24)
|
|
1573
|
+
return `${hours}h ago`;
|
|
1574
|
+
if (days === 1)
|
|
1575
|
+
return 'Yesterday';
|
|
1576
|
+
if (days < 7)
|
|
1577
|
+
return `${days}d ago`;
|
|
1578
|
+
return messageDate.toLocaleDateString('en-US', {
|
|
1579
|
+
month: 'short',
|
|
1580
|
+
day: 'numeric'
|
|
1581
|
+
});
|
|
1582
|
+
}
|
|
1583
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ChatMessageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1584
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: ChatMessageComponent, isStandalone: true, selector: "studio-chat-message", inputs: { message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: true, transformFunction: null }, currentUserId: { classPropertyName: "currentUserId", publicName: "currentUserId", isSignal: true, isRequired: true, transformFunction: null }, showAvatar: { classPropertyName: "showAvatar", publicName: "showAvatar", isSignal: true, isRequired: false, transformFunction: null }, showTimestamp: { classPropertyName: "showTimestamp", publicName: "showTimestamp", isSignal: true, isRequired: false, transformFunction: null }, showUserName: { classPropertyName: "showUserName", publicName: "showUserName", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "hostClasses()" } }, ngImport: i0, template: `
|
|
1585
|
+
<div class="chat-message__container">
|
|
1586
|
+
@if (showAvatar() && !isOwn()) {
|
|
1587
|
+
<div class="chat-message__avatar">
|
|
1588
|
+
@if (message().userAvatar) {
|
|
1589
|
+
<img [src]="message().userAvatar" [alt]="message().userName" />
|
|
1590
|
+
} @else {
|
|
1591
|
+
<div class="chat-message__avatar-fallback">
|
|
1592
|
+
{{ getInitials(message().userName) }}
|
|
1593
|
+
</div>
|
|
1594
|
+
}
|
|
1595
|
+
</div>
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
<div class="chat-message__content-wrapper">
|
|
1599
|
+
@if (!isOwn() && showUserName()) {
|
|
1600
|
+
<div class="chat-message__user-name">{{ message().userName }}</div>
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
<div class="chat-message__bubble">
|
|
1604
|
+
@if (message().type === 'system') {
|
|
1605
|
+
<div class="chat-message__system">{{ message().content }}</div>
|
|
1606
|
+
} @else {
|
|
1607
|
+
<div class="chat-message__text">{{ message().content }}</div>
|
|
1608
|
+
}
|
|
1609
|
+
|
|
1610
|
+
@if (message().edited) {
|
|
1611
|
+
<span class="chat-message__edited">(edited)</span>
|
|
1612
|
+
}
|
|
1613
|
+
</div>
|
|
1614
|
+
|
|
1615
|
+
<div class="chat-message__meta">
|
|
1616
|
+
@if (showTimestamp()) {
|
|
1617
|
+
<span class="chat-message__time">{{ formatTime(message().timestamp) }}</span>
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
@if (isOwn() && message().status && message().status !== 'sending') {
|
|
1621
|
+
<span class="chat-message__status">
|
|
1622
|
+
@if (message().status === 'sent') {
|
|
1623
|
+
<studio-icon name="check" [size]="12" />
|
|
1624
|
+
}
|
|
1625
|
+
@if (message().status === 'delivered' || message().status === 'read') {
|
|
1626
|
+
<studio-icon name="check-check" [size]="12" />
|
|
1627
|
+
}
|
|
1628
|
+
@if (message().status === 'error') {
|
|
1629
|
+
<studio-icon name="alert-circle" [size]="12" />
|
|
1630
|
+
}
|
|
1631
|
+
</span>
|
|
1632
|
+
}
|
|
1633
|
+
</div>
|
|
1634
|
+
</div>
|
|
1635
|
+
</div>
|
|
1636
|
+
`, isInline: true, styles: [":host{display:block;margin-bottom:.75rem}:host(.chat-message--own) .chat-message__container{justify-content:flex-end}:host(.chat-message--own) .chat-message__bubble{background:var(--studio-primary);color:#fff}:host(.chat-message--own) .chat-message__meta{justify-content:flex-end}:host(.chat-message--system){text-align:center;margin:1rem 0}:host(.chat-message--system) .chat-message__system{display:inline-block;padding:.25rem .75rem;background:var(--studio-bg-secondary);color:var(--studio-text-secondary);border-radius:var(--studio-radius-full);font-size:.75rem}:host(.chat-message--compact){margin-bottom:.25rem}.chat-message__container{display:flex;gap:.75rem;align-items:flex-end}.chat-message__avatar{width:32px;height:32px;border-radius:50%;overflow:hidden;flex-shrink:0}.chat-message__avatar img{width:100%;height:100%;object-fit:cover}.chat-message__avatar-fallback{width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:var(--studio-primary);color:#fff;font-size:.75rem;font-weight:600}.chat-message__content-wrapper{max-width:70%;display:flex;flex-direction:column;gap:.25rem}.chat-message__user-name{font-size:.75rem;font-weight:500;color:var(--studio-text-secondary);padding-left:.75rem}.chat-message__bubble{padding:.625rem .875rem;border-radius:var(--studio-radius-lg);background:var(--studio-bg-secondary);color:var(--studio-text-primary);word-wrap:break-word;position:relative}.chat-message__text{white-space:pre-wrap;line-height:1.5}.chat-message__edited{font-size:.6875rem;color:var(--studio-text-tertiary);margin-left:.25rem}.chat-message__meta{display:flex;align-items:center;gap:.25rem;padding:0 .75rem}.chat-message__time{font-size:.6875rem;color:var(--studio-text-tertiary)}.chat-message__status{display:flex;align-items:center;color:var(--studio-text-tertiary)}:host(.chat-message--own) .chat-message__status{color:var(--studio-text-tertiary)}:host(.chat-message--status-read) .chat-message__status{color:var(--studio-primary)}:host(.chat-message--status-error) .chat-message__status{color:var(--studio-error)}:host(.chat-message--compact) .chat-message__avatar{width:24px;height:24px}:host(.chat-message--compact) .chat-message__bubble{padding:.5rem .75rem;font-size:.875rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: IconComponent, selector: "studio-icon", inputs: ["name", "size", "color", "strokeWidth", "absoluteStrokeWidth", "showFallback", "fallbackIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1637
|
+
}
|
|
1638
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ChatMessageComponent, decorators: [{
|
|
1639
|
+
type: Component,
|
|
1640
|
+
args: [{ selector: 'studio-chat-message', standalone: true, imports: [CommonModule, IconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1641
|
+
'[class]': 'hostClasses()'
|
|
1642
|
+
}, template: `
|
|
1643
|
+
<div class="chat-message__container">
|
|
1644
|
+
@if (showAvatar() && !isOwn()) {
|
|
1645
|
+
<div class="chat-message__avatar">
|
|
1646
|
+
@if (message().userAvatar) {
|
|
1647
|
+
<img [src]="message().userAvatar" [alt]="message().userName" />
|
|
1648
|
+
} @else {
|
|
1649
|
+
<div class="chat-message__avatar-fallback">
|
|
1650
|
+
{{ getInitials(message().userName) }}
|
|
1651
|
+
</div>
|
|
1652
|
+
}
|
|
1653
|
+
</div>
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
<div class="chat-message__content-wrapper">
|
|
1657
|
+
@if (!isOwn() && showUserName()) {
|
|
1658
|
+
<div class="chat-message__user-name">{{ message().userName }}</div>
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
<div class="chat-message__bubble">
|
|
1662
|
+
@if (message().type === 'system') {
|
|
1663
|
+
<div class="chat-message__system">{{ message().content }}</div>
|
|
1664
|
+
} @else {
|
|
1665
|
+
<div class="chat-message__text">{{ message().content }}</div>
|
|
1666
|
+
}
|
|
1667
|
+
|
|
1668
|
+
@if (message().edited) {
|
|
1669
|
+
<span class="chat-message__edited">(edited)</span>
|
|
1670
|
+
}
|
|
1671
|
+
</div>
|
|
1672
|
+
|
|
1673
|
+
<div class="chat-message__meta">
|
|
1674
|
+
@if (showTimestamp()) {
|
|
1675
|
+
<span class="chat-message__time">{{ formatTime(message().timestamp) }}</span>
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
@if (isOwn() && message().status && message().status !== 'sending') {
|
|
1679
|
+
<span class="chat-message__status">
|
|
1680
|
+
@if (message().status === 'sent') {
|
|
1681
|
+
<studio-icon name="check" [size]="12" />
|
|
1682
|
+
}
|
|
1683
|
+
@if (message().status === 'delivered' || message().status === 'read') {
|
|
1684
|
+
<studio-icon name="check-check" [size]="12" />
|
|
1685
|
+
}
|
|
1686
|
+
@if (message().status === 'error') {
|
|
1687
|
+
<studio-icon name="alert-circle" [size]="12" />
|
|
1688
|
+
}
|
|
1689
|
+
</span>
|
|
1690
|
+
}
|
|
1691
|
+
</div>
|
|
1692
|
+
</div>
|
|
1693
|
+
</div>
|
|
1694
|
+
`, styles: [":host{display:block;margin-bottom:.75rem}:host(.chat-message--own) .chat-message__container{justify-content:flex-end}:host(.chat-message--own) .chat-message__bubble{background:var(--studio-primary);color:#fff}:host(.chat-message--own) .chat-message__meta{justify-content:flex-end}:host(.chat-message--system){text-align:center;margin:1rem 0}:host(.chat-message--system) .chat-message__system{display:inline-block;padding:.25rem .75rem;background:var(--studio-bg-secondary);color:var(--studio-text-secondary);border-radius:var(--studio-radius-full);font-size:.75rem}:host(.chat-message--compact){margin-bottom:.25rem}.chat-message__container{display:flex;gap:.75rem;align-items:flex-end}.chat-message__avatar{width:32px;height:32px;border-radius:50%;overflow:hidden;flex-shrink:0}.chat-message__avatar img{width:100%;height:100%;object-fit:cover}.chat-message__avatar-fallback{width:100%;height:100%;display:flex;align-items:center;justify-content:center;background:var(--studio-primary);color:#fff;font-size:.75rem;font-weight:600}.chat-message__content-wrapper{max-width:70%;display:flex;flex-direction:column;gap:.25rem}.chat-message__user-name{font-size:.75rem;font-weight:500;color:var(--studio-text-secondary);padding-left:.75rem}.chat-message__bubble{padding:.625rem .875rem;border-radius:var(--studio-radius-lg);background:var(--studio-bg-secondary);color:var(--studio-text-primary);word-wrap:break-word;position:relative}.chat-message__text{white-space:pre-wrap;line-height:1.5}.chat-message__edited{font-size:.6875rem;color:var(--studio-text-tertiary);margin-left:.25rem}.chat-message__meta{display:flex;align-items:center;gap:.25rem;padding:0 .75rem}.chat-message__time{font-size:.6875rem;color:var(--studio-text-tertiary)}.chat-message__status{display:flex;align-items:center;color:var(--studio-text-tertiary)}:host(.chat-message--own) .chat-message__status{color:var(--studio-text-tertiary)}:host(.chat-message--status-read) .chat-message__status{color:var(--studio-primary)}:host(.chat-message--status-error) .chat-message__status{color:var(--studio-error)}:host(.chat-message--compact) .chat-message__avatar{width:24px;height:24px}:host(.chat-message--compact) .chat-message__bubble{padding:.5rem .75rem;font-size:.875rem}\n"] }]
|
|
1695
|
+
}], propDecorators: { message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: true }] }], currentUserId: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentUserId", required: true }] }], showAvatar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAvatar", required: false }] }], showTimestamp: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTimestamp", required: false }] }], showUserName: [{ type: i0.Input, args: [{ isSignal: true, alias: "showUserName", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }] } });
|
|
1696
|
+
|
|
1697
|
+
class ChatInputComponent {
|
|
1698
|
+
placeholder = input('Type a message...', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
1699
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
1700
|
+
compact = input(false, ...(ngDevMode ? [{ debugName: "compact" }] : []));
|
|
1701
|
+
messageSubmit = output();
|
|
1702
|
+
typing = output();
|
|
1703
|
+
inputValue = signal('', ...(ngDevMode ? [{ debugName: "inputValue" }] : []));
|
|
1704
|
+
textareaRef = viewChild('textareaRef', ...(ngDevMode ? [{ debugName: "textareaRef" }] : []));
|
|
1705
|
+
typingTimeout;
|
|
1706
|
+
canSend = computed(() => this.inputValue().trim().length > 0 && !this.disabled(), ...(ngDevMode ? [{ debugName: "canSend" }] : []));
|
|
1707
|
+
hostClasses = computed(() => {
|
|
1708
|
+
const classes = ['studio-chat-input'];
|
|
1709
|
+
if (this.compact())
|
|
1710
|
+
classes.push('chat-input--compact');
|
|
1711
|
+
return classes.join(' ');
|
|
1712
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
|
|
1713
|
+
constructor() {
|
|
1714
|
+
// Auto-resize textarea
|
|
1715
|
+
effect(() => {
|
|
1716
|
+
const textarea = this.textareaRef()?.nativeElement;
|
|
1717
|
+
if (textarea) {
|
|
1718
|
+
textarea.style.height = 'auto';
|
|
1719
|
+
textarea.style.height = textarea.scrollHeight + 'px';
|
|
1720
|
+
}
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1723
|
+
onKeyDown(event) {
|
|
1724
|
+
if (event.key === 'Enter' && !event.shiftKey) {
|
|
1725
|
+
event.preventDefault();
|
|
1726
|
+
this.handleSubmit();
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
onInput() {
|
|
1730
|
+
// Emit typing indicator
|
|
1731
|
+
this.typing.emit(true);
|
|
1732
|
+
// Clear previous timeout
|
|
1733
|
+
if (this.typingTimeout) {
|
|
1734
|
+
clearTimeout(this.typingTimeout);
|
|
1735
|
+
}
|
|
1736
|
+
// Set new timeout to stop typing after 1 second
|
|
1737
|
+
this.typingTimeout = setTimeout(() => {
|
|
1738
|
+
this.typing.emit(false);
|
|
1739
|
+
}, 1000);
|
|
1740
|
+
// Auto-resize
|
|
1741
|
+
const textarea = this.textareaRef()?.nativeElement;
|
|
1742
|
+
if (textarea) {
|
|
1743
|
+
textarea.style.height = 'auto';
|
|
1744
|
+
textarea.style.height = textarea.scrollHeight + 'px';
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
handleSubmit() {
|
|
1748
|
+
const content = this.inputValue().trim();
|
|
1749
|
+
if (content && !this.disabled()) {
|
|
1750
|
+
this.messageSubmit.emit({ content });
|
|
1751
|
+
this.inputValue.set('');
|
|
1752
|
+
// Reset textarea height
|
|
1753
|
+
const textarea = this.textareaRef()?.nativeElement;
|
|
1754
|
+
if (textarea) {
|
|
1755
|
+
textarea.style.height = 'auto';
|
|
1756
|
+
}
|
|
1757
|
+
// Stop typing indicator
|
|
1758
|
+
if (this.typingTimeout) {
|
|
1759
|
+
clearTimeout(this.typingTimeout);
|
|
1760
|
+
}
|
|
1761
|
+
this.typing.emit(false);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
focus() {
|
|
1765
|
+
this.textareaRef()?.nativeElement.focus();
|
|
1766
|
+
}
|
|
1767
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ChatInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1768
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.12", type: ChatInputComponent, isStandalone: true, selector: "studio-chat-input", inputs: { placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, compact: { classPropertyName: "compact", publicName: "compact", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { messageSubmit: "messageSubmit", typing: "typing" }, host: { properties: { "class": "hostClasses()" } }, viewQueries: [{ propertyName: "textareaRef", first: true, predicate: ["textareaRef"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
1769
|
+
<div class="chat-input__container">
|
|
1770
|
+
<textarea
|
|
1771
|
+
#textareaRef
|
|
1772
|
+
class="chat-input__textarea"
|
|
1773
|
+
[placeholder]="placeholder()"
|
|
1774
|
+
[disabled]="disabled()"
|
|
1775
|
+
[(ngModel)]="inputValue"
|
|
1776
|
+
(keydown)="onKeyDown($event)"
|
|
1777
|
+
(input)="onInput()"
|
|
1778
|
+
rows="1"
|
|
1779
|
+
></textarea>
|
|
1780
|
+
|
|
1781
|
+
<studio-button
|
|
1782
|
+
variant="ghost"
|
|
1783
|
+
size="sm"
|
|
1784
|
+
[disabled]="!canSend()"
|
|
1785
|
+
(click)="handleSubmit()"
|
|
1786
|
+
class="chat-input__send-button"
|
|
1787
|
+
>
|
|
1788
|
+
<studio-icon name="send" [size]="20" />
|
|
1789
|
+
</studio-button>
|
|
1790
|
+
</div>
|
|
1791
|
+
`, isInline: true, styles: [":host{display:block}.chat-input__container{display:flex;align-items:flex-end;gap:.5rem;padding:1rem;background:var(--studio-bg-primary);border-top:1px solid var(--studio-border-primary)}.chat-input__textarea{flex:1;min-height:40px;max-height:120px;padding:.625rem .875rem;border:1px solid var(--studio-border-primary);border-radius:var(--studio-radius-md);background:var(--studio-bg-primary);color:var(--studio-text-primary);font-family:inherit;font-size:.875rem;line-height:1.5;resize:none;overflow-y:auto;transition:border-color .15s ease}.chat-input__textarea:focus{outline:none;border-color:var(--studio-primary)}.chat-input__textarea:disabled{opacity:.5;cursor:not-allowed}.chat-input__textarea::placeholder{color:var(--studio-text-tertiary)}.chat-input__send-button{flex-shrink:0}:host(.chat-input--compact) .chat-input__container{padding:.75rem}:host(.chat-input--compact) .chat-input__textarea{padding:.5rem .75rem;font-size:.8125rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IconComponent, selector: "studio-icon", inputs: ["name", "size", "color", "strokeWidth", "absoluteStrokeWidth", "showFallback", "fallbackIcon"] }, { kind: "component", type: ButtonComponent, selector: "studio-button", inputs: ["variant", "size", "color", "radius", "shadow", "compact", "disabled", "loading", "loadingText", "fullWidth", "type", "icon", "iconPosition", "href", "target", "badge", "badgeColor", "ariaLabel"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1792
|
+
}
|
|
1793
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ChatInputComponent, decorators: [{
|
|
1794
|
+
type: Component,
|
|
1795
|
+
args: [{ selector: 'studio-chat-input', standalone: true, imports: [CommonModule, FormsModule, IconComponent, ButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1796
|
+
'[class]': 'hostClasses()'
|
|
1797
|
+
}, template: `
|
|
1798
|
+
<div class="chat-input__container">
|
|
1799
|
+
<textarea
|
|
1800
|
+
#textareaRef
|
|
1801
|
+
class="chat-input__textarea"
|
|
1802
|
+
[placeholder]="placeholder()"
|
|
1803
|
+
[disabled]="disabled()"
|
|
1804
|
+
[(ngModel)]="inputValue"
|
|
1805
|
+
(keydown)="onKeyDown($event)"
|
|
1806
|
+
(input)="onInput()"
|
|
1807
|
+
rows="1"
|
|
1808
|
+
></textarea>
|
|
1809
|
+
|
|
1810
|
+
<studio-button
|
|
1811
|
+
variant="ghost"
|
|
1812
|
+
size="sm"
|
|
1813
|
+
[disabled]="!canSend()"
|
|
1814
|
+
(click)="handleSubmit()"
|
|
1815
|
+
class="chat-input__send-button"
|
|
1816
|
+
>
|
|
1817
|
+
<studio-icon name="send" [size]="20" />
|
|
1818
|
+
</studio-button>
|
|
1819
|
+
</div>
|
|
1820
|
+
`, styles: [":host{display:block}.chat-input__container{display:flex;align-items:flex-end;gap:.5rem;padding:1rem;background:var(--studio-bg-primary);border-top:1px solid var(--studio-border-primary)}.chat-input__textarea{flex:1;min-height:40px;max-height:120px;padding:.625rem .875rem;border:1px solid var(--studio-border-primary);border-radius:var(--studio-radius-md);background:var(--studio-bg-primary);color:var(--studio-text-primary);font-family:inherit;font-size:.875rem;line-height:1.5;resize:none;overflow-y:auto;transition:border-color .15s ease}.chat-input__textarea:focus{outline:none;border-color:var(--studio-primary)}.chat-input__textarea:disabled{opacity:.5;cursor:not-allowed}.chat-input__textarea::placeholder{color:var(--studio-text-tertiary)}.chat-input__send-button{flex-shrink:0}:host(.chat-input--compact) .chat-input__container{padding:.75rem}:host(.chat-input--compact) .chat-input__textarea{padding:.5rem .75rem;font-size:.8125rem}\n"] }]
|
|
1821
|
+
}], ctorParameters: () => [], propDecorators: { placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], messageSubmit: [{ type: i0.Output, args: ["messageSubmit"] }], typing: [{ type: i0.Output, args: ["typing"] }], textareaRef: [{ type: i0.ViewChild, args: ['textareaRef', { isSignal: true }] }] } });
|
|
1822
|
+
|
|
1823
|
+
/**
|
|
1824
|
+
* Chat component - Flexible chat/messaging component
|
|
1825
|
+
*
|
|
1826
|
+
* @example
|
|
1827
|
+
* <studio-chat
|
|
1828
|
+
* [messages]="messages"
|
|
1829
|
+
* [currentUserId]="currentUser.id"
|
|
1830
|
+
* variant="default"
|
|
1831
|
+
* (messageSubmit)="handleMessage($event)"
|
|
1832
|
+
* />
|
|
1833
|
+
*/
|
|
1834
|
+
class ChatComponent {
|
|
1835
|
+
// ========== Required ==========
|
|
1836
|
+
messages = input.required(...(ngDevMode ? [{ debugName: "messages" }] : []));
|
|
1837
|
+
currentUserId = input.required(...(ngDevMode ? [{ debugName: "currentUserId" }] : []));
|
|
1838
|
+
// ========== Appearance ==========
|
|
1839
|
+
variant = input('default', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
1840
|
+
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
1841
|
+
height = input('600px', ...(ngDevMode ? [{ debugName: "height" }] : []));
|
|
1842
|
+
// ========== Behavior ==========
|
|
1843
|
+
placeholder = input('Type a message...', ...(ngDevMode ? [{ debugName: "placeholder" }] : []));
|
|
1844
|
+
showAvatars = input(true, ...(ngDevMode ? [{ debugName: "showAvatars" }] : []));
|
|
1845
|
+
showTimestamps = input(true, ...(ngDevMode ? [{ debugName: "showTimestamps" }] : []));
|
|
1846
|
+
showUserNames = input(true, ...(ngDevMode ? [{ debugName: "showUserNames" }] : []));
|
|
1847
|
+
enableAutoScroll = input(true, ...(ngDevMode ? [{ debugName: "enableAutoScroll" }] : []));
|
|
1848
|
+
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
1849
|
+
// ========== Customization ==========
|
|
1850
|
+
class = input('', ...(ngDevMode ? [{ debugName: "class" }] : []));
|
|
1851
|
+
// ========== Outputs ==========
|
|
1852
|
+
messageSubmit = output();
|
|
1853
|
+
typing = output();
|
|
1854
|
+
// ========== State ==========
|
|
1855
|
+
messagesContainerRef = viewChild('messagesContainer', ...(ngDevMode ? [{ debugName: "messagesContainerRef" }] : []));
|
|
1856
|
+
isScrolledUp = signal(false, ...(ngDevMode ? [{ debugName: "isScrolledUp" }] : []));
|
|
1857
|
+
shouldAutoScroll = signal(true, ...(ngDevMode ? [{ debugName: "shouldAutoScroll" }] : []));
|
|
1858
|
+
hostClasses = computed(() => {
|
|
1859
|
+
const classes = ['studio-chat'];
|
|
1860
|
+
classes.push(`studio-chat--${this.variant()}`);
|
|
1861
|
+
classes.push(`studio-chat--${this.size()}`);
|
|
1862
|
+
if (this.disabled())
|
|
1863
|
+
classes.push('studio-chat--disabled');
|
|
1864
|
+
if (this.class())
|
|
1865
|
+
classes.push(this.class());
|
|
1866
|
+
return classes.join(' ');
|
|
1867
|
+
}, ...(ngDevMode ? [{ debugName: "hostClasses" }] : []));
|
|
1868
|
+
isCompact = computed(() => this.variant() === 'compact' || this.variant() === 'minimal', ...(ngDevMode ? [{ debugName: "isCompact" }] : []));
|
|
1869
|
+
constructor() {
|
|
1870
|
+
// Auto-scroll when new messages arrive
|
|
1871
|
+
effect(() => {
|
|
1872
|
+
const messages = this.messages();
|
|
1873
|
+
if (messages.length > 0 && this.shouldAutoScroll() && this.enableAutoScroll()) {
|
|
1874
|
+
setTimeout(() => this.scrollToBottom(), 0);
|
|
1875
|
+
}
|
|
1876
|
+
});
|
|
1877
|
+
}
|
|
1878
|
+
ngAfterViewInit() {
|
|
1879
|
+
this.scrollToBottom();
|
|
1880
|
+
}
|
|
1881
|
+
onScroll() {
|
|
1882
|
+
const container = this.messagesContainerRef()?.nativeElement;
|
|
1883
|
+
if (!container)
|
|
1884
|
+
return;
|
|
1885
|
+
const isAtBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 50;
|
|
1886
|
+
this.isScrolledUp.set(!isAtBottom);
|
|
1887
|
+
this.shouldAutoScroll.set(isAtBottom);
|
|
1888
|
+
}
|
|
1889
|
+
onMessageSubmit(event) {
|
|
1890
|
+
this.messageSubmit.emit(event);
|
|
1891
|
+
this.shouldAutoScroll.set(true);
|
|
1892
|
+
}
|
|
1893
|
+
scrollToBottom() {
|
|
1894
|
+
const container = this.messagesContainerRef()?.nativeElement;
|
|
1895
|
+
if (container) {
|
|
1896
|
+
container.scrollTop = container.scrollHeight;
|
|
1897
|
+
this.isScrolledUp.set(false);
|
|
1898
|
+
this.shouldAutoScroll.set(true);
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
onTyping(typing) {
|
|
1902
|
+
this.typing.emit(typing);
|
|
1903
|
+
}
|
|
1904
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ChatComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1905
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: ChatComponent, isStandalone: true, selector: "studio-chat", inputs: { messages: { classPropertyName: "messages", publicName: "messages", isSignal: true, isRequired: true, transformFunction: null }, currentUserId: { classPropertyName: "currentUserId", publicName: "currentUserId", isSignal: true, isRequired: true, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, showAvatars: { classPropertyName: "showAvatars", publicName: "showAvatars", isSignal: true, isRequired: false, transformFunction: null }, showTimestamps: { classPropertyName: "showTimestamps", publicName: "showTimestamps", isSignal: true, isRequired: false, transformFunction: null }, showUserNames: { classPropertyName: "showUserNames", publicName: "showUserNames", isSignal: true, isRequired: false, transformFunction: null }, enableAutoScroll: { classPropertyName: "enableAutoScroll", publicName: "enableAutoScroll", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { messageSubmit: "messageSubmit", typing: "typing" }, host: { properties: { "class": "hostClasses()", "style.height": "height()" } }, viewQueries: [{ propertyName: "messagesContainerRef", first: true, predicate: ["messagesContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class=\"chat__container\">\n <div\n #messagesContainer\n class=\"chat__messages\"\n (scroll)=\"onScroll()\"\n >\n @if (messages().length === 0) {\n <div class=\"chat__empty\">\n <studio-icon name=\"message-circle\" [size]=\"48\" />\n <p>No messages yet</p>\n <small>Start a conversation</small>\n </div>\n } @else {\n @for (message of messages(); track message.id || $index) {\n <studio-chat-message\n [message]=\"message\"\n [currentUserId]=\"currentUserId()\"\n [showAvatar]=\"showAvatars()\"\n [showTimestamp]=\"showTimestamps()\"\n [showUserName]=\"showUserNames()\"\n [compact]=\"isCompact()\"\n />\n }\n }\n </div>\n\n @if (isScrolledUp()) {\n <button\n class=\"chat__scroll-button\"\n (click)=\"scrollToBottom()\"\n type=\"button\"\n >\n <studio-icon name=\"arrow-down\" [size]=\"20\" />\n </button>\n }\n\n <studio-chat-input\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [compact]=\"isCompact()\"\n (messageSubmit)=\"onMessageSubmit($event)\"\n (typing)=\"onTyping($event)\"\n />\n</div>\n", styles: [":host{display:block;position:relative;background:var(--studio-bg-primary);border:1px solid var(--studio-border-primary);border-radius:var(--studio-radius-lg);overflow:hidden}.chat__container{display:flex;flex-direction:column;height:100%}.chat__messages{flex:1;overflow-y:auto;padding:1.5rem;display:flex;flex-direction:column;scroll-behavior:smooth}.chat__messages::-webkit-scrollbar{width:6px}.chat__messages::-webkit-scrollbar-track{background:var(--studio-bg-secondary)}.chat__messages::-webkit-scrollbar-thumb{background:var(--studio-border-primary);border-radius:var(--studio-radius-full)}.chat__messages::-webkit-scrollbar-thumb:hover{background:var(--studio-text-tertiary)}.chat__empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;color:var(--studio-text-secondary);padding:3rem 1.5rem}.chat__empty p{margin:0;font-size:1rem;font-weight:500}.chat__empty small{font-size:.875rem;color:var(--studio-text-tertiary)}.chat__scroll-button{position:absolute;bottom:100px;right:1.5rem;width:40px;height:40px;display:flex;align-items:center;justify-content:center;background:var(--studio-bg-primary);border:1px solid var(--studio-border-primary);border-radius:50%;box-shadow:0 2px 8px #0000001a;cursor:pointer;transition:all .15s ease;color:var(--studio-text-primary);z-index:10}.chat__scroll-button:hover{background:var(--studio-bg-hover);transform:scale(1.05)}.chat__scroll-button:active{transform:scale(.95)}:host(.studio-chat--compact) .chat__messages{padding:1rem}:host(.studio-chat--compact) .chat__scroll-button{bottom:80px}:host(.studio-chat--minimal){border:none;background:transparent}:host(.studio-chat--minimal) .chat__messages{padding:1rem}:host(.studio-chat--bubbles) .chat__messages{padding:1rem}:host(.studio-chat--sm) .chat__messages{padding:1rem;font-size:.875rem}:host(.studio-chat--sm) .chat__scroll-button{width:36px;height:36px;bottom:90px}:host(.studio-chat--lg) .chat__messages{padding:2rem;font-size:1rem}:host(.studio-chat--lg) .chat__scroll-button{width:44px;height:44px;bottom:110px}:host(.studio-chat--disabled){opacity:.6;pointer-events:none}@media (max-width: 640px){.chat__messages{padding:1rem}.chat__scroll-button{bottom:90px;right:1rem}}@media (prefers-reduced-motion: reduce){.chat__messages{scroll-behavior:auto}.chat__scroll-button{transition:none}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: ChatMessageComponent, selector: "studio-chat-message", inputs: ["message", "currentUserId", "showAvatar", "showTimestamp", "showUserName", "compact"] }, { kind: "component", type: ChatInputComponent, selector: "studio-chat-input", inputs: ["placeholder", "disabled", "compact"], outputs: ["messageSubmit", "typing"] }, { kind: "component", type: IconComponent, selector: "studio-icon", inputs: ["name", "size", "color", "strokeWidth", "absoluteStrokeWidth", "showFallback", "fallbackIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1906
|
+
}
|
|
1907
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: ChatComponent, decorators: [{
|
|
1908
|
+
type: Component,
|
|
1909
|
+
args: [{ selector: 'studio-chat', standalone: true, imports: [
|
|
1910
|
+
CommonModule,
|
|
1911
|
+
ChatMessageComponent,
|
|
1912
|
+
ChatInputComponent,
|
|
1913
|
+
IconComponent
|
|
1914
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
1915
|
+
'[class]': 'hostClasses()',
|
|
1916
|
+
'[style.height]': 'height()'
|
|
1917
|
+
}, template: "<div class=\"chat__container\">\n <div\n #messagesContainer\n class=\"chat__messages\"\n (scroll)=\"onScroll()\"\n >\n @if (messages().length === 0) {\n <div class=\"chat__empty\">\n <studio-icon name=\"message-circle\" [size]=\"48\" />\n <p>No messages yet</p>\n <small>Start a conversation</small>\n </div>\n } @else {\n @for (message of messages(); track message.id || $index) {\n <studio-chat-message\n [message]=\"message\"\n [currentUserId]=\"currentUserId()\"\n [showAvatar]=\"showAvatars()\"\n [showTimestamp]=\"showTimestamps()\"\n [showUserName]=\"showUserNames()\"\n [compact]=\"isCompact()\"\n />\n }\n }\n </div>\n\n @if (isScrolledUp()) {\n <button\n class=\"chat__scroll-button\"\n (click)=\"scrollToBottom()\"\n type=\"button\"\n >\n <studio-icon name=\"arrow-down\" [size]=\"20\" />\n </button>\n }\n\n <studio-chat-input\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled()\"\n [compact]=\"isCompact()\"\n (messageSubmit)=\"onMessageSubmit($event)\"\n (typing)=\"onTyping($event)\"\n />\n</div>\n", styles: [":host{display:block;position:relative;background:var(--studio-bg-primary);border:1px solid var(--studio-border-primary);border-radius:var(--studio-radius-lg);overflow:hidden}.chat__container{display:flex;flex-direction:column;height:100%}.chat__messages{flex:1;overflow-y:auto;padding:1.5rem;display:flex;flex-direction:column;scroll-behavior:smooth}.chat__messages::-webkit-scrollbar{width:6px}.chat__messages::-webkit-scrollbar-track{background:var(--studio-bg-secondary)}.chat__messages::-webkit-scrollbar-thumb{background:var(--studio-border-primary);border-radius:var(--studio-radius-full)}.chat__messages::-webkit-scrollbar-thumb:hover{background:var(--studio-text-tertiary)}.chat__empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.75rem;color:var(--studio-text-secondary);padding:3rem 1.5rem}.chat__empty p{margin:0;font-size:1rem;font-weight:500}.chat__empty small{font-size:.875rem;color:var(--studio-text-tertiary)}.chat__scroll-button{position:absolute;bottom:100px;right:1.5rem;width:40px;height:40px;display:flex;align-items:center;justify-content:center;background:var(--studio-bg-primary);border:1px solid var(--studio-border-primary);border-radius:50%;box-shadow:0 2px 8px #0000001a;cursor:pointer;transition:all .15s ease;color:var(--studio-text-primary);z-index:10}.chat__scroll-button:hover{background:var(--studio-bg-hover);transform:scale(1.05)}.chat__scroll-button:active{transform:scale(.95)}:host(.studio-chat--compact) .chat__messages{padding:1rem}:host(.studio-chat--compact) .chat__scroll-button{bottom:80px}:host(.studio-chat--minimal){border:none;background:transparent}:host(.studio-chat--minimal) .chat__messages{padding:1rem}:host(.studio-chat--bubbles) .chat__messages{padding:1rem}:host(.studio-chat--sm) .chat__messages{padding:1rem;font-size:.875rem}:host(.studio-chat--sm) .chat__scroll-button{width:36px;height:36px;bottom:90px}:host(.studio-chat--lg) .chat__messages{padding:2rem;font-size:1rem}:host(.studio-chat--lg) .chat__scroll-button{width:44px;height:44px;bottom:110px}:host(.studio-chat--disabled){opacity:.6;pointer-events:none}@media (max-width: 640px){.chat__messages{padding:1rem}.chat__scroll-button{bottom:90px;right:1rem}}@media (prefers-reduced-motion: reduce){.chat__messages{scroll-behavior:auto}.chat__scroll-button{transition:none}}\n"] }]
|
|
1918
|
+
}], ctorParameters: () => [], propDecorators: { messages: [{ type: i0.Input, args: [{ isSignal: true, alias: "messages", required: true }] }], currentUserId: [{ type: i0.Input, args: [{ isSignal: true, alias: "currentUserId", required: true }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], height: [{ type: i0.Input, args: [{ isSignal: true, alias: "height", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], showAvatars: [{ type: i0.Input, args: [{ isSignal: true, alias: "showAvatars", required: false }] }], showTimestamps: [{ type: i0.Input, args: [{ isSignal: true, alias: "showTimestamps", required: false }] }], showUserNames: [{ type: i0.Input, args: [{ isSignal: true, alias: "showUserNames", required: false }] }], enableAutoScroll: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableAutoScroll", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], messageSubmit: [{ type: i0.Output, args: ["messageSubmit"] }], typing: [{ type: i0.Output, args: ["typing"] }], messagesContainerRef: [{ type: i0.ViewChild, args: ['messagesContainer', { isSignal: true }] }] } });
|
|
1919
|
+
|
|
1270
1920
|
/**
|
|
1271
1921
|
* Checkbox component for selecting boolean values
|
|
1272
1922
|
*
|
|
@@ -5775,5 +6425,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImpo
|
|
|
5775
6425
|
* Generated bundle index. Do not edit.
|
|
5776
6426
|
*/
|
|
5777
6427
|
|
|
5778
|
-
export { BadgeComponent, BadgeWrapperComponent, BottomNavigationComponent, ButtonComponent, ButtonGroupComponent, ButtonToggleGroupComponent, CheckboxComponent, ColorPickerCompactComponent, ColorPickerComponent, DEFAULT_COLOR_PRESETS, DrawerComponent, DrawerService, DropdownComponent, IconComponent, InputComponent, InspectorComponent, MASK_PRESETS, MaskDirective, MaskEngine, MenuComponent, ModalComponent, NavbarComponent, PopoverComponent, RadioButtonComponent, STUDIO_CONFIG, SelectComponent, SidebarComponent, StudioConfigService, SwitchComponent, TabsComponent, TextareaComponent, ThemeSwitchComponent, TooltipComponent, classNames, isSafeUrl, loadGoogleFont, loadGoogleFonts, provideStudioConfig, provideStudioIcons, sanitizeUrl, withConfigDefault };
|
|
6428
|
+
export { BadgeComponent, BadgeWrapperComponent, BottomNavigationComponent, ButtonComponent, ButtonGroupComponent, ButtonToggleGroupComponent, CardComponent, ChatComponent, ChatInputComponent, ChatMessageComponent, CheckboxComponent, ColorPickerCompactComponent, ColorPickerComponent, DEFAULT_COLOR_PRESETS, DrawerComponent, DrawerService, DropdownComponent, IconComponent, InputComponent, InspectorComponent, MASK_PRESETS, MaskDirective, MaskEngine, MenuComponent, ModalComponent, NavbarComponent, PopoverComponent, RadioButtonComponent, STUDIO_CONFIG, SelectComponent, SidebarComponent, StudioConfigService, SwitchComponent, TabsComponent, TextareaComponent, ThemeSwitchComponent, TooltipComponent, classNames, isSafeUrl, loadGoogleFont, loadGoogleFonts, provideStudioConfig, provideStudioIcons, sanitizeUrl, withConfigDefault };
|
|
5779
6429
|
//# sourceMappingURL=eduboxpro-studio.mjs.map
|