@brickclay-org/ui 0.0.49 → 0.0.51
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/README.md +1911 -1911
- package/fesm2022/brickclay-org-ui.mjs +283 -58
- package/fesm2022/brickclay-org-ui.mjs.map +1 -1
- package/index.d.ts +125 -58
- package/package.json +1 -1
- package/src/lib/avatar-profile/avatar-profile.css +80 -0
- package/src/styles.css +1 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Component, EventEmitter, HostListener, ViewChildren, Output, Input, Injectable, NgModule, forwardRef, ViewEncapsulation, Optional, Self, Directive, ViewChild, input, model, output, signal, computed, effect, inject, ElementRef, InjectionToken } from '@angular/core';
|
|
3
3
|
import * as i1 from '@angular/common';
|
|
4
|
-
import { CommonModule } from '@angular/common';
|
|
4
|
+
import { CommonModule, NgClass } from '@angular/common';
|
|
5
5
|
import * as i1$1 from '@angular/forms';
|
|
6
6
|
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
7
7
|
import moment from 'moment';
|
|
@@ -11,7 +11,7 @@ import { moveItemInArray, DragDropModule } from '@angular/cdk/drag-drop';
|
|
|
11
11
|
import * as i1$2 from '@angular/cdk/scrolling';
|
|
12
12
|
import { ScrollingModule, CdkScrollable } from '@angular/cdk/scrolling';
|
|
13
13
|
import { NgxMaskDirective, provideNgxMask } from 'ngx-mask';
|
|
14
|
-
import { DIALOG_DATA
|
|
14
|
+
import { DIALOG_DATA, CdkDialogContainer, Dialog, DialogModule } from '@angular/cdk/dialog';
|
|
15
15
|
import { Overlay, OverlayModule } from '@angular/cdk/overlay';
|
|
16
16
|
import { CdkPortalOutlet, PortalModule } from '@angular/cdk/portal';
|
|
17
17
|
|
|
@@ -4336,8 +4336,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4336
4336
|
* as before.
|
|
4337
4337
|
*
|
|
4338
4338
|
* • `INTERNAL_DIALOG_CONFIG` — Internal-only token used to pass our
|
|
4339
|
-
* full `
|
|
4340
|
-
* `
|
|
4339
|
+
* full `BkDialogConfig` (including animation fields) to the custom
|
|
4340
|
+
* `BkDialogContainerComponent`. Not part of the public API.
|
|
4341
4341
|
*/
|
|
4342
4342
|
// ──── Public ─────────────────────────────────────────────────────────────
|
|
4343
4343
|
/**
|
|
@@ -4349,10 +4349,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4349
4349
|
*
|
|
4350
4350
|
* Usage inside a dialog component:
|
|
4351
4351
|
* ```ts
|
|
4352
|
-
* constructor(@Inject(
|
|
4352
|
+
* constructor(@Inject(BK_DIALOG_DATA) public data: MyDataType) {}
|
|
4353
4353
|
* ```
|
|
4354
4354
|
*/
|
|
4355
|
-
const
|
|
4355
|
+
const BK_DIALOG_DATA = DIALOG_DATA;
|
|
4356
4356
|
/**
|
|
4357
4357
|
* Optional token for providing global dialog defaults at the
|
|
4358
4358
|
* application level.
|
|
@@ -4360,19 +4360,19 @@ const DIALOG_DATA = DIALOG_DATA$1;
|
|
|
4360
4360
|
* Usage in `app.config.ts` or a module's `providers` array:
|
|
4361
4361
|
* ```ts
|
|
4362
4362
|
* providers: [
|
|
4363
|
-
* { provide:
|
|
4363
|
+
* { provide: BK_DIALOG_GLOBAL_CONFIG, useValue: { animation: 'zoom', width: '600px' } }
|
|
4364
4364
|
* ]
|
|
4365
4365
|
* ```
|
|
4366
4366
|
*/
|
|
4367
|
-
const
|
|
4367
|
+
const BK_DIALOG_GLOBAL_CONFIG = new InjectionToken('BK_DIALOG_GLOBAL_CONFIG');
|
|
4368
4368
|
// ──── Internal ───────────────────────────────────────────────────────────
|
|
4369
4369
|
/**
|
|
4370
|
-
* Internal token that carries our full `
|
|
4371
|
-
* settings, position offsets, etc.) into the `
|
|
4370
|
+
* Internal token that carries our full `BkDialogConfig` (with animation
|
|
4371
|
+
* settings, position offsets, etc.) into the `BkDialogContainerComponent`.
|
|
4372
4372
|
*
|
|
4373
4373
|
* @internal — not exported from the barrel; do not depend on it.
|
|
4374
4374
|
*/
|
|
4375
|
-
const
|
|
4375
|
+
const BK_INTERNAL_DIALOG_CONFIG = new InjectionToken('BK_INTERNAL_DIALOG_CONFIG');
|
|
4376
4376
|
|
|
4377
4377
|
/**
|
|
4378
4378
|
* Dialog Animations
|
|
@@ -4387,7 +4387,7 @@ const INTERNAL_DIALOG_CONFIG = new InjectionToken('INTERNAL_DIALOG_CONFIG');
|
|
|
4387
4387
|
* 3. Future presets can be added without touching the component template.
|
|
4388
4388
|
*
|
|
4389
4389
|
* Each preset exports an `enter` and `leave` keyframe array plus a
|
|
4390
|
-
* recommended timing object. The
|
|
4390
|
+
* recommended timing object. The BkDialogContainerComponent plays these
|
|
4391
4391
|
* via `element.animate()`.
|
|
4392
4392
|
*/
|
|
4393
4393
|
/**
|
|
@@ -4539,7 +4539,7 @@ function getDialogBackdropAnimation(enterDuration, leaveDuration) {
|
|
|
4539
4539
|
}
|
|
4540
4540
|
|
|
4541
4541
|
/**
|
|
4542
|
-
*
|
|
4542
|
+
* BkDialogContainerComponent
|
|
4543
4543
|
*
|
|
4544
4544
|
* Architecture Decision:
|
|
4545
4545
|
* ─────────────────────
|
|
@@ -4559,19 +4559,19 @@ function getDialogBackdropAnimation(enterDuration, leaveDuration) {
|
|
|
4559
4559
|
* • Position-offset application via CSS margin.
|
|
4560
4560
|
*
|
|
4561
4561
|
* This component is **never** used directly — it is created internally
|
|
4562
|
-
* by `
|
|
4562
|
+
* by `BkDialogService` via CDK's `Dialog.open()`.
|
|
4563
4563
|
*/
|
|
4564
|
-
class
|
|
4564
|
+
class BkDialogContainerComponent extends CdkDialogContainer {
|
|
4565
4565
|
/**
|
|
4566
4566
|
* Our full config (including animation fields).
|
|
4567
|
-
* Provided by
|
|
4567
|
+
* Provided by BkDialogService via the INTERNAL_DIALOG_CONFIG token.
|
|
4568
4568
|
*/
|
|
4569
|
-
_dialogConfig = inject(
|
|
4569
|
+
_dialogConfig = inject(BK_INTERNAL_DIALOG_CONFIG);
|
|
4570
4570
|
// ──── Opened promise ─────────────────────────────────────────────────
|
|
4571
4571
|
/**
|
|
4572
4572
|
* Resolves when the enter animation finishes (or immediately for 'none').
|
|
4573
|
-
* `
|
|
4574
|
-
* `
|
|
4573
|
+
* `BkDialogService` subscribes via `.then()` to emit `afterOpened` on the
|
|
4574
|
+
* `BkDialogRef`.
|
|
4575
4575
|
*/
|
|
4576
4576
|
_resolveOpened;
|
|
4577
4577
|
opened = new Promise(resolve => {
|
|
@@ -4629,7 +4629,7 @@ class DialogContainerComponent extends CdkDialogContainer {
|
|
|
4629
4629
|
}
|
|
4630
4630
|
/**
|
|
4631
4631
|
* Play the leave animation. Returns a Promise that resolves when done.
|
|
4632
|
-
* Called by `
|
|
4632
|
+
* Called by `BkDialogRef._runCloseSequence()` before CDK tears down the
|
|
4633
4633
|
* overlay.
|
|
4634
4634
|
*/
|
|
4635
4635
|
playLeaveAnimation() {
|
|
@@ -4681,10 +4681,10 @@ class DialogContainerComponent extends CdkDialogContainer {
|
|
|
4681
4681
|
const pane = this._elementRef.nativeElement.closest('.cdk-overlay-pane');
|
|
4682
4682
|
return pane?.parentElement?.querySelector('.cdk-overlay-backdrop') ?? null;
|
|
4683
4683
|
}
|
|
4684
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
4685
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type:
|
|
4684
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkDialogContainerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
4685
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.16", type: BkDialogContainerComponent, isStandalone: true, selector: "bk-dialog-container", host: { classAttribute: "bk-dialog-container" }, usesInheritance: true, ngImport: i0, template: "<!--\r\n Dialog Container Template (CDK-based)\r\n\r\n Architecture:\r\n \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n CDK Overlay manages the full overlay stack:\r\n\r\n \u250C\u2500 .cdk-overlay-container (fixed, z-index managed by CDK) \u2500\u2500\u2500\u2500\u2500\u2500\u2510\r\n \u2502 \u250C\u2500 .cdk-global-overlay-wrapper (flex-center) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502\r\n \u2502 \u2502 .cdk-overlay-backdrop (click \u2192 close, CDK transition) \u2502 \u2502\r\n \u2502 \u2502 \u250C\u2500 .cdk-overlay-pane (width/height from config) \u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u2502 \u2502\r\n \u2502 \u2502 \u2502 <bk-dialog-container> \u2190 this component (panel) \u2502 \u2502 \u2502\r\n \u2502 \u2502 \u2502 <ng-template cdkPortalOutlet /> \u2190 user component \u2502 \u2502 \u2502\r\n \u2502 \u2502 \u2502 <UserDialogComponent> \u2502 \u2502 \u2502\r\n \u2502 \u2502 \u2502 <h2 bk-dialog-title>Title</h2> \u2502 \u2502 \u2502\r\n \u2502 \u2502 \u2502 <div bk-dialog-content>Scrollable body</div> \u2502 \u2502 \u2502\r\n \u2502 \u2502 \u2502 <div bk-dialog-actions>Pinned buttons</div> \u2502 \u2502 \u2502\r\n \u2502 \u2502 \u2502 </UserDialogComponent> \u2502 \u2502 \u2502\r\n \u2502 \u2502 \u2502 </bk-dialog-container> \u2502 \u2502 \u2502\r\n \u2502 \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502 \u2502\r\n \u2502 \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2502\r\n \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\r\n\r\n The host element IS the visible panel (background, radius, shadow).\r\n CDK Portal projects the caller's component as a direct child.\r\n\r\n Directives (BkDialogTitle, BkDialogContent, BkDialogActions, BkDialogClose)\r\n apply the corresponding CSS classes and add accessibility features.\r\n-->\r\n\r\n<ng-template cdkPortalOutlet />\r\n", styles: [":host{display:flex;flex-direction:column;flex:1;min-height:0;max-height:inherit;background:var(--bk-dialog-panel-bg, #ffffff);border-radius:var(--bk-dialog-panel-radius, 8px);box-shadow:var( --bk-dialog-panel-shadow, 0 11px 15px -7px rgba(0, 0, 0, .2), 0 24px 38px 3px rgba(0, 0, 0, .14), 0 9px 46px 8px rgba(0, 0, 0, .12) );outline:0;box-sizing:border-box;overflow:hidden;will-change:transform,opacity}:host ::ng-deep>:first-child{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden}:host ::ng-deep .bk-dialog-content{flex:1 1 auto;overflow:auto;min-height:0;display:block;-webkit-overflow-scrolling:touch}:host ::ng-deep .bk-dialog-actions{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-end;flex-wrap:wrap;min-height:52px}:host ::ng-deep .bk-dialog-title{flex:0 0 auto;margin:0}:host ::ng-deep .bk-dialog-actions-align-start{justify-content:flex-start}:host ::ng-deep .bk-dialog-actions-align-center{justify-content:center}\n"], dependencies: [{ kind: "directive", type: CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }] });
|
|
4686
4686
|
}
|
|
4687
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
4687
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkDialogContainerComponent, decorators: [{
|
|
4688
4688
|
type: Component,
|
|
4689
4689
|
args: [{ selector: 'bk-dialog-container', standalone: true, imports: [CdkPortalOutlet], host: {
|
|
4690
4690
|
'class': 'bk-dialog-container',
|
|
@@ -4692,7 +4692,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4692
4692
|
}] });
|
|
4693
4693
|
|
|
4694
4694
|
/**
|
|
4695
|
-
*
|
|
4695
|
+
* BkDialogRef — Handle returned to callers by `BkDialogService.open()`.
|
|
4696
4696
|
*
|
|
4697
4697
|
* Architecture Decision:
|
|
4698
4698
|
* ─────────────────────
|
|
@@ -4707,13 +4707,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
4707
4707
|
* Ours keeps `<T, R>` (Component first, Result second) to match the
|
|
4708
4708
|
* convention consumers already use.
|
|
4709
4709
|
*/
|
|
4710
|
-
class
|
|
4710
|
+
class BkDialogRef {
|
|
4711
4711
|
_cdkRef;
|
|
4712
4712
|
/** Unique dialog identifier (managed by CDK). */
|
|
4713
4713
|
id;
|
|
4714
4714
|
/** Instance of the component rendered inside the dialog. */
|
|
4715
4715
|
componentInstance;
|
|
4716
|
-
// ──── Internal wiring (set by
|
|
4716
|
+
// ──── Internal wiring (set by BkDialogService) ──────────────────────────
|
|
4717
4717
|
/** @internal Container reference for leave animation. */
|
|
4718
4718
|
_containerInstance;
|
|
4719
4719
|
/** @internal Prevent double-close. */
|
|
@@ -4791,14 +4791,14 @@ class DialogRef {
|
|
|
4791
4791
|
*
|
|
4792
4792
|
* Architecture Decision:
|
|
4793
4793
|
* ─────────────────────
|
|
4794
|
-
* Our `
|
|
4794
|
+
* Our `BkDialogConfig` mirrors the fields from CDK's `DialogConfig` that we
|
|
4795
4795
|
* expose, plus adds custom animation properties powered by WAAPI.
|
|
4796
4796
|
*
|
|
4797
|
-
* When `
|
|
4797
|
+
* When `BkDialogService.open()` is called these values are:
|
|
4798
4798
|
* 1. Merged with global defaults and per-call overrides.
|
|
4799
4799
|
* 2. Mapped onto CDK's native `DialogConfig` for overlay, backdrop, scroll,
|
|
4800
4800
|
* position, ARIA, and focus-trap management.
|
|
4801
|
-
* 3. Passed to `
|
|
4801
|
+
* 3. Passed to `BkDialogContainerComponent` via an internal token for
|
|
4802
4802
|
* animation playback and position offsets.
|
|
4803
4803
|
*
|
|
4804
4804
|
* CDK handles: unique IDs, z-index stacking, scroll blocking, focus trap,
|
|
@@ -4806,7 +4806,7 @@ class DialogRef {
|
|
|
4806
4806
|
* We handle: WAAPI animations, panel appearance, convenience config sugar.
|
|
4807
4807
|
*/
|
|
4808
4808
|
// ──── Defaults ───────────────────────────────────────────────────────────
|
|
4809
|
-
const
|
|
4809
|
+
const BK_DEFAULT_DIALOG_CONFIG = {
|
|
4810
4810
|
id: undefined,
|
|
4811
4811
|
width: undefined,
|
|
4812
4812
|
height: undefined,
|
|
@@ -4836,7 +4836,7 @@ const DEFAULT_DIALOG_CONFIG = {
|
|
|
4836
4836
|
};
|
|
4837
4837
|
|
|
4838
4838
|
/**
|
|
4839
|
-
*
|
|
4839
|
+
* BkDialogService — The core engine of the custom dialog system.
|
|
4840
4840
|
*
|
|
4841
4841
|
* Architecture Decision:
|
|
4842
4842
|
* ─────────────────────
|
|
@@ -4847,10 +4847,10 @@ const DEFAULT_DIALOG_CONFIG = {
|
|
|
4847
4847
|
* z-index stacking, and unique ID management — battle-tested infra
|
|
4848
4848
|
* shared with every Angular Material dialog in the ecosystem.
|
|
4849
4849
|
*
|
|
4850
|
-
* 2. We provide our own `
|
|
4850
|
+
* 2. We provide our own `BkDialogContainerComponent` (extending
|
|
4851
4851
|
* `CdkDialogContainer`) for WAAPI animations and panel styling.
|
|
4852
4852
|
*
|
|
4853
|
-
* 3. We wrap CDK's `DialogRef` in our own `
|
|
4853
|
+
* 3. We wrap CDK's `DialogRef` in our own `BkDialogRef` to add the
|
|
4854
4854
|
* leave-animation step before CDK tears down the overlay, and to
|
|
4855
4855
|
* expose the same familiar API shape (`afterClosed()`, etc.).
|
|
4856
4856
|
*
|
|
@@ -4873,13 +4873,13 @@ const DEFAULT_DIALOG_CONFIG = {
|
|
|
4873
4873
|
* ─────────────
|
|
4874
4874
|
* CDK manages the full lifecycle: on close it detaches the overlay,
|
|
4875
4875
|
* destroys the container, and disposes the overlay ref.
|
|
4876
|
-
* Our
|
|
4876
|
+
* Our BkDialogRef subjects complete via CDK's `closed` observable,
|
|
4877
4877
|
* preventing lingering subscriptions.
|
|
4878
4878
|
*/
|
|
4879
|
-
class
|
|
4879
|
+
class BkDialogService {
|
|
4880
4880
|
_cdkDialog = inject(Dialog);
|
|
4881
4881
|
_overlay = inject(Overlay);
|
|
4882
|
-
_globalConfig = inject(
|
|
4882
|
+
_globalConfig = inject(BK_DIALOG_GLOBAL_CONFIG, { optional: true });
|
|
4883
4883
|
/** Stack of currently open dialog refs (most recent = last). */
|
|
4884
4884
|
_openDialogRefs = [];
|
|
4885
4885
|
// ════════════════════════════════════════════════════════════════════
|
|
@@ -4891,7 +4891,7 @@ class DialogService {
|
|
|
4891
4891
|
* @param component The component class to render inside the dialog.
|
|
4892
4892
|
* @param config Optional per-dialog configuration (merged on top
|
|
4893
4893
|
* of global and default settings).
|
|
4894
|
-
* @returns A strongly-typed `
|
|
4894
|
+
* @returns A strongly-typed `BkDialogRef` to interact with.
|
|
4895
4895
|
*
|
|
4896
4896
|
* @example
|
|
4897
4897
|
* ```ts
|
|
@@ -4905,7 +4905,7 @@ class DialogService {
|
|
|
4905
4905
|
open(component, config) {
|
|
4906
4906
|
// ── 1. Merge configs: DEFAULT ← GLOBAL ← per-call ──────────────
|
|
4907
4907
|
const mergedConfig = {
|
|
4908
|
-
...
|
|
4908
|
+
...BK_DEFAULT_DIALOG_CONFIG,
|
|
4909
4909
|
...(this._globalConfig ?? {}),
|
|
4910
4910
|
...(config ?? {}),
|
|
4911
4911
|
};
|
|
@@ -4947,23 +4947,23 @@ class DialogService {
|
|
|
4947
4947
|
positionStrategy: this._buildPositionStrategy(mergedConfig),
|
|
4948
4948
|
// ── Custom container ──────────────────────────────────────────
|
|
4949
4949
|
container: {
|
|
4950
|
-
type:
|
|
4950
|
+
type: BkDialogContainerComponent,
|
|
4951
4951
|
providers: () => [
|
|
4952
|
-
{ provide:
|
|
4952
|
+
{ provide: BK_INTERNAL_DIALOG_CONFIG, useValue: mergedConfig },
|
|
4953
4953
|
],
|
|
4954
4954
|
},
|
|
4955
4955
|
// ── Provider callback ─────────────────────────────────────────
|
|
4956
4956
|
// Runs after the container is created but before the user
|
|
4957
|
-
// component. We create our `
|
|
4957
|
+
// component. We create our `BkDialogRef` wrapper here and make
|
|
4958
4958
|
// it available for injection in the user component.
|
|
4959
4959
|
providers: (cdkRef, _cdkConfig, containerInstance) => {
|
|
4960
|
-
ourRef = new
|
|
4960
|
+
ourRef = new BkDialogRef(cdkRef);
|
|
4961
4961
|
ourRef._containerInstance = containerInstance;
|
|
4962
4962
|
// Wire up afterOpened emission.
|
|
4963
4963
|
containerInstance.opened
|
|
4964
4964
|
.then(() => ourRef._emitOpened());
|
|
4965
4965
|
return [
|
|
4966
|
-
{ provide:
|
|
4966
|
+
{ provide: BkDialogRef, useValue: ourRef },
|
|
4967
4967
|
];
|
|
4968
4968
|
},
|
|
4969
4969
|
};
|
|
@@ -4992,7 +4992,7 @@ class DialogService {
|
|
|
4992
4992
|
}
|
|
4993
4993
|
}
|
|
4994
4994
|
/**
|
|
4995
|
-
* Returns the `
|
|
4995
|
+
* Returns the `BkDialogRef` of the most recently opened dialog,
|
|
4996
4996
|
* or `undefined` if none are open.
|
|
4997
4997
|
*/
|
|
4998
4998
|
getTopDialog() {
|
|
@@ -5013,7 +5013,7 @@ class DialogService {
|
|
|
5013
5013
|
/**
|
|
5014
5014
|
* Read-only snapshot of currently open dialog refs.
|
|
5015
5015
|
* Used internally by content directives (`BkDialogTitle`, `BkDialogActions`,
|
|
5016
|
-
* `BkDialogClose`) for the DOM-walk fallback when `
|
|
5016
|
+
* `BkDialogClose`) for the DOM-walk fallback when `BkDialogRef` is not
|
|
5017
5017
|
* available via injection (e.g. inside `<ng-template>`).
|
|
5018
5018
|
*/
|
|
5019
5019
|
get openDialogsRef() {
|
|
@@ -5135,10 +5135,10 @@ class DialogService {
|
|
|
5135
5135
|
}
|
|
5136
5136
|
return strategy;
|
|
5137
5137
|
}
|
|
5138
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
5139
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
5138
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
5139
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkDialogService, providedIn: 'root' });
|
|
5140
5140
|
}
|
|
5141
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type:
|
|
5141
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: BkDialogService, decorators: [{
|
|
5142
5142
|
type: Injectable,
|
|
5143
5143
|
args: [{ providedIn: 'root' }]
|
|
5144
5144
|
}] });
|
|
@@ -5172,7 +5172,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
5172
5172
|
let nextTitleId = 0;
|
|
5173
5173
|
// ──── Helper ─────────────────────────────────────────────────────────────
|
|
5174
5174
|
/**
|
|
5175
|
-
* Finds the closest `
|
|
5175
|
+
* Finds the closest `BkDialogRef` by walking up the DOM from the given
|
|
5176
5176
|
* element to the nearest `bk-dialog-container` host, then matching its
|
|
5177
5177
|
* `id` attribute against the currently open dialogs.
|
|
5178
5178
|
*
|
|
@@ -5193,15 +5193,15 @@ function getClosestDialog(element, openDialogs) {
|
|
|
5193
5193
|
}
|
|
5194
5194
|
// ──── Base for Title / Actions ───────────────────────────────────────────
|
|
5195
5195
|
/**
|
|
5196
|
-
* Shared abstract base that resolves the owning `
|
|
5196
|
+
* Shared abstract base that resolves the owning `BkDialogRef` (via DI or
|
|
5197
5197
|
* DOM walk) and invokes `_onAdd()` / `_onRemove()` lifecycle hooks.
|
|
5198
5198
|
*
|
|
5199
5199
|
* Same pattern as Material's internal `MatDialogLayoutSection`.
|
|
5200
5200
|
*/
|
|
5201
5201
|
class BkDialogLayoutSection {
|
|
5202
|
-
_dialogRef = inject(
|
|
5202
|
+
_dialogRef = inject(BkDialogRef, { optional: true });
|
|
5203
5203
|
_elementRef = inject((ElementRef));
|
|
5204
|
-
_dialogService = inject(
|
|
5204
|
+
_dialogService = inject(BkDialogService);
|
|
5205
5205
|
ngOnInit() {
|
|
5206
5206
|
if (!this._dialogRef) {
|
|
5207
5207
|
this._dialogRef = getClosestDialog(this._elementRef, this._dialogService.openDialogsRef);
|
|
@@ -5375,9 +5375,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
5375
5375
|
* ```
|
|
5376
5376
|
*/
|
|
5377
5377
|
class BkDialogClose {
|
|
5378
|
-
_dialogRef = inject(
|
|
5378
|
+
_dialogRef = inject(BkDialogRef, { optional: true });
|
|
5379
5379
|
_elementRef = inject((ElementRef));
|
|
5380
|
-
_dialogService = inject(
|
|
5380
|
+
_dialogService = inject(BkDialogService);
|
|
5381
5381
|
/** Screen-reader label for the button. */
|
|
5382
5382
|
ariaLabel;
|
|
5383
5383
|
/** Prevents accidental form submits. Default: `'button'`. */
|
|
@@ -5440,7 +5440,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
5440
5440
|
*
|
|
5441
5441
|
* • All components/directives are **standalone**.
|
|
5442
5442
|
* • This module simply imports + re-exports them for convenience.
|
|
5443
|
-
* • `
|
|
5443
|
+
* • `BkDialogService` is `providedIn: 'root'`, so it does NOT need to
|
|
5444
5444
|
* be listed in `providers` here — it is tree-shakeable and available
|
|
5445
5445
|
* app-wide automatically.
|
|
5446
5446
|
*
|
|
@@ -5473,7 +5473,7 @@ class BkDialogModule {
|
|
|
5473
5473
|
OverlayModule,
|
|
5474
5474
|
PortalModule,
|
|
5475
5475
|
// ── Our standalone pieces ───────────────────────────────────────
|
|
5476
|
-
|
|
5476
|
+
BkDialogContainerComponent,
|
|
5477
5477
|
BkDialogTitle,
|
|
5478
5478
|
BkDialogContent,
|
|
5479
5479
|
BkDialogActions,
|
|
@@ -5500,7 +5500,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
5500
5500
|
OverlayModule,
|
|
5501
5501
|
PortalModule,
|
|
5502
5502
|
// ── Our standalone pieces ───────────────────────────────────────
|
|
5503
|
-
|
|
5503
|
+
BkDialogContainerComponent,
|
|
5504
5504
|
BkDialogTitle,
|
|
5505
5505
|
BkDialogContent,
|
|
5506
5506
|
BkDialogActions,
|
|
@@ -5543,6 +5543,231 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
5543
5543
|
type: Input
|
|
5544
5544
|
}] } });
|
|
5545
5545
|
|
|
5546
|
+
class AvatarProfile {
|
|
5547
|
+
// ---------- Display inputs ----------
|
|
5548
|
+
src = null;
|
|
5549
|
+
alt = 'Avatar';
|
|
5550
|
+
name = '';
|
|
5551
|
+
size = 'md';
|
|
5552
|
+
fallback = 'auto';
|
|
5553
|
+
// ---------- Functional inputs ----------
|
|
5554
|
+
/** Whether upload / remove actions are enabled */
|
|
5555
|
+
editable = true;
|
|
5556
|
+
/** Accepted file MIME types for the file picker */
|
|
5557
|
+
accept = 'image/jpeg, image/png';
|
|
5558
|
+
/** Max file size in KB (0 = no limit) */
|
|
5559
|
+
maxFileSizeKB = 0;
|
|
5560
|
+
/** Label shown on the upload button */
|
|
5561
|
+
uploadLabel = 'Upload';
|
|
5562
|
+
/** Hint text shown below the upload button */
|
|
5563
|
+
hint = '500x500 JPEG, PNG Image';
|
|
5564
|
+
/** External loading state (e.g. while uploading) */
|
|
5565
|
+
loading = false;
|
|
5566
|
+
/** Whether the remove badge is shown when an image is present */
|
|
5567
|
+
removable = false;
|
|
5568
|
+
// ---------- Form / CVA inputs ----------
|
|
5569
|
+
/** Label displayed above the avatar */
|
|
5570
|
+
label = '';
|
|
5571
|
+
/** Whether the field is required (shows asterisk) */
|
|
5572
|
+
required = false;
|
|
5573
|
+
/** External error state flag */
|
|
5574
|
+
hasError = false;
|
|
5575
|
+
/** Error message to display when hasError is true */
|
|
5576
|
+
errorMessage = '';
|
|
5577
|
+
/** Disabled state (also set via CVA setDisabledState) */
|
|
5578
|
+
disabled = false;
|
|
5579
|
+
// ---------- Outputs ----------
|
|
5580
|
+
/** Emits the selected File after validation passes */
|
|
5581
|
+
fileSelected = new EventEmitter();
|
|
5582
|
+
/** Emits when the user clicks the remove badge */
|
|
5583
|
+
removed = new EventEmitter();
|
|
5584
|
+
/** Emits a human-readable error string on validation failure */
|
|
5585
|
+
fileError = new EventEmitter();
|
|
5586
|
+
initials = '';
|
|
5587
|
+
imageLoadFailed = false;
|
|
5588
|
+
/** Local blob URL for instant preview before server upload completes */
|
|
5589
|
+
previewUrl = null;
|
|
5590
|
+
// ---------- CVA Callbacks ----------
|
|
5591
|
+
onChange = (_value) => { };
|
|
5592
|
+
onTouched = () => { };
|
|
5593
|
+
writeValue(value) {
|
|
5594
|
+
this.src = value || null;
|
|
5595
|
+
// When a new value arrives from the form (e.g. server URL after upload),
|
|
5596
|
+
// discard any stale local blob preview so displaySrc uses the real URL
|
|
5597
|
+
this.revokePreview();
|
|
5598
|
+
this.imageLoadFailed = false;
|
|
5599
|
+
}
|
|
5600
|
+
registerOnChange(fn) {
|
|
5601
|
+
this.onChange = fn;
|
|
5602
|
+
}
|
|
5603
|
+
registerOnTouched(fn) {
|
|
5604
|
+
this.onTouched = fn;
|
|
5605
|
+
}
|
|
5606
|
+
setDisabledState(isDisabled) {
|
|
5607
|
+
this.disabled = isDisabled;
|
|
5608
|
+
this.editable = !isDisabled;
|
|
5609
|
+
}
|
|
5610
|
+
// ---------- Lifecycle ----------
|
|
5611
|
+
ngOnChanges(changes) {
|
|
5612
|
+
if (this.name) {
|
|
5613
|
+
this.initials = this.getInitials(this.name);
|
|
5614
|
+
}
|
|
5615
|
+
this.imageLoadFailed = false;
|
|
5616
|
+
// When the parent updates [src] via @Input (non-CVA usage), discard the local preview
|
|
5617
|
+
if (changes['src'] && this.previewUrl) {
|
|
5618
|
+
this.revokePreview();
|
|
5619
|
+
}
|
|
5620
|
+
}
|
|
5621
|
+
ngOnDestroy() {
|
|
5622
|
+
this.revokePreview();
|
|
5623
|
+
}
|
|
5624
|
+
onImageError() {
|
|
5625
|
+
this.imageLoadFailed = true;
|
|
5626
|
+
}
|
|
5627
|
+
// ---------- Derived UI ----------
|
|
5628
|
+
/** The URL the template should display — local preview takes priority over the server src */
|
|
5629
|
+
get displaySrc() {
|
|
5630
|
+
return this.previewUrl ?? this.src;
|
|
5631
|
+
}
|
|
5632
|
+
get showInitials() {
|
|
5633
|
+
if (!this.name)
|
|
5634
|
+
return false;
|
|
5635
|
+
if (this.fallback === 'icon')
|
|
5636
|
+
return false;
|
|
5637
|
+
if (this.fallback === 'camera')
|
|
5638
|
+
return false;
|
|
5639
|
+
if (this.fallback === 'initials')
|
|
5640
|
+
return true;
|
|
5641
|
+
return true; // auto
|
|
5642
|
+
}
|
|
5643
|
+
get containerClasses() {
|
|
5644
|
+
return ['avatar-profile', this.size].join(' ');
|
|
5645
|
+
}
|
|
5646
|
+
get sizeClasses() {
|
|
5647
|
+
return [this.size];
|
|
5648
|
+
}
|
|
5649
|
+
get showRemoveButton() {
|
|
5650
|
+
return this.removable && this.editable && !!(this.displaySrc) && !this.imageLoadFailed;
|
|
5651
|
+
}
|
|
5652
|
+
// ---------- File handling ----------
|
|
5653
|
+
onFileSelected(event) {
|
|
5654
|
+
const input = event.target;
|
|
5655
|
+
if (!input.files?.length)
|
|
5656
|
+
return;
|
|
5657
|
+
const file = input.files[0];
|
|
5658
|
+
// Validate file type
|
|
5659
|
+
if (this.accept && !this.isFileTypeValid(file)) {
|
|
5660
|
+
this.fileError.emit(`Invalid file type. Accepted: ${this.accept}`);
|
|
5661
|
+
input.value = '';
|
|
5662
|
+
return;
|
|
5663
|
+
}
|
|
5664
|
+
// Validate file size
|
|
5665
|
+
if (this.maxFileSizeKB > 0 && file.size > this.maxFileSizeKB * 1024) {
|
|
5666
|
+
this.fileError.emit(`File size exceeds ${this.maxFileSizeKB}KB limit.`);
|
|
5667
|
+
input.value = '';
|
|
5668
|
+
return;
|
|
5669
|
+
}
|
|
5670
|
+
// Instant local preview — no server round-trip needed to show the image
|
|
5671
|
+
this.revokePreview();
|
|
5672
|
+
this.previewUrl = URL.createObjectURL(file);
|
|
5673
|
+
this.imageLoadFailed = false;
|
|
5674
|
+
// Push the preview URL as the form value so validation (e.g. required) passes
|
|
5675
|
+
this.onChange(this.previewUrl);
|
|
5676
|
+
this.onTouched();
|
|
5677
|
+
this.fileSelected.emit(event);
|
|
5678
|
+
input.value = ''; // reset so re-selecting the same file still triggers change
|
|
5679
|
+
}
|
|
5680
|
+
onRemove() {
|
|
5681
|
+
this.revokePreview();
|
|
5682
|
+
this.src = null;
|
|
5683
|
+
this.onChange(null);
|
|
5684
|
+
this.onTouched();
|
|
5685
|
+
this.removed.emit();
|
|
5686
|
+
}
|
|
5687
|
+
// ---------- Utils ----------
|
|
5688
|
+
/** Revoke the previous object URL to free memory */
|
|
5689
|
+
revokePreview() {
|
|
5690
|
+
if (this.previewUrl) {
|
|
5691
|
+
URL.revokeObjectURL(this.previewUrl);
|
|
5692
|
+
this.previewUrl = null;
|
|
5693
|
+
}
|
|
5694
|
+
}
|
|
5695
|
+
isFileTypeValid(file) {
|
|
5696
|
+
const accepted = this.accept.split(',').map(t => t.trim());
|
|
5697
|
+
return accepted.some(type => {
|
|
5698
|
+
if (type.endsWith('/*')) {
|
|
5699
|
+
return file.type.startsWith(type.replace('/*', '/'));
|
|
5700
|
+
}
|
|
5701
|
+
return file.type === type;
|
|
5702
|
+
});
|
|
5703
|
+
}
|
|
5704
|
+
getInitials(name) {
|
|
5705
|
+
const parts = name.trim().split(/\s+/);
|
|
5706
|
+
if (parts.length === 1) {
|
|
5707
|
+
return parts[0].slice(0, 2).toUpperCase();
|
|
5708
|
+
}
|
|
5709
|
+
return (parts[0][0] + parts.at(-1)[0]).toUpperCase();
|
|
5710
|
+
}
|
|
5711
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AvatarProfile, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
5712
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: AvatarProfile, isStandalone: true, selector: "bk-avatar-profile", inputs: { src: "src", alt: "alt", name: "name", size: "size", fallback: "fallback", editable: "editable", accept: "accept", maxFileSizeKB: "maxFileSizeKB", uploadLabel: "uploadLabel", hint: "hint", loading: "loading", removable: "removable", label: "label", required: "required", hasError: "hasError", errorMessage: "errorMessage", disabled: "disabled" }, outputs: { fileSelected: "fileSelected", removed: "removed", fileError: "fileError" }, providers: [
|
|
5713
|
+
{
|
|
5714
|
+
provide: NG_VALUE_ACCESSOR,
|
|
5715
|
+
useExisting: forwardRef(() => AvatarProfile),
|
|
5716
|
+
multi: true
|
|
5717
|
+
}
|
|
5718
|
+
], usesOnChanges: true, ngImport: i0, template: "<div class=\"avatar-profile-container\" [ngClass]=\"sizeClasses\">\r\n @if (label) {\r\n <label class=\"avatar-profile-label\">\r\n {{ label }}\r\n @if (required) {\r\n <span class=\"avatar-profile-label-required\">*</span>\r\n }\r\n </label>\r\n }\r\n\r\n <div class=\"flex gap-4 justify-end\">\r\n <div\r\n [ngClass]=\"containerClasses\"\r\n [bkTooltip]=\"name\"\r\n [bkTooltipPosition]=\"'top'\"\r\n >\r\n\r\n <!-- Loading overlay -->\r\n @if (loading) {\r\n <div class=\"absolute inset-0 flex items-center justify-center z-10 rounded-full bg-white/60\">\r\n <div class=\"w-5 h-5 border-2 border-[#141414] border-t-transparent rounded-full animate-spin\"></div>\r\n </div>\r\n }\r\n\r\n @if (displaySrc && !imageLoadFailed) {\r\n <img\r\n [src]=\"displaySrc\"\r\n [alt]=\"alt\"\r\n class=\"avatar-img\"\r\n (error)=\"onImageError()\"\r\n />\r\n }\r\n\r\n @else if (fallback === 'camera') {\r\n <svg class=\"placeholder-icon\" width=\"23\" height=\"24\" viewBox=\"0 0 23 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M18.3843 4.66667C17.6726 4.66667 17.0193 4.25833 16.6926 3.62833L15.8526 1.93667C15.316 0.875 13.916 0 12.726 0H10.0543C8.85264 0 7.45264 0.875 6.91598 1.93667L6.07598 3.62833C5.74931 4.25833 5.09598 4.66667 4.38431 4.66667C1.85264 4.66667 -0.154023 6.80167 0.00931005 9.32167L0.615977 18.9583C0.755977 21.3617 2.05098 23.3333 5.27098 23.3333H17.4976C20.7176 23.3333 22.001 21.3617 22.1526 18.9583L22.7593 9.32167C22.9226 6.80167 20.916 4.66667 18.3843 4.66667ZM9.63431 6.125H13.1343C13.6126 6.125 14.0093 6.52167 14.0093 7C14.0093 7.47833 13.6126 7.875 13.1343 7.875H9.63431C9.15598 7.875 8.75931 7.47833 8.75931 7C8.75931 6.52167 9.15598 6.125 9.63431 6.125ZM11.3843 18.8067C9.21431 18.8067 7.44098 17.045 7.44098 14.8633C7.44098 12.6817 9.20264 10.92 11.3843 10.92C13.566 10.92 15.3276 12.6817 15.3276 14.8633C15.3276 17.045 13.5543 18.8067 11.3843 18.8067Z\" fill=\"#6B7080\"/>\r\n </svg>\r\n }\r\n\r\n @else if (showInitials) {\r\n <span class=\"avatar-text\">\r\n {{ initials }}\r\n </span>\r\n }\r\n\r\n @else {\r\n <svg class=\"placeholder-icon\" viewBox=\"0 0 32 32\" fill=\"none\" aria-hidden=\"true\" xmlns=\"http://www.w3.org/2000/svg\" > <g clip-path=\"url(#clip0)\"> <path d=\"M16 16c3.682 0 6.667-2.985 6.667-6.667S19.682 2.667 16 2.667 9.333 5.651 9.333 9.333 12.318 16 16 16Z\" stroke=\"#363C51\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" /> <path d=\"M27.453 29.333C27.453 24.173 22.32 20 16 20S4.547 24.173 4.547 29.333\" stroke=\"#363C51\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" /> </g> <defs> <clipPath id=\"clip0\"> <rect width=\"32\" height=\"32\" fill=\"white\" /> </clipPath> </defs> </svg>\r\n }\r\n\r\n <!-- Remove badge -->\r\n @if (showRemoveButton) {\r\n <button\r\n type=\"button\"\r\n class=\"remove-badge\"\r\n (click)=\"onRemove()\"\r\n aria-label=\"Remove avatar\"\r\n >\r\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M1 1L9 9M9 1L1 9\" stroke=\"#6B7080\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\r\n </svg>\r\n </button>\r\n }\r\n\r\n </div>\r\n <div class=\"flex flex-col gap-2 justify-end items-start\">\r\n @if (editable) {\r\n <label class=\"upload-button cursor-pointer\">\r\n {{ uploadLabel }}\r\n <input\r\n type=\"file\"\r\n class=\"hidden\"\r\n [accept]=\"accept\"\r\n [disabled]=\"disabled\"\r\n (change)=\"onFileSelected($event)\"\r\n />\r\n </label>\r\n }\r\n @if (!hasError && hint) {\r\n <p class=\"profile-size\">{{ hint }}</p>\r\n }\r\n @if (hasError && errorMessage) {\r\n <p class=\"avatar-profile-error\">{{ errorMessage }}</p>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".avatar-profile-container{@apply flex flex-col gap-1.5;}.avatar-profile-label{@apply text-sm font-medium text-[#141414];}.avatar-profile-label-required{@apply text-[#E7000B] ml-0.5;}.avatar-profile-error{@apply text-xs text-[#E7000B] font-normal;}.avatar-profile{@apply relative inline-flex items-center justify-center rounded-full flex-shrink-0 select-none shadow-lg transition-all duration-200 border-[3px] border-white bg-[#F9FAFA];}.avatar-profile .avatar-img{@apply w-full h-full object-cover rounded-full;}.upload-button{@apply font-medium text-[#6B7080] border border-[#E3E3E7] rounded shadow-sm;}.sm .upload-button{@apply text-[12px] leading-[18px] px-2 py-3;}.md .upload-button{@apply text-[14px] leading-[20px] px-[10px] py-2.5;}.lg .upload-button{@apply text-[16px] leading-[24px] px-[18px] py-2.5;}.xl .upload-button{@apply text-[16px] leading-[24px] px-5 py-3;}.profile-size{@apply font-medium text-[#6B7080];}.sm .profile-size{@apply text-[10px] leading-[14px];}.md .profile-size{@apply text-[12px] leading-[18px];}.lg .profile-size{@apply text-[14px] leading-[20px];}.xl .profile-size{@apply text-[16px] leading-[24px];}.avatar-profile.sm .avatar-text{@apply font-medium text-[30px] leading-[38px];}.avatar-profile.md .avatar-text{@apply font-medium text-[36px] leading-[44px];}.avatar-profile.lg .avatar-text{@apply font-medium text-[45px] leading-[55px];}.avatar-profile.xl .avatar-text{@apply font-medium text-[60px] leading-[72px];}.avatar-profile{@apply font-medium text-[#6B7080];}.avatar-profile.sm{@apply size-[72px] text-sm;}.avatar-profile.md{@apply size-[96px] text-base;}.avatar-profile.lg{@apply size-[120px] text-[18px] leading-[26px];}.avatar-profile.xl{@apply size-[160px] text-xl;}.avatar-profile.sm .placeholder-icon{@apply size-[28px];}.avatar-profile.md .placeholder-icon{@apply size-[42px];}.avatar-profile.lg .placeholder-icon{@apply size-[52px];}.avatar-profile.xl .placeholder-icon{@apply size-[65px];}.remove-badge{@apply absolute top-0 right-0 w-5 h-5 bg-white rounded-full shadow-md flex items-center justify-center cursor-pointer hover:bg-gray-50 transition z-20 border-0 p-0;}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: BKTooltipDirective, selector: "[bkTooltip]", inputs: ["bkTooltip", "bkTooltipPosition"] }] });
|
|
5719
|
+
}
|
|
5720
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: AvatarProfile, decorators: [{
|
|
5721
|
+
type: Component,
|
|
5722
|
+
args: [{ selector: 'bk-avatar-profile', imports: [NgClass, CommonModule, BKTooltipDirective], providers: [
|
|
5723
|
+
{
|
|
5724
|
+
provide: NG_VALUE_ACCESSOR,
|
|
5725
|
+
useExisting: forwardRef(() => AvatarProfile),
|
|
5726
|
+
multi: true
|
|
5727
|
+
}
|
|
5728
|
+
], template: "<div class=\"avatar-profile-container\" [ngClass]=\"sizeClasses\">\r\n @if (label) {\r\n <label class=\"avatar-profile-label\">\r\n {{ label }}\r\n @if (required) {\r\n <span class=\"avatar-profile-label-required\">*</span>\r\n }\r\n </label>\r\n }\r\n\r\n <div class=\"flex gap-4 justify-end\">\r\n <div\r\n [ngClass]=\"containerClasses\"\r\n [bkTooltip]=\"name\"\r\n [bkTooltipPosition]=\"'top'\"\r\n >\r\n\r\n <!-- Loading overlay -->\r\n @if (loading) {\r\n <div class=\"absolute inset-0 flex items-center justify-center z-10 rounded-full bg-white/60\">\r\n <div class=\"w-5 h-5 border-2 border-[#141414] border-t-transparent rounded-full animate-spin\"></div>\r\n </div>\r\n }\r\n\r\n @if (displaySrc && !imageLoadFailed) {\r\n <img\r\n [src]=\"displaySrc\"\r\n [alt]=\"alt\"\r\n class=\"avatar-img\"\r\n (error)=\"onImageError()\"\r\n />\r\n }\r\n\r\n @else if (fallback === 'camera') {\r\n <svg class=\"placeholder-icon\" width=\"23\" height=\"24\" viewBox=\"0 0 23 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M18.3843 4.66667C17.6726 4.66667 17.0193 4.25833 16.6926 3.62833L15.8526 1.93667C15.316 0.875 13.916 0 12.726 0H10.0543C8.85264 0 7.45264 0.875 6.91598 1.93667L6.07598 3.62833C5.74931 4.25833 5.09598 4.66667 4.38431 4.66667C1.85264 4.66667 -0.154023 6.80167 0.00931005 9.32167L0.615977 18.9583C0.755977 21.3617 2.05098 23.3333 5.27098 23.3333H17.4976C20.7176 23.3333 22.001 21.3617 22.1526 18.9583L22.7593 9.32167C22.9226 6.80167 20.916 4.66667 18.3843 4.66667ZM9.63431 6.125H13.1343C13.6126 6.125 14.0093 6.52167 14.0093 7C14.0093 7.47833 13.6126 7.875 13.1343 7.875H9.63431C9.15598 7.875 8.75931 7.47833 8.75931 7C8.75931 6.52167 9.15598 6.125 9.63431 6.125ZM11.3843 18.8067C9.21431 18.8067 7.44098 17.045 7.44098 14.8633C7.44098 12.6817 9.20264 10.92 11.3843 10.92C13.566 10.92 15.3276 12.6817 15.3276 14.8633C15.3276 17.045 13.5543 18.8067 11.3843 18.8067Z\" fill=\"#6B7080\"/>\r\n </svg>\r\n }\r\n\r\n @else if (showInitials) {\r\n <span class=\"avatar-text\">\r\n {{ initials }}\r\n </span>\r\n }\r\n\r\n @else {\r\n <svg class=\"placeholder-icon\" viewBox=\"0 0 32 32\" fill=\"none\" aria-hidden=\"true\" xmlns=\"http://www.w3.org/2000/svg\" > <g clip-path=\"url(#clip0)\"> <path d=\"M16 16c3.682 0 6.667-2.985 6.667-6.667S19.682 2.667 16 2.667 9.333 5.651 9.333 9.333 12.318 16 16 16Z\" stroke=\"#363C51\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" /> <path d=\"M27.453 29.333C27.453 24.173 22.32 20 16 20S4.547 24.173 4.547 29.333\" stroke=\"#363C51\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" /> </g> <defs> <clipPath id=\"clip0\"> <rect width=\"32\" height=\"32\" fill=\"white\" /> </clipPath> </defs> </svg>\r\n }\r\n\r\n <!-- Remove badge -->\r\n @if (showRemoveButton) {\r\n <button\r\n type=\"button\"\r\n class=\"remove-badge\"\r\n (click)=\"onRemove()\"\r\n aria-label=\"Remove avatar\"\r\n >\r\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M1 1L9 9M9 1L1 9\" stroke=\"#6B7080\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\r\n </svg>\r\n </button>\r\n }\r\n\r\n </div>\r\n <div class=\"flex flex-col gap-2 justify-end items-start\">\r\n @if (editable) {\r\n <label class=\"upload-button cursor-pointer\">\r\n {{ uploadLabel }}\r\n <input\r\n type=\"file\"\r\n class=\"hidden\"\r\n [accept]=\"accept\"\r\n [disabled]=\"disabled\"\r\n (change)=\"onFileSelected($event)\"\r\n />\r\n </label>\r\n }\r\n @if (!hasError && hint) {\r\n <p class=\"profile-size\">{{ hint }}</p>\r\n }\r\n @if (hasError && errorMessage) {\r\n <p class=\"avatar-profile-error\">{{ errorMessage }}</p>\r\n }\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".avatar-profile-container{@apply flex flex-col gap-1.5;}.avatar-profile-label{@apply text-sm font-medium text-[#141414];}.avatar-profile-label-required{@apply text-[#E7000B] ml-0.5;}.avatar-profile-error{@apply text-xs text-[#E7000B] font-normal;}.avatar-profile{@apply relative inline-flex items-center justify-center rounded-full flex-shrink-0 select-none shadow-lg transition-all duration-200 border-[3px] border-white bg-[#F9FAFA];}.avatar-profile .avatar-img{@apply w-full h-full object-cover rounded-full;}.upload-button{@apply font-medium text-[#6B7080] border border-[#E3E3E7] rounded shadow-sm;}.sm .upload-button{@apply text-[12px] leading-[18px] px-2 py-3;}.md .upload-button{@apply text-[14px] leading-[20px] px-[10px] py-2.5;}.lg .upload-button{@apply text-[16px] leading-[24px] px-[18px] py-2.5;}.xl .upload-button{@apply text-[16px] leading-[24px] px-5 py-3;}.profile-size{@apply font-medium text-[#6B7080];}.sm .profile-size{@apply text-[10px] leading-[14px];}.md .profile-size{@apply text-[12px] leading-[18px];}.lg .profile-size{@apply text-[14px] leading-[20px];}.xl .profile-size{@apply text-[16px] leading-[24px];}.avatar-profile.sm .avatar-text{@apply font-medium text-[30px] leading-[38px];}.avatar-profile.md .avatar-text{@apply font-medium text-[36px] leading-[44px];}.avatar-profile.lg .avatar-text{@apply font-medium text-[45px] leading-[55px];}.avatar-profile.xl .avatar-text{@apply font-medium text-[60px] leading-[72px];}.avatar-profile{@apply font-medium text-[#6B7080];}.avatar-profile.sm{@apply size-[72px] text-sm;}.avatar-profile.md{@apply size-[96px] text-base;}.avatar-profile.lg{@apply size-[120px] text-[18px] leading-[26px];}.avatar-profile.xl{@apply size-[160px] text-xl;}.avatar-profile.sm .placeholder-icon{@apply size-[28px];}.avatar-profile.md .placeholder-icon{@apply size-[42px];}.avatar-profile.lg .placeholder-icon{@apply size-[52px];}.avatar-profile.xl .placeholder-icon{@apply size-[65px];}.remove-badge{@apply absolute top-0 right-0 w-5 h-5 bg-white rounded-full shadow-md flex items-center justify-center cursor-pointer hover:bg-gray-50 transition z-20 border-0 p-0;}\n"] }]
|
|
5729
|
+
}], propDecorators: { src: [{
|
|
5730
|
+
type: Input
|
|
5731
|
+
}], alt: [{
|
|
5732
|
+
type: Input
|
|
5733
|
+
}], name: [{
|
|
5734
|
+
type: Input
|
|
5735
|
+
}], size: [{
|
|
5736
|
+
type: Input
|
|
5737
|
+
}], fallback: [{
|
|
5738
|
+
type: Input
|
|
5739
|
+
}], editable: [{
|
|
5740
|
+
type: Input
|
|
5741
|
+
}], accept: [{
|
|
5742
|
+
type: Input
|
|
5743
|
+
}], maxFileSizeKB: [{
|
|
5744
|
+
type: Input
|
|
5745
|
+
}], uploadLabel: [{
|
|
5746
|
+
type: Input
|
|
5747
|
+
}], hint: [{
|
|
5748
|
+
type: Input
|
|
5749
|
+
}], loading: [{
|
|
5750
|
+
type: Input
|
|
5751
|
+
}], removable: [{
|
|
5752
|
+
type: Input
|
|
5753
|
+
}], label: [{
|
|
5754
|
+
type: Input
|
|
5755
|
+
}], required: [{
|
|
5756
|
+
type: Input
|
|
5757
|
+
}], hasError: [{
|
|
5758
|
+
type: Input
|
|
5759
|
+
}], errorMessage: [{
|
|
5760
|
+
type: Input
|
|
5761
|
+
}], disabled: [{
|
|
5762
|
+
type: Input
|
|
5763
|
+
}], fileSelected: [{
|
|
5764
|
+
type: Output
|
|
5765
|
+
}], removed: [{
|
|
5766
|
+
type: Output
|
|
5767
|
+
}], fileError: [{
|
|
5768
|
+
type: Output
|
|
5769
|
+
}] } });
|
|
5770
|
+
|
|
5546
5771
|
/*
|
|
5547
5772
|
* Public API Surface of brickclay-lib
|
|
5548
5773
|
*/
|
|
@@ -5552,5 +5777,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
5552
5777
|
* Generated bundle index. Do not edit.
|
|
5553
5778
|
*/
|
|
5554
5779
|
|
|
5555
|
-
export { BKTooltipDirective, BkBadge, BkButton, BkButtonGroup, BkCheckbox, BkCustomCalendar, BkDialogActions, BkDialogClose, BkDialogContent, BkDialogModule, BkDialogTitle, BkGrid, BkIconButton, BkInput, BkInputChips, BkPill, BkRadioButton, BkScheduledDatePicker, BkSelect, BkSpinner, BkTabs, BkTextarea, BkTimePicker, BkToggle, BkValidator, BrickclayIcons, BrickclayLib, CalendarManagerService, CalendarModule,
|
|
5780
|
+
export { AvatarProfile, BKTooltipDirective, BK_DEFAULT_DIALOG_CONFIG, BK_DIALOG_DATA, BK_DIALOG_GLOBAL_CONFIG, BkBadge, BkButton, BkButtonGroup, BkCheckbox, BkCustomCalendar, BkDialogActions, BkDialogClose, BkDialogContent, BkDialogModule, BkDialogRef, BkDialogService, BkDialogTitle, BkGrid, BkIconButton, BkInput, BkInputChips, BkPill, BkRadioButton, BkScheduledDatePicker, BkSelect, BkSpinner, BkTabs, BkTextarea, BkTimePicker, BkToggle, BkValidator, BrickclayIcons, BrickclayLib, CalendarManagerService, CalendarModule, getDialogBackdropAnimation, getDialogPanelAnimation };
|
|
5556
5781
|
//# sourceMappingURL=brickclay-org-ui.mjs.map
|