@haloduck/ui 2.0.27 → 2.0.29
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/haloduck-ui.mjs +118 -111
- package/fesm2022/haloduck-ui.mjs.map +1 -1
- package/index.d.ts +28 -17
- package/package.json +1 -1
package/fesm2022/haloduck-ui.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable, Input, Component, inject, ChangeDetectorRef, forwardRef, ViewChild, signal, EventEmitter, Output, ViewContainerRef, NgZone, isDevMode,
|
|
2
|
+
import { Injectable, Input, Component, inject, ChangeDetectorRef, forwardRef, ViewChild, signal, EventEmitter, Output, ViewContainerRef, NgZone, isDevMode, ElementRef, Directive, ChangeDetectionStrategy, HostBinding } from '@angular/core';
|
|
3
3
|
import { signIn, confirmSignIn, resetPassword, confirmResetPassword } from 'aws-amplify/auth';
|
|
4
4
|
import * as i1$1 from '@angular/forms';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
6
|
-
import { BehaviorSubject, zip, Subject, takeUntil, tap, combineLatest, switchMap, of, Observable, distinctUntilChanged, map, take
|
|
6
|
+
import { BehaviorSubject, zip, Subject, takeUntil, tap, combineLatest, switchMap, of, Observable, distinctUntilChanged, map, take } from 'rxjs';
|
|
7
7
|
import { ulid } from 'ulid';
|
|
8
8
|
import * as i1 from '@angular/common';
|
|
9
9
|
import { CommonModule, DecimalPipe, DatePipe } from '@angular/common';
|
|
@@ -2888,11 +2888,108 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
2888
2888
|
args: ['viewerContainer']
|
|
2889
2889
|
}] } });
|
|
2890
2890
|
|
|
2891
|
+
class AutoLoadDirective {
|
|
2892
|
+
elementRef = inject(ElementRef);
|
|
2893
|
+
ngZone = inject(NgZone);
|
|
2894
|
+
observer;
|
|
2895
|
+
isLoading = false;
|
|
2896
|
+
hasLoadedOnce = false;
|
|
2897
|
+
autoLoadEnabled = true;
|
|
2898
|
+
autoLoadThreshold = 0.1;
|
|
2899
|
+
autoLoadRootMargin = '0px';
|
|
2900
|
+
autoLoadTrigger = new EventEmitter();
|
|
2901
|
+
ngOnInit() {
|
|
2902
|
+
if (this.autoLoadEnabled && 'IntersectionObserver' in window) {
|
|
2903
|
+
this.initializeObserver();
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
ngOnDestroy() {
|
|
2907
|
+
this.disconnect();
|
|
2908
|
+
}
|
|
2909
|
+
initializeObserver() {
|
|
2910
|
+
this.ngZone.runOutsideAngular(() => {
|
|
2911
|
+
this.observer = new IntersectionObserver((entries) => {
|
|
2912
|
+
entries.forEach((entry) => {
|
|
2913
|
+
if (entry.isIntersecting && !this.isLoading) {
|
|
2914
|
+
this.ngZone.run(() => {
|
|
2915
|
+
this.triggerLoad();
|
|
2916
|
+
});
|
|
2917
|
+
}
|
|
2918
|
+
});
|
|
2919
|
+
}, {
|
|
2920
|
+
threshold: this.autoLoadThreshold,
|
|
2921
|
+
rootMargin: this.autoLoadRootMargin,
|
|
2922
|
+
});
|
|
2923
|
+
this.observer.observe(this.elementRef.nativeElement);
|
|
2924
|
+
});
|
|
2925
|
+
}
|
|
2926
|
+
triggerLoad() {
|
|
2927
|
+
if (this.isLoading || !this.autoLoadEnabled) {
|
|
2928
|
+
return;
|
|
2929
|
+
}
|
|
2930
|
+
// 무한 로드 방지: 첫 번째 보임 감지 시에는 로드하지 않고,
|
|
2931
|
+
// 실제로 사용자가 스크롤해서 다시 보일 때만 로드
|
|
2932
|
+
if (this.hasLoadedOnce) {
|
|
2933
|
+
this.isLoading = true;
|
|
2934
|
+
this.autoLoadTrigger.emit();
|
|
2935
|
+
// 로딩 상태를 일정 시간 후 해제하여 중복 로드 방지
|
|
2936
|
+
setTimeout(() => {
|
|
2937
|
+
this.isLoading = false;
|
|
2938
|
+
}, 2000);
|
|
2939
|
+
// 옵저버를 일시적으로 해제하여 연속 트리거 방지
|
|
2940
|
+
this.temporarilyDisableObserver();
|
|
2941
|
+
}
|
|
2942
|
+
this.hasLoadedOnce = true;
|
|
2943
|
+
}
|
|
2944
|
+
temporarilyDisableObserver() {
|
|
2945
|
+
if (this.observer) {
|
|
2946
|
+
this.observer.disconnect();
|
|
2947
|
+
// 2초 후 옵저버 재연결
|
|
2948
|
+
setTimeout(() => {
|
|
2949
|
+
if (this.autoLoadEnabled && this.observer) {
|
|
2950
|
+
this.observer.observe(this.elementRef.nativeElement);
|
|
2951
|
+
}
|
|
2952
|
+
}, 2000);
|
|
2953
|
+
}
|
|
2954
|
+
}
|
|
2955
|
+
disconnect() {
|
|
2956
|
+
if (this.observer) {
|
|
2957
|
+
this.observer.disconnect();
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2960
|
+
// 외부에서 로딩 상태를 제어할 수 있는 메서드
|
|
2961
|
+
setLoadingState(loading) {
|
|
2962
|
+
this.isLoading = loading;
|
|
2963
|
+
}
|
|
2964
|
+
// 자동 로드를 재활성화하는 메서드
|
|
2965
|
+
resetAutoLoad() {
|
|
2966
|
+
this.hasLoadedOnce = false;
|
|
2967
|
+
this.isLoading = false;
|
|
2968
|
+
}
|
|
2969
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AutoLoadDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
2970
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.1.4", type: AutoLoadDirective, isStandalone: true, selector: "[haloduckAutoLoad]", inputs: { autoLoadEnabled: "autoLoadEnabled", autoLoadThreshold: "autoLoadThreshold", autoLoadRootMargin: "autoLoadRootMargin" }, outputs: { autoLoadTrigger: "autoLoadTrigger" }, ngImport: i0 });
|
|
2971
|
+
}
|
|
2972
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AutoLoadDirective, decorators: [{
|
|
2973
|
+
type: Directive,
|
|
2974
|
+
args: [{
|
|
2975
|
+
selector: '[haloduckAutoLoad]',
|
|
2976
|
+
standalone: true,
|
|
2977
|
+
}]
|
|
2978
|
+
}], propDecorators: { autoLoadEnabled: [{
|
|
2979
|
+
type: Input
|
|
2980
|
+
}], autoLoadThreshold: [{
|
|
2981
|
+
type: Input
|
|
2982
|
+
}], autoLoadRootMargin: [{
|
|
2983
|
+
type: Input
|
|
2984
|
+
}], autoLoadTrigger: [{
|
|
2985
|
+
type: Output
|
|
2986
|
+
}] } });
|
|
2987
|
+
|
|
2891
2988
|
class TableComponent {
|
|
2892
2989
|
coreService = inject(CoreService);
|
|
2893
|
-
|
|
2894
|
-
destroyRef = inject(DestroyRef);
|
|
2990
|
+
loadMoreRowRef;
|
|
2895
2991
|
tableLayout = 'auto';
|
|
2992
|
+
autoLoad = true;
|
|
2896
2993
|
showHeader = true;
|
|
2897
2994
|
useLoadMore = true;
|
|
2898
2995
|
columns = [];
|
|
@@ -2907,12 +3004,6 @@ class TableComponent {
|
|
|
2907
3004
|
onLoadMore = new EventEmitter();
|
|
2908
3005
|
onRowClick = new EventEmitter();
|
|
2909
3006
|
onRowDblClick = new EventEmitter();
|
|
2910
|
-
loadMoreRow;
|
|
2911
|
-
dataRows;
|
|
2912
|
-
scrollContainer;
|
|
2913
|
-
intersectionObserver;
|
|
2914
|
-
scrollListenerTarget;
|
|
2915
|
-
didScrollSinceLastLoad = false;
|
|
2916
3007
|
getColumnValue(row, column) {
|
|
2917
3008
|
const value = this.getColumnValueRaw(row, column);
|
|
2918
3009
|
if (column.customRenderFn) {
|
|
@@ -2992,6 +3083,13 @@ class TableComponent {
|
|
|
2992
3083
|
this.onLoadMore.emit(lastEvaluatedKey);
|
|
2993
3084
|
});
|
|
2994
3085
|
}
|
|
3086
|
+
onAutoLoadTriggered() {
|
|
3087
|
+
if (this.autoLoad) {
|
|
3088
|
+
this.lastEvaluatedKey.pipe(take(1)).subscribe((lastEvaluatedKey) => {
|
|
3089
|
+
this.onLoadMore.emit(lastEvaluatedKey);
|
|
3090
|
+
});
|
|
3091
|
+
}
|
|
3092
|
+
}
|
|
2995
3093
|
onRowClicked(row) {
|
|
2996
3094
|
this.onRowClick.emit(row);
|
|
2997
3095
|
}
|
|
@@ -2999,102 +3097,20 @@ class TableComponent {
|
|
|
2999
3097
|
this.onRowDblClick.emit(row);
|
|
3000
3098
|
}
|
|
3001
3099
|
ngOnInit() { }
|
|
3002
|
-
ngAfterViewInit() {
|
|
3003
|
-
if (!this.useLoadMore)
|
|
3004
|
-
return;
|
|
3005
|
-
combineLatest([this.rows, this.lastEvaluatedKey, this.isLoading])
|
|
3006
|
-
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3007
|
-
.subscribe(() => {
|
|
3008
|
-
this.setupIntersectionObserver();
|
|
3009
|
-
});
|
|
3010
|
-
// 데이터 행 렌더링 변화에 맞춰 센티널 타겟을 재지정
|
|
3011
|
-
this.dataRows?.changes
|
|
3012
|
-
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
3013
|
-
.subscribe(() => {
|
|
3014
|
-
this.setupIntersectionObserver();
|
|
3015
|
-
});
|
|
3016
|
-
const container = this.scrollContainer?.nativeElement;
|
|
3017
|
-
this.scrollListenerTarget = container || (typeof window !== 'undefined' ? window : undefined);
|
|
3018
|
-
if (this.scrollListenerTarget) {
|
|
3019
|
-
this.scrollListenerTarget.addEventListener('scroll', this.onScroll, { passive: true });
|
|
3020
|
-
}
|
|
3021
|
-
}
|
|
3022
|
-
ngOnDestroy() {
|
|
3023
|
-
this.cleanupIntersectionObserver();
|
|
3024
|
-
if (this.scrollListenerTarget) {
|
|
3025
|
-
this.scrollListenerTarget.removeEventListener('scroll', this.onScroll);
|
|
3026
|
-
this.scrollListenerTarget = undefined;
|
|
3027
|
-
}
|
|
3028
|
-
}
|
|
3029
|
-
setupIntersectionObserver() {
|
|
3030
|
-
if (!this.useLoadMore)
|
|
3031
|
-
return;
|
|
3032
|
-
this.cleanupIntersectionObserver();
|
|
3033
|
-
const rootElement = this.scrollContainer?.nativeElement || null;
|
|
3034
|
-
// 우선순위: 마지막 데이터 행 -> 로드모어 행
|
|
3035
|
-
const lastRowEl = this.dataRows?.last?.nativeElement;
|
|
3036
|
-
const target = lastRowEl || this.loadMoreRow?.nativeElement;
|
|
3037
|
-
if (!target)
|
|
3038
|
-
return;
|
|
3039
|
-
// 새로운 옵저버 생성 시 초기 교차 무시 플래그 초기화
|
|
3040
|
-
this.hasObservedOnce = false;
|
|
3041
|
-
// 스크롤 발생 전에는 자동 로드를 막음
|
|
3042
|
-
this.didScrollSinceLastLoad = false;
|
|
3043
|
-
this.ngZone.runOutsideAngular(() => {
|
|
3044
|
-
this.intersectionObserver = new IntersectionObserver(this.onIntersection, {
|
|
3045
|
-
root: rootElement || undefined,
|
|
3046
|
-
rootMargin: '0px 0px 200px 0px',
|
|
3047
|
-
threshold: 0.05,
|
|
3048
|
-
});
|
|
3049
|
-
this.intersectionObserver.observe(target);
|
|
3050
|
-
});
|
|
3051
|
-
}
|
|
3052
|
-
cleanupIntersectionObserver() {
|
|
3053
|
-
if (this.intersectionObserver) {
|
|
3054
|
-
this.intersectionObserver.disconnect();
|
|
3055
|
-
this.intersectionObserver = undefined;
|
|
3056
|
-
}
|
|
3057
|
-
}
|
|
3058
|
-
hasObservedOnce = false;
|
|
3059
|
-
onIntersection = (entries) => {
|
|
3060
|
-
for (const entry of entries) {
|
|
3061
|
-
if (!entry.isIntersecting)
|
|
3062
|
-
continue;
|
|
3063
|
-
const container = this.scrollContainer?.nativeElement;
|
|
3064
|
-
const allowWithoutScroll = !container || container.scrollHeight <= container.clientHeight;
|
|
3065
|
-
if (!this.hasObservedOnce && !allowWithoutScroll) {
|
|
3066
|
-
// 내부 스크롤 컨테이너가 있고 첫 교차는 무시
|
|
3067
|
-
this.hasObservedOnce = true;
|
|
3068
|
-
continue;
|
|
3069
|
-
}
|
|
3070
|
-
// 마지막 키가 존재, 로딩 아님, 그리고 (실제 스크롤 발생 or 스크롤 불필요)일 때만 로드
|
|
3071
|
-
Promise.all([
|
|
3072
|
-
firstValueFrom(this.lastEvaluatedKey.pipe(take(1))),
|
|
3073
|
-
firstValueFrom(this.isLoading.pipe(take(1))),
|
|
3074
|
-
]).then(([lastKey, isLoading]) => {
|
|
3075
|
-
const scrolledOk = this.didScrollSinceLastLoad || allowWithoutScroll;
|
|
3076
|
-
if (!(lastKey && !isLoading && scrolledOk)) {
|
|
3077
|
-
return;
|
|
3078
|
-
}
|
|
3079
|
-
// 중복 호출 방지: 즉시 관찰 해제 후 로드 트리거
|
|
3080
|
-
this.cleanupIntersectionObserver();
|
|
3081
|
-
this.didScrollSinceLastLoad = false;
|
|
3082
|
-
this.ngZone.run(() => this.onLoadMoreClicked());
|
|
3083
|
-
});
|
|
3084
|
-
}
|
|
3085
|
-
};
|
|
3086
|
-
onScroll = () => {
|
|
3087
|
-
this.didScrollSinceLastLoad = true;
|
|
3088
|
-
};
|
|
3089
|
-
// Note: 무스크롤 자동 로드는 연속 로딩을 유발할 수 있어 제거
|
|
3100
|
+
ngAfterViewInit() { }
|
|
3090
3101
|
constructor() { }
|
|
3091
3102
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3092
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: TableComponent, isStandalone: true, selector: "haloduck-table", inputs: { tableLayout: "tableLayout", showHeader: "showHeader", useLoadMore: "useLoadMore", columns: "columns", rows: "rows", isLoading: "isLoading", isPaging: "isPaging", sort: "sort", expandedTemplate: "expandedTemplate", customTemplates: "customTemplates", lastEvaluatedKey: "lastEvaluatedKey" }, outputs: { onSortChange: "onSortChange", onLoadMore: "onLoadMore", onRowClick: "onRowClick", onRowDblClick: "onRowDblClick" }, providers: [provideTranslocoScope('haloduck')], viewQueries: [{ propertyName: "
|
|
3103
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.4", type: TableComponent, isStandalone: true, selector: "haloduck-table", inputs: { tableLayout: "tableLayout", autoLoad: "autoLoad", showHeader: "showHeader", useLoadMore: "useLoadMore", columns: "columns", rows: "rows", isLoading: "isLoading", isPaging: "isPaging", sort: "sort", expandedTemplate: "expandedTemplate", customTemplates: "customTemplates", lastEvaluatedKey: "lastEvaluatedKey" }, outputs: { onSortChange: "onSortChange", onLoadMore: "onLoadMore", onRowClick: "onRowClick", onRowDblClick: "onRowDblClick" }, providers: [provideTranslocoScope('haloduck')], viewQueries: [{ propertyName: "loadMoreRowRef", first: true, predicate: ["loadMoreRow"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div class=\"w-full h-full shadow border border-light-inactive dark:border-dark-inactive rounded-lg overflow-auto\">\n <table class=\"w-full h-full\"\n [ngClass]=\"{\n 'table-fixed': tableLayout === 'fixed',\n 'table-auto': tableLayout === 'auto',\n }\">\n <colgroup>\n @for (column of columns; track column.key) {\n @if (!column.hidden || !(column.hidden | async)) {\n <col class=\"{{ column.width || '' }}\" />\n }\n }\n </colgroup>\n @if (showHeader) {\n <thead class=\"bg-light-inactive/50 dark:bg-dark-inactive/50 rounded-tl-lg rounded-tr-lg\">\n <tr>\n @for (column of columns; track column.key) {\n @if (!column.hidden || !(column.hidden | async)) {\n <th scope=\"col\"\n class=\"{{ column.align || '' }} py-3.5 pl-4 pr-3 text-sm font-semibold text-light-on-background dark:text-dark-on-background whitespace-nowrap\">\n <span class=\"group inline-flex\">\n {{ column.label }}\n @if (column.sortable) {\n @switch (getSortDirection(column.sort?.field || column.key) | async)\n {\n @case('desc') {\n <span (click)=\"onUpdateSort(column.sort?.field || column.key, 'asc')\"\n class=\"ml-2 flex-none rounded text-light-on-inactive dark:text-dark-on-inactive\">\n <svg class=\"size-5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n data-slot=\"icon\">\n <path fill-rule=\"evenodd\"\n d=\"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n @case('asc') {\n <span (click)=\"onUpdateSort(column.sort?.field || column.key, 'desc')\"\n class=\"ml-2 flex-none rounded text-light-on-inactive dark:text-dark-on-inactive\">\n <svg class=\"size-5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n data-slot=\"icon\">\n <path fill-rule=\"evenodd\"\n d=\"M14.78 11.78a.75.75 0 0 1-1.06 0L10 8.06l-3.72 3.72a.75.75 0 1 1-1.06-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06Z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n @default {\n <span (click)=\"onUpdateSort(column.sort?.field || column.key, 'asc')\"\n class=\"invisible ml-2 flex-none rounded text-light-on-inactive dark:text-dark-on-inactive group-hover:visible group-focus:visible\">\n <svg class=\"size-5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n data-slot=\"icon\">\n <path fill-rule=\"evenodd\"\n d=\"M14.78 11.78a.75.75 0 0 1-1.06 0L10 8.06l-3.72 3.72a.75.75 0 1 1-1.06-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06Z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n }\n }\n </span>\n </th>\n }\n }\n </tr>\n </thead>\n }\n <tbody class=\"overflow-scroll\">\n @for (row of rows | async; track row['id']; let lastRow = $last) {\n <tr class=\"border-t border-light-inactive dark:border-dark-inactive {{ row.bgColor || '' }}\"\n (click)=\"onRowClicked(row)\"\n (dblclick)=\"onRowDblClicked(row)\"\n [ngClass]=\"{'rounded-b-lg': lastRow && (lastEvaluatedKey | async) === null, 'even:bg-light-alternative dark:even:bg-dark-alternative odd:bg-light-background dark:odd:bg-dark-background': !row.bgColor }\"\n [ngStyle]=\"{ 'background-color': row.bgColor || '' }\">\n @for (column of columns; track column.key) {\n @if (!column.hidden || !(column.hidden | async)) {\n <td class=\"relative overflow-visible {{ column.align || '' }} whitespace-nowrap px-3 text-sm text-light-on-background dark:text-dark-on-background\"\n [ngClass]=\"{\n 'first:rounded-bl-lg last:rounded-br-lg': lastRow && (lastEvaluatedKey | async) === null,\n 'text-wrap': row.isExpanded && column.type !== 'custom',\n 'overflow-x-hidden text-ellipsis' : !row.isExpanded && column.type !== 'custom',\n 'py-2': column.type === 'custom',\n 'py-4': column.type !== 'custom'\n }\">\n @if (column.type === 'custom') {\n @if (column.customRenderTemplate) {\n <ng-container [ngTemplateOutlet]=\"customTemplates[column.customRenderTemplate]\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"></ng-container>\n }\n }\n @else {\n {{ getColumnValue(row, column) | async }}\n }\n </td>\n }\n }\n </tr>\n\n @if (row.isExpanded && expandedTemplate) {\n <tr>\n <td [attr.colspan]=\"columns.length\">\n </td>\n </tr>\n <tr class=\"even:bg-light-alternative dark:even:bg-dark-alternative odd:bg-light-background dark:odd:bg-dark-background\">\n <td [attr.colspan]=\"columns.length\"\n class=\"whitespace-nowrap px-3 pb-4 text-sm text-center\">\n <ng-container [ngTemplateOutlet]=\"expandedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row }\"></ng-container>\n </td>\n </tr>\n }\n\n @if (lastRow && (lastEvaluatedKey | async) && !(isLoading | async) && useLoadMore) {\n <tr #loadMoreRow \n class=\"border-t border-light-inactive dark:border-dark-inactive bg-light-background dark:bg-dark-background\"\n haloduckAutoLoad\n [autoLoadEnabled]=\"autoLoad\"\n [autoLoadThreshold]=\"0.1\"\n (autoLoadTrigger)=\"onAutoLoadTriggered()\">\n <td [attr.colspan]=\"columns.length\"\n class=\"whitespace-nowrap px-3 py-4 text-sm text-light-on-background dark:text-dark-on-background text-center h-16 bg-light-background dark:bg-dark-background rounded-bl-lg rounded-br-lg\">\n <div (click)=\"onLoadMoreClicked()\"\n class=\"cursor-pointer\">\n {{ 'haloduck.ui.table.Load More...' | transloco }}\n </div>\n </td>\n </tr>\n }\n\n } @empty {\n @if(!(isLoading | async)) {\n <tr>\n <td [attr.colspan]=\"columns.length\"\n class=\"whitespace-nowrap px-3 py-4 text-sm text-light-on-background dark:text-dark-on-background text-center h-16 bg-light-background dark:bg-dark-background rounded-bl-lg rounded-br-lg\">\n {{ 'haloduck.ui.table.No data available.' | transloco }}\n </td>\n </tr>\n }\n }\n\n @if(isLoading | async) {\n @for ( i of [0,1,2,3,4]; track i; let lastRow = $last)\n {\n <tr class=\"bg-light-background dark:bg-dark-background border-t border-light-inactive/50 dark:border-dark-inactive/50\">\n @for (column of columns; track column.key) {\n <td class=\"whitespace-nowrap py-4 pl-4 pr-3 text-sm\"\n [ngClass]=\"{'first:rounded-bl-lg last:rounded-br-lg': lastRow}\">\n <div class=\"h-4 bg-light-inactive/50 dark:bg-dark-inactive/50 rounded-md animate-pulse\"></div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: TranslocoModule }, { kind: "directive", type: AutoLoadDirective, selector: "[haloduckAutoLoad]", inputs: ["autoLoadEnabled", "autoLoadThreshold", "autoLoadRootMargin"], outputs: ["autoLoadTrigger"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i2$1.TranslocoPipe, name: "transloco" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3093
3104
|
}
|
|
3094
3105
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TableComponent, decorators: [{
|
|
3095
3106
|
type: Component,
|
|
3096
|
-
args: [{ selector: 'haloduck-table', imports: [CommonModule, TranslocoModule], providers: [provideTranslocoScope('haloduck')], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div
|
|
3097
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
3107
|
+
args: [{ selector: 'haloduck-table', imports: [CommonModule, TranslocoModule, AutoLoadDirective], providers: [provideTranslocoScope('haloduck')], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"w-full h-full shadow border border-light-inactive dark:border-dark-inactive rounded-lg overflow-auto\">\n <table class=\"w-full h-full\"\n [ngClass]=\"{\n 'table-fixed': tableLayout === 'fixed',\n 'table-auto': tableLayout === 'auto',\n }\">\n <colgroup>\n @for (column of columns; track column.key) {\n @if (!column.hidden || !(column.hidden | async)) {\n <col class=\"{{ column.width || '' }}\" />\n }\n }\n </colgroup>\n @if (showHeader) {\n <thead class=\"bg-light-inactive/50 dark:bg-dark-inactive/50 rounded-tl-lg rounded-tr-lg\">\n <tr>\n @for (column of columns; track column.key) {\n @if (!column.hidden || !(column.hidden | async)) {\n <th scope=\"col\"\n class=\"{{ column.align || '' }} py-3.5 pl-4 pr-3 text-sm font-semibold text-light-on-background dark:text-dark-on-background whitespace-nowrap\">\n <span class=\"group inline-flex\">\n {{ column.label }}\n @if (column.sortable) {\n @switch (getSortDirection(column.sort?.field || column.key) | async)\n {\n @case('desc') {\n <span (click)=\"onUpdateSort(column.sort?.field || column.key, 'asc')\"\n class=\"ml-2 flex-none rounded text-light-on-inactive dark:text-dark-on-inactive\">\n <svg class=\"size-5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n data-slot=\"icon\">\n <path fill-rule=\"evenodd\"\n d=\"M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n @case('asc') {\n <span (click)=\"onUpdateSort(column.sort?.field || column.key, 'desc')\"\n class=\"ml-2 flex-none rounded text-light-on-inactive dark:text-dark-on-inactive\">\n <svg class=\"size-5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n data-slot=\"icon\">\n <path fill-rule=\"evenodd\"\n d=\"M14.78 11.78a.75.75 0 0 1-1.06 0L10 8.06l-3.72 3.72a.75.75 0 1 1-1.06-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06Z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n @default {\n <span (click)=\"onUpdateSort(column.sort?.field || column.key, 'asc')\"\n class=\"invisible ml-2 flex-none rounded text-light-on-inactive dark:text-dark-on-inactive group-hover:visible group-focus:visible\">\n <svg class=\"size-5\"\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n data-slot=\"icon\">\n <path fill-rule=\"evenodd\"\n d=\"M14.78 11.78a.75.75 0 0 1-1.06 0L10 8.06l-3.72 3.72a.75.75 0 1 1-1.06-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.75.75 0 0 1 0 1.06Z\"\n clip-rule=\"evenodd\" />\n </svg>\n </span>\n }\n }\n }\n </span>\n </th>\n }\n }\n </tr>\n </thead>\n }\n <tbody class=\"overflow-scroll\">\n @for (row of rows | async; track row['id']; let lastRow = $last) {\n <tr class=\"border-t border-light-inactive dark:border-dark-inactive {{ row.bgColor || '' }}\"\n (click)=\"onRowClicked(row)\"\n (dblclick)=\"onRowDblClicked(row)\"\n [ngClass]=\"{'rounded-b-lg': lastRow && (lastEvaluatedKey | async) === null, 'even:bg-light-alternative dark:even:bg-dark-alternative odd:bg-light-background dark:odd:bg-dark-background': !row.bgColor }\"\n [ngStyle]=\"{ 'background-color': row.bgColor || '' }\">\n @for (column of columns; track column.key) {\n @if (!column.hidden || !(column.hidden | async)) {\n <td class=\"relative overflow-visible {{ column.align || '' }} whitespace-nowrap px-3 text-sm text-light-on-background dark:text-dark-on-background\"\n [ngClass]=\"{\n 'first:rounded-bl-lg last:rounded-br-lg': lastRow && (lastEvaluatedKey | async) === null,\n 'text-wrap': row.isExpanded && column.type !== 'custom',\n 'overflow-x-hidden text-ellipsis' : !row.isExpanded && column.type !== 'custom',\n 'py-2': column.type === 'custom',\n 'py-4': column.type !== 'custom'\n }\">\n @if (column.type === 'custom') {\n @if (column.customRenderTemplate) {\n <ng-container [ngTemplateOutlet]=\"customTemplates[column.customRenderTemplate]\"\n [ngTemplateOutletContext]=\"{ $implicit: row, column: column }\"></ng-container>\n }\n }\n @else {\n {{ getColumnValue(row, column) | async }}\n }\n </td>\n }\n }\n </tr>\n\n @if (row.isExpanded && expandedTemplate) {\n <tr>\n <td [attr.colspan]=\"columns.length\">\n </td>\n </tr>\n <tr class=\"even:bg-light-alternative dark:even:bg-dark-alternative odd:bg-light-background dark:odd:bg-dark-background\">\n <td [attr.colspan]=\"columns.length\"\n class=\"whitespace-nowrap px-3 pb-4 text-sm text-center\">\n <ng-container [ngTemplateOutlet]=\"expandedTemplate\"\n [ngTemplateOutletContext]=\"{ $implicit: row }\"></ng-container>\n </td>\n </tr>\n }\n\n @if (lastRow && (lastEvaluatedKey | async) && !(isLoading | async) && useLoadMore) {\n <tr #loadMoreRow \n class=\"border-t border-light-inactive dark:border-dark-inactive bg-light-background dark:bg-dark-background\"\n haloduckAutoLoad\n [autoLoadEnabled]=\"autoLoad\"\n [autoLoadThreshold]=\"0.1\"\n (autoLoadTrigger)=\"onAutoLoadTriggered()\">\n <td [attr.colspan]=\"columns.length\"\n class=\"whitespace-nowrap px-3 py-4 text-sm text-light-on-background dark:text-dark-on-background text-center h-16 bg-light-background dark:bg-dark-background rounded-bl-lg rounded-br-lg\">\n <div (click)=\"onLoadMoreClicked()\"\n class=\"cursor-pointer\">\n {{ 'haloduck.ui.table.Load More...' | transloco }}\n </div>\n </td>\n </tr>\n }\n\n } @empty {\n @if(!(isLoading | async)) {\n <tr>\n <td [attr.colspan]=\"columns.length\"\n class=\"whitespace-nowrap px-3 py-4 text-sm text-light-on-background dark:text-dark-on-background text-center h-16 bg-light-background dark:bg-dark-background rounded-bl-lg rounded-br-lg\">\n {{ 'haloduck.ui.table.No data available.' | transloco }}\n </td>\n </tr>\n }\n }\n\n @if(isLoading | async) {\n @for ( i of [0,1,2,3,4]; track i; let lastRow = $last)\n {\n <tr class=\"bg-light-background dark:bg-dark-background border-t border-light-inactive/50 dark:border-dark-inactive/50\">\n @for (column of columns; track column.key) {\n <td class=\"whitespace-nowrap py-4 pl-4 pr-3 text-sm\"\n [ngClass]=\"{'first:rounded-bl-lg last:rounded-br-lg': lastRow}\">\n <div class=\"h-4 bg-light-inactive/50 dark:bg-dark-inactive/50 rounded-md animate-pulse\"></div>\n </td>\n }\n </tr>\n }\n }\n </tbody>\n </table>\n</div>\n" }]
|
|
3108
|
+
}], ctorParameters: () => [], propDecorators: { loadMoreRowRef: [{
|
|
3109
|
+
type: ViewChild,
|
|
3110
|
+
args: ['loadMoreRow', { read: ElementRef }]
|
|
3111
|
+
}], tableLayout: [{
|
|
3112
|
+
type: Input
|
|
3113
|
+
}], autoLoad: [{
|
|
3098
3114
|
type: Input
|
|
3099
3115
|
}], showHeader: [{
|
|
3100
3116
|
type: Input
|
|
@@ -3124,15 +3140,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImpor
|
|
|
3124
3140
|
type: Output
|
|
3125
3141
|
}], onRowDblClick: [{
|
|
3126
3142
|
type: Output
|
|
3127
|
-
}], loadMoreRow: [{
|
|
3128
|
-
type: ViewChild,
|
|
3129
|
-
args: ['loadMoreRow']
|
|
3130
|
-
}], dataRows: [{
|
|
3131
|
-
type: ViewChildren,
|
|
3132
|
-
args: ['dataRow', { read: ElementRef }]
|
|
3133
|
-
}], scrollContainer: [{
|
|
3134
|
-
type: ViewChild,
|
|
3135
|
-
args: ['scrollContainer', { static: true }]
|
|
3136
3143
|
}] } });
|
|
3137
3144
|
|
|
3138
3145
|
class ToggleComponent {
|
|
@@ -3734,5 +3741,5 @@ const provideHaloduckTransloco = () => provideTranslocoScope({
|
|
|
3734
3741
|
* Generated bundle index. Do not edit.
|
|
3735
3742
|
*/
|
|
3736
3743
|
|
|
3737
|
-
export { AuthenticateComponent, BreadcrumbComponent, ButtonComponent, CalendarComponent, ConfirmDialogService, CopyButtonComponent, DatePickerComponent, DateRangeComponent, DialogService, DrawCanvasComponent, ERROR_NOT_ACCEPTABLE_FILE_TYPE, ERROR_OVER_COUNT, ERROR_OVER_SIZE, ERROR_UPLOAD, FileUploaderComponent, FlipComponent, GroupedDirective, ImageUploaderComponent, ImageViewerComponent, InputComponent, LanguageSelectorComponent, MapToAddressComponent, NotificationComponent, NotificationService, PictureNameComponent, SelectComponent, SelectDropdownComponent, SideMenuComponent, SideMenuItemComponent, StlViewerComponent, TableComponent, TabsComponent, TagInputComponent, TagViewerComponent, ToggleComponent, dateToString, provideHaloduckTransloco };
|
|
3744
|
+
export { AuthenticateComponent, AutoLoadDirective, BreadcrumbComponent, ButtonComponent, CalendarComponent, ConfirmDialogService, CopyButtonComponent, DatePickerComponent, DateRangeComponent, DialogService, DrawCanvasComponent, ERROR_NOT_ACCEPTABLE_FILE_TYPE, ERROR_OVER_COUNT, ERROR_OVER_SIZE, ERROR_UPLOAD, FileUploaderComponent, FlipComponent, GroupedDirective, ImageUploaderComponent, ImageViewerComponent, InputComponent, LanguageSelectorComponent, MapToAddressComponent, NotificationComponent, NotificationService, PictureNameComponent, SelectComponent, SelectDropdownComponent, SideMenuComponent, SideMenuItemComponent, StlViewerComponent, TableComponent, TabsComponent, TagInputComponent, TagViewerComponent, ToggleComponent, dateToString, provideHaloduckTransloco };
|
|
3738
3745
|
//# sourceMappingURL=haloduck-ui.mjs.map
|