@tekus/design-system 5.19.0 → 5.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/checkbox/src/checkbox.component.d.ts +24 -0
- package/components/date-picker/src/date-picker.component.d.ts +112 -87
- package/components/drawer/src/drawer.component.d.ts +36 -9
- package/components/drawer/src/drawer.types.d.ts +5 -2
- package/components/drawer/src/services/drawer.service.d.ts +2 -2
- package/components/modal/src/modal.component.d.ts +86 -67
- package/components/modal/src/modal.types.d.ts +22 -2
- package/components/modal/src/services/modal.service.d.ts +15 -0
- package/components/radio-button/src/radio-button.component.d.ts +33 -3
- package/components/toolbar/src/toolbar.component.d.ts +55 -1
- package/core/types/public-api.d.ts +1 -0
- package/core/types/src/interception/index.d.ts +1 -0
- package/core/types/src/interception/interception.types.d.ts +21 -0
- package/fesm2022/tekus-design-system-components-checkbox.mjs +24 -6
- package/fesm2022/tekus-design-system-components-checkbox.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-date-picker.mjs +164 -165
- package/fesm2022/tekus-design-system-components-date-picker.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-drawer.mjs +130 -22
- package/fesm2022/tekus-design-system-components-drawer.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-modal.mjs +190 -89
- package/fesm2022/tekus-design-system-components-modal.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-radio-button.mjs +53 -18
- package/fesm2022/tekus-design-system-components-radio-button.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-toolbar.mjs +72 -4
- package/fesm2022/tekus-design-system-components-toolbar.mjs.map +1 -1
- package/package.json +9 -9
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { input, computed, model, EventEmitter, Component, createComponent, Injectable } from '@angular/core';
|
|
3
|
-
import { NgComponentOutlet } from '@angular/common';
|
|
2
|
+
import { viewChild, ViewContainerRef, input, computed, model, EventEmitter, effect, untracked, afterRender, Component, createComponent, Injectable } from '@angular/core';
|
|
4
3
|
import { ButtonComponent } from '@tekus/design-system/components/button';
|
|
5
4
|
import * as i1 from 'primeng/drawer';
|
|
6
5
|
import { DrawerModule } from 'primeng/drawer';
|
|
@@ -39,13 +38,17 @@ import { Subject } from 'rxjs';
|
|
|
39
38
|
* console.log('Drawer closed with value:', result);
|
|
40
39
|
* });
|
|
41
40
|
* ```
|
|
41
|
+
* Modernized for Angular 19 with 100% synchronous Signal-based closing interception.
|
|
42
42
|
*/
|
|
43
43
|
class DrawerComponent {
|
|
44
44
|
constructor(elementRef) {
|
|
45
45
|
this.elementRef = elementRef;
|
|
46
|
+
this.contentHost = viewChild('contentHost', {
|
|
47
|
+
read: ViewContainerRef,
|
|
48
|
+
});
|
|
46
49
|
/** The required title displayed at the top left of the drawer header */
|
|
47
50
|
this.title = input.required();
|
|
48
|
-
/** The main content of the drawer */
|
|
51
|
+
/** The main content of the drawer. Can be a string or a Component Type. */
|
|
49
52
|
this.content = input(null);
|
|
50
53
|
/** Optional header action button (displayed before close button) */
|
|
51
54
|
this.headerAction = input(null);
|
|
@@ -55,6 +58,10 @@ class DrawerComponent {
|
|
|
55
58
|
this.closable = input(true);
|
|
56
59
|
/** Whether clicking the mask closes the drawer */
|
|
57
60
|
this.dismissible = input(true);
|
|
61
|
+
/** Optional data to be passed as inputs to the dynamic component. */
|
|
62
|
+
this.data = input({});
|
|
63
|
+
/** Optional interceptor called before the drawer closes. */
|
|
64
|
+
this.interceptor = input(undefined);
|
|
58
65
|
this.isContentString = computed(() => typeof this.content() === 'string');
|
|
59
66
|
this.hasHeaderAction = computed(() => this.headerAction() != null);
|
|
60
67
|
/** Computed: drawer width (responsive) and max-width based on `size`. Always right position. */
|
|
@@ -68,49 +75,146 @@ class DrawerComponent {
|
|
|
68
75
|
});
|
|
69
76
|
/** Visibility flag. Use model for two-way binding when using drawer in template. */
|
|
70
77
|
this.isOpened = model(false);
|
|
78
|
+
/** Whether the drawer content has a scrollbar */
|
|
79
|
+
this.hasScroll = false;
|
|
71
80
|
/** Emits when the drawer closes, passing the return value from header action or null */
|
|
72
81
|
this.onClose = new EventEmitter();
|
|
73
82
|
this.alreadyEmitted = false;
|
|
74
83
|
this.returnValueOnClose = null;
|
|
84
|
+
/**
|
|
85
|
+
* @summary Orchestrates the reactive dynamic lifecycle.
|
|
86
|
+
*/
|
|
87
|
+
effect(() => {
|
|
88
|
+
const opened = this.isOpened();
|
|
89
|
+
const host = this.contentHost();
|
|
90
|
+
untracked(() => {
|
|
91
|
+
if (opened && host) {
|
|
92
|
+
this.attachDynamicContent();
|
|
93
|
+
}
|
|
94
|
+
else if (!opened) {
|
|
95
|
+
this.detachDynamicContent();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
effect(() => {
|
|
100
|
+
const currentData = this.data();
|
|
101
|
+
untracked(() => this.syncDynamicInputs(currentData));
|
|
102
|
+
});
|
|
103
|
+
afterRender(() => {
|
|
104
|
+
this.checkScroll();
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
ngOnDestroy() {
|
|
108
|
+
this.detachDynamicContent();
|
|
109
|
+
}
|
|
110
|
+
attachDynamicContent() {
|
|
111
|
+
const type = this.content();
|
|
112
|
+
const host = this.contentHost();
|
|
113
|
+
if (!type || typeof type === 'string' || !host)
|
|
114
|
+
return;
|
|
115
|
+
this.detachDynamicContent();
|
|
116
|
+
this.componentRef = host.createComponent(type);
|
|
117
|
+
this.syncDynamicInputs(this.data());
|
|
118
|
+
}
|
|
119
|
+
syncDynamicInputs(data) {
|
|
120
|
+
if (!this.componentRef)
|
|
121
|
+
return;
|
|
122
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
123
|
+
this.componentRef?.setInput(key, value);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
detachDynamicContent() {
|
|
127
|
+
if (this.componentRef) {
|
|
128
|
+
this.componentRef.destroy();
|
|
129
|
+
this.componentRef = undefined;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Checks if the drawer content has a scrollbar and updates `hasScroll` state.
|
|
134
|
+
*/
|
|
135
|
+
checkScroll() {
|
|
136
|
+
const contentEl = this.elementRef.nativeElement.querySelector('.p-drawer-content');
|
|
137
|
+
if (contentEl) {
|
|
138
|
+
this.hasScroll = contentEl.scrollHeight > contentEl.clientHeight;
|
|
139
|
+
}
|
|
75
140
|
}
|
|
76
141
|
/** Opens the drawer */
|
|
77
142
|
open() {
|
|
78
143
|
this.isOpened.set(true);
|
|
79
|
-
this.
|
|
80
|
-
this.returnValueOnClose = null;
|
|
144
|
+
this.resetClosureState();
|
|
81
145
|
}
|
|
82
|
-
/**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
146
|
+
/**
|
|
147
|
+
* @summary Main entry point for closure requests.
|
|
148
|
+
* @returns true if closure was executed.
|
|
149
|
+
*/
|
|
150
|
+
tryClose(returnValue = null) {
|
|
151
|
+
if (this.canExecuteClosure()) {
|
|
152
|
+
this.executeClosure(returnValue, arguments.length > 0);
|
|
153
|
+
return true;
|
|
86
154
|
}
|
|
87
155
|
else {
|
|
88
|
-
this.
|
|
156
|
+
const instance = this.componentRef?.instance;
|
|
157
|
+
instance?.onBlockedClose?.();
|
|
158
|
+
return false;
|
|
89
159
|
}
|
|
90
|
-
this.alreadyEmitted = false;
|
|
91
|
-
this.returnValueOnClose = null;
|
|
92
160
|
}
|
|
93
|
-
|
|
94
|
-
|
|
161
|
+
canExecuteClosure() {
|
|
162
|
+
const instance = this.componentRef?.instance;
|
|
163
|
+
const canClose = instance?.canClose ? instance.canClose() : true;
|
|
164
|
+
if (!canClose)
|
|
165
|
+
return false;
|
|
166
|
+
const configInterceptor = this.interceptor();
|
|
167
|
+
if (configInterceptor && !configInterceptor())
|
|
168
|
+
return false;
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
executeClosure(returnValue, hasReturnValue) {
|
|
172
|
+
if (hasReturnValue) {
|
|
173
|
+
this.alreadyEmitted = true;
|
|
174
|
+
this.returnValueOnClose = returnValue;
|
|
175
|
+
}
|
|
95
176
|
this.isOpened.set(false);
|
|
96
177
|
}
|
|
178
|
+
/** Handles external visibility changes (from p-drawer close button or mask) */
|
|
179
|
+
onVisibleChange(visible) {
|
|
180
|
+
if (!visible) {
|
|
181
|
+
const closed = this.tryClose();
|
|
182
|
+
if (!closed) {
|
|
183
|
+
this.isOpened.set(true);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/** Closes the drawer and emits onClose */
|
|
188
|
+
handleClose() {
|
|
189
|
+
if (this.isOpened()) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const valueToEmit = this.alreadyEmitted ? this.returnValueOnClose : null;
|
|
193
|
+
this.onClose.emit(valueToEmit);
|
|
194
|
+
this.resetClosureState();
|
|
195
|
+
}
|
|
196
|
+
/** Forcefully closes the drawer without checks */
|
|
197
|
+
close() {
|
|
198
|
+
this.tryClose();
|
|
199
|
+
}
|
|
97
200
|
/**
|
|
98
201
|
* Handles header action button click.
|
|
99
|
-
* Executes the action callback, emits onClose with the provided returnValue, then closes the drawer.
|
|
100
202
|
*/
|
|
101
203
|
handleHeaderAction(action, returnValue) {
|
|
102
204
|
if (action)
|
|
103
205
|
action();
|
|
104
|
-
this.
|
|
105
|
-
|
|
106
|
-
|
|
206
|
+
this.tryClose(returnValue);
|
|
207
|
+
}
|
|
208
|
+
resetClosureState() {
|
|
209
|
+
this.alreadyEmitted = false;
|
|
210
|
+
this.returnValueOnClose = null;
|
|
107
211
|
}
|
|
108
212
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: DrawerComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
109
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: DrawerComponent, isStandalone: true, selector: "tk-drawer", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, headerAction: { classPropertyName: "headerAction", publicName: "headerAction", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, isOpened: { classPropertyName: "isOpened", publicName: "isOpened", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpened: "isOpenedChange" }, ngImport: i0, template: "<p-drawer\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"
|
|
213
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.18", type: DrawerComponent, isStandalone: true, selector: "tk-drawer", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: true, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, headerAction: { classPropertyName: "headerAction", publicName: "headerAction", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, closable: { classPropertyName: "closable", publicName: "closable", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, interceptor: { classPropertyName: "interceptor", publicName: "interceptor", isSignal: true, isRequired: false, transformFunction: null }, isOpened: { classPropertyName: "isOpened", publicName: "isOpened", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isOpened: "isOpenedChange" }, viewQueries: [{ propertyName: "contentHost", first: true, predicate: ["contentHost"], descendants: true, read: ViewContainerRef, isSignal: true }], ngImport: i0, template: "<p-drawer\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"onVisibleChange($event)\"\n [closable]=\"closable()\"\n [dismissible]=\"dismissible()\"\n [closeOnEscape]=\"true\"\n position=\"right\"\n [style]=\"drawerStyle()\"\n [styleClass]=\"'tk-drawer'\"\n [class.tk-drawer--has-scroll]=\"hasScroll\"\n (onHide)=\"handleClose()\">\n <ng-template pTemplate=\"header\">\n <div class=\"tk-drawer__header\">\n <h2 class=\"tk-drawer__title\" [title]=\"title()\">{{ title() }}</h2>\n @if (hasHeaderAction()) {\n <div class=\"tk-drawer__actions\">\n <tk-button\n [label]=\"headerAction()!.label\"\n [severity]=\"headerAction()!.severity\"\n [variant]=\"headerAction()!.variant\"\n (clicked)=\"\n handleHeaderAction(\n headerAction()!.action,\n headerAction()!.returnValue\n )\n \" />\n </div>\n }\n </div>\n </ng-template>\n\n <section class=\"tk-drawer__content\">\n @if (content()) {\n @if (isContentString()) {\n <p [innerHTML]=\"content()\"></p>\n } @else {\n <ng-template #contentHost></ng-template>\n }\n }\n </section>\n</p-drawer>\n", styles: [":host ::ng-deep .tk-drawer{max-height:100vh;display:flex;flex-direction:column}:host ::ng-deep .tk-drawer__content{flex:1;overflow-y:auto;padding:var(--tk-spacing-paddingX-m, 1.5rem)}:host ::ng-deep .p-drawer-content{overflow-y:auto;display:flex;flex-direction:column;flex:1}:host ::ng-deep .p-drawer-close-button{color:var(--tk-color-base-surface-500, #8a8a8b)}:host ::ng-deep .p-drawer-close-button:hover{background:var(--tk-color-base-surface-100, #f0f0f0)!important;color:var(--tk-color-base-surface-500, #8a8a8b)}.tk-drawer--has-scroll .p-drawer-header{border-bottom:1px solid var(--tk-color-base-surface-200, #e2e8f0);box-shadow:0 2px 4px #00000005}.tk-drawer__header{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:var(--tk-spacing-base-100, 1rem);flex-shrink:0;width:calc(100% - var(--tk-spacing-base-250, 2.5rem))}.tk-drawer__title{margin:0;font-size:var(--tk-font-size-headers-s, 1.125rem);font-weight:var(--tk-font-weight-600, 600);color:var(--tk-color-text-default, #212121);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}.tk-drawer__actions{display:flex;flex-direction:row;align-items:center;gap:var(--tk-spacing-base-50, .5rem);flex-shrink:0;padding-right:var(--tk-spacing-paddingX-xs, .25rem)}\n"], dependencies: [{ kind: "ngmodule", type: DrawerModule }, { kind: "component", type: i1.Drawer, selector: "p-drawer", inputs: ["appendTo", "blockScroll", "style", "styleClass", "ariaCloseLabel", "autoZIndex", "baseZIndex", "modal", "closeButtonProps", "dismissible", "showCloseIcon", "closeOnEscape", "transitionOptions", "visible", "position", "fullScreen", "header", "maskStyle", "closable"], outputs: ["onShow", "onHide", "visibleChange"] }, { kind: "directive", type: i2.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "component", type: ButtonComponent, selector: "tk-button", inputs: ["label", "disabled", "type", "severity", "variant", "link", "icon", "tooltipText"], outputs: ["clicked"] }] }); }
|
|
110
214
|
}
|
|
111
215
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImport: i0, type: DrawerComponent, decorators: [{
|
|
112
216
|
type: Component,
|
|
113
|
-
args: [{ selector: 'tk-drawer', standalone: true, imports: [DrawerModule, ButtonComponent
|
|
217
|
+
args: [{ selector: 'tk-drawer', standalone: true, imports: [DrawerModule, ButtonComponent], template: "<p-drawer\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"onVisibleChange($event)\"\n [closable]=\"closable()\"\n [dismissible]=\"dismissible()\"\n [closeOnEscape]=\"true\"\n position=\"right\"\n [style]=\"drawerStyle()\"\n [styleClass]=\"'tk-drawer'\"\n [class.tk-drawer--has-scroll]=\"hasScroll\"\n (onHide)=\"handleClose()\">\n <ng-template pTemplate=\"header\">\n <div class=\"tk-drawer__header\">\n <h2 class=\"tk-drawer__title\" [title]=\"title()\">{{ title() }}</h2>\n @if (hasHeaderAction()) {\n <div class=\"tk-drawer__actions\">\n <tk-button\n [label]=\"headerAction()!.label\"\n [severity]=\"headerAction()!.severity\"\n [variant]=\"headerAction()!.variant\"\n (clicked)=\"\n handleHeaderAction(\n headerAction()!.action,\n headerAction()!.returnValue\n )\n \" />\n </div>\n }\n </div>\n </ng-template>\n\n <section class=\"tk-drawer__content\">\n @if (content()) {\n @if (isContentString()) {\n <p [innerHTML]=\"content()\"></p>\n } @else {\n <ng-template #contentHost></ng-template>\n }\n }\n </section>\n</p-drawer>\n", styles: [":host ::ng-deep .tk-drawer{max-height:100vh;display:flex;flex-direction:column}:host ::ng-deep .tk-drawer__content{flex:1;overflow-y:auto;padding:var(--tk-spacing-paddingX-m, 1.5rem)}:host ::ng-deep .p-drawer-content{overflow-y:auto;display:flex;flex-direction:column;flex:1}:host ::ng-deep .p-drawer-close-button{color:var(--tk-color-base-surface-500, #8a8a8b)}:host ::ng-deep .p-drawer-close-button:hover{background:var(--tk-color-base-surface-100, #f0f0f0)!important;color:var(--tk-color-base-surface-500, #8a8a8b)}.tk-drawer--has-scroll .p-drawer-header{border-bottom:1px solid var(--tk-color-base-surface-200, #e2e8f0);box-shadow:0 2px 4px #00000005}.tk-drawer__header{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:var(--tk-spacing-base-100, 1rem);flex-shrink:0;width:calc(100% - var(--tk-spacing-base-250, 2.5rem))}.tk-drawer__title{margin:0;font-size:var(--tk-font-size-headers-s, 1.125rem);font-weight:var(--tk-font-weight-600, 600);color:var(--tk-color-text-default, #212121);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0}.tk-drawer__actions{display:flex;flex-direction:row;align-items:center;gap:var(--tk-spacing-base-50, .5rem);flex-shrink:0;padding-right:var(--tk-spacing-paddingX-xs, .25rem)}\n"] }]
|
|
114
218
|
}], ctorParameters: () => [{ type: i0.ElementRef }] });
|
|
115
219
|
|
|
116
220
|
class DrawerService {
|
|
@@ -144,13 +248,17 @@ class DrawerService {
|
|
|
144
248
|
componentRef.setInput('size', config.size ?? 'small');
|
|
145
249
|
componentRef.setInput('closable', config.closable ?? true);
|
|
146
250
|
componentRef.setInput('dismissible', config.dismissible ?? true);
|
|
251
|
+
componentRef.setInput('data', config.data ?? {});
|
|
252
|
+
componentRef.setInput('interceptor', config.interceptor ?? undefined);
|
|
147
253
|
const close$ = new Subject();
|
|
148
|
-
componentRef.instance.onClose.subscribe(
|
|
254
|
+
componentRef.instance.onClose.subscribe(value => {
|
|
149
255
|
close$.next(value);
|
|
150
256
|
close$.complete();
|
|
151
257
|
this.appRef.detachView(componentRef.hostView);
|
|
152
258
|
componentRef.destroy();
|
|
153
|
-
this.drawerRef
|
|
259
|
+
if (this.drawerRef === componentRef) {
|
|
260
|
+
this.drawerRef = null;
|
|
261
|
+
}
|
|
154
262
|
});
|
|
155
263
|
componentRef.instance.open();
|
|
156
264
|
this.drawerRef = componentRef;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tekus-design-system-components-drawer.mjs","sources":["../../../projects/design-system/components/drawer/src/drawer.component.ts","../../../projects/design-system/components/drawer/src/drawer.component.html","../../../projects/design-system/components/drawer/src/services/drawer.service.ts","../../../projects/design-system/components/drawer/tekus-design-system-components-drawer.ts"],"sourcesContent":["import {\n Component,\n computed,\n input,\n model,\n EventEmitter,\n Type,\n ElementRef,\n} from '@angular/core';\nimport { NgComponentOutlet } from '@angular/common';\nimport { ButtonComponent } from '@tekus/design-system/components/button';\nimport { DrawerModule } from 'primeng/drawer';\nimport { DrawerHeaderAction, DrawerSizeType } from './drawer.types';\n\n/**\n * @component DrawerComponent\n * @description\n * A programmatically controlled drawer overlay used for displaying dynamic content,\n * titles, and header actions. The drawer is opened through a service with a configuration object,\n * similar to tk-modal.\n *\n * This component supports:\n * - Required title with ellipsis for long text.\n * - Optional header action button + close button.\n * - Content as string or component.\n * - Position: always right.\n * - Sizes: small (500px), large (1024px).\n * - Closable and dismissible mask behavior.\n *\n * @usage\n * ### Open a drawer from TypeScript using the drawer service\n * ```ts\n * this.drawerService.open({\n * title: 'Drawer name',\n * content: 'Content text drawer example',\n * headerAction: {\n * label: 'Action',\n * severity: 'primary',\n * action: () => console.log('Action clicked'),\n * returnValue: true,\n * },\n * size: 'small',\n * }).subscribe((result) => {\n * console.log('Drawer closed with value:', result);\n * });\n * ```\n */\n@Component({\n selector: 'tk-drawer',\n standalone: true,\n imports: [DrawerModule, ButtonComponent, NgComponentOutlet],\n templateUrl: './drawer.component.html',\n styleUrls: ['./drawer.component.scss'],\n})\nexport class DrawerComponent {\n constructor(private readonly elementRef: ElementRef) {}\n\n /** The required title displayed at the top left of the drawer header */\n title = input.required<string>();\n /** The main content of the drawer */\n content = input<string | Type<unknown> | null>(null);\n /** Optional header action button (displayed before close button) */\n headerAction = input<DrawerHeaderAction | null>(null);\n /** Drawer size: 'small' (500px), 'large' (1024px) */\n size = input<DrawerSizeType>('small');\n /** Whether the drawer can be closed by the user via close button */\n closable = input<boolean>(true);\n /** Whether clicking the mask closes the drawer */\n dismissible = input<boolean>(true);\n\n isContentString = computed(() => typeof this.content() === 'string');\n hasHeaderAction = computed(() => this.headerAction() != null);\n\n /** Computed: drawer width (responsive) and max-width based on `size`. Always right position. */\n drawerStyle = computed(() => {\n const sz = this.size();\n const maxWidth = sz === 'large' ? '1024px' : '500px';\n return {\n width: 'calc(100vw - 1rem)',\n maxWidth,\n };\n });\n\n /** Visibility flag. Use model for two-way binding when using drawer in template. */\n isOpened = model<boolean>(false);\n\n /** Emits when the drawer closes, passing the return value from header action or null */\n readonly onClose = new EventEmitter<unknown>();\n private alreadyEmitted = false;\n private returnValueOnClose: unknown = null;\n\n /** Opens the drawer */\n open() {\n this.isOpened.set(true);\n this.alreadyEmitted = false;\n this.returnValueOnClose = null;\n }\n\n /** Closes the drawer and emits onClose */\n handleClose() {\n if (!this.alreadyEmitted) {\n this.onClose.emit(null);\n } else {\n this.onClose.emit(this.returnValueOnClose);\n }\n this.alreadyEmitted = false;\n this.returnValueOnClose = null;\n }\n\n /** Closes the drawer without emitting an event */\n close() {\n this.isOpened.set(false);\n }\n\n /**\n * Handles header action button click.\n * Executes the action callback, emits onClose with the provided returnValue, then closes the drawer.\n */\n handleHeaderAction(\n action: (() => void) | undefined,\n returnValue: unknown\n ): void {\n if (action) action();\n this.alreadyEmitted = true;\n this.returnValueOnClose = returnValue;\n this.isOpened.set(false);\n }\n}\n","<p-drawer\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"isOpened.set($event)\"\n [closable]=\"closable()\"\n [dismissible]=\"dismissible()\"\n [closeOnEscape]=\"true\"\n position=\"right\"\n [style]=\"drawerStyle()\"\n [styleClass]=\"'tk-drawer'\"\n (onHide)=\"handleClose()\"\n>\n <ng-template pTemplate=\"header\">\n <div class=\"tk-drawer__header\">\n <h2 class=\"tk-drawer__title\" [title]=\"title()\">{{ title() }}</h2>\n @if (hasHeaderAction()) {\n <div class=\"tk-drawer__actions\">\n <tk-button\n [label]=\"headerAction()!.label\"\n [severity]=\"headerAction()!.severity\"\n [variant]=\"headerAction()!.variant\"\n (clicked)=\"handleHeaderAction(headerAction()!.action, headerAction()!.returnValue)\"\n />\n </div>\n }\n </div>\n </ng-template>\n\n <section class=\"tk-drawer__content\">\n @if (content()) {\n @if (isContentString()) {\n <p [innerHTML]=\"content()\"></p>\n } @else {\n <ng-container *ngComponentOutlet=\"$any(content())\"></ng-container>\n }\n }\n </section>\n</p-drawer>\n","import {\n Injectable,\n ApplicationRef,\n ComponentRef,\n createComponent,\n EmbeddedViewRef,\n} from '@angular/core';\nimport { DrawerComponent } from '../drawer.component';\nimport { Observable, Subject } from 'rxjs';\nimport { DrawerConfig } from '../drawer.types';\n\n@Injectable({ providedIn: 'root' })\nexport class DrawerService {\n private drawerRef: ComponentRef<DrawerComponent> | null = null;\n\n constructor(private readonly appRef: ApplicationRef) {}\n\n get _drawerRefForTesting(): ComponentRef<DrawerComponent> | null {\n return this.drawerRef;\n }\n set _drawerRefForTesting(ref: ComponentRef<DrawerComponent> | null) {\n this.drawerRef = ref;\n }\n\n open(config: DrawerConfig): Observable<unknown> {\n if (this.drawerRef) {\n this.drawerRef.instance.close();\n this.appRef.detachView(this.drawerRef.hostView);\n this.drawerRef.destroy();\n this.drawerRef = null;\n }\n\n const componentRef = createComponent(DrawerComponent, {\n environmentInjector: this.appRef.injector,\n });\n\n this.appRef.attachView(componentRef.hostView);\n\n const domElem = (componentRef.hostView as EmbeddedViewRef<unknown>)\n .rootNodes[0] as HTMLElement;\n document.body.appendChild(domElem);\n\n componentRef.setInput('title', config.title);\n componentRef.setInput('content', config.content ?? null);\n componentRef.setInput('headerAction', config.headerAction ?? null);\n componentRef.setInput('size', config.size ?? 'small');\n componentRef.setInput('closable', config.closable ?? true);\n componentRef.setInput('dismissible', config.dismissible ?? true);\n\n const close$ = new Subject<unknown>();\n\n componentRef.instance.onClose.subscribe((value) => {\n close$.next(value);\n close$.complete();\n\n this.appRef.detachView(componentRef.hostView);\n componentRef.destroy();\n this.drawerRef = null;\n });\n\n componentRef.instance.open();\n this.drawerRef = componentRef;\n\n return close$.asObservable();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tekus-design-system-components-drawer.mjs","sources":["../../../projects/design-system/components/drawer/src/drawer.component.ts","../../../projects/design-system/components/drawer/src/drawer.component.html","../../../projects/design-system/components/drawer/src/services/drawer.service.ts","../../../projects/design-system/components/drawer/tekus-design-system-components-drawer.ts"],"sourcesContent":["import {\n Component,\n computed,\n input,\n model,\n EventEmitter,\n Type,\n ElementRef,\n ViewContainerRef,\n viewChild,\n ComponentRef,\n effect,\n untracked,\n OnDestroy,\n afterRender,\n} from '@angular/core';\nimport { ButtonComponent } from '@tekus/design-system/components/button';\nimport { DrawerModule } from 'primeng/drawer';\nimport { DrawerHeaderAction, DrawerSizeType } from './drawer.types';\nimport {\n TkCanClose,\n TkCloseInterceptor,\n} from '@tekus/design-system/core/types';\n\n/**\n * @component DrawerComponent\n * @description\n * A programmatically controlled drawer overlay used for displaying dynamic content,\n * titles, and header actions. The drawer is opened through a service with a configuration object,\n * similar to tk-modal.\n *\n * This component supports:\n * - Required title with ellipsis for long text.\n * - Optional header action button + close button.\n * - Content as string or component.\n * - Position: always right.\n * - Sizes: small (500px), large (1024px).\n * - Closable and dismissible mask behavior.\n *\n * @usage\n * ### Open a drawer from TypeScript using the drawer service\n * ```ts\n * this.drawerService.open({\n * title: 'Drawer name',\n * content: 'Content text drawer example',\n * headerAction: {\n * label: 'Action',\n * severity: 'primary',\n * action: () => console.log('Action clicked'),\n * returnValue: true,\n * },\n * size: 'small',\n * }).subscribe((result) => {\n * console.log('Drawer closed with value:', result);\n * });\n * ```\n * Modernized for Angular 19 with 100% synchronous Signal-based closing interception.\n */\n@Component({\n selector: 'tk-drawer',\n standalone: true,\n imports: [DrawerModule, ButtonComponent],\n templateUrl: './drawer.component.html',\n styleUrls: ['./drawer.component.scss'],\n})\nexport class DrawerComponent<T = unknown> implements OnDestroy {\n private readonly contentHost = viewChild('contentHost', {\n read: ViewContainerRef,\n });\n private componentRef?: ComponentRef<T>;\n\n /** The required title displayed at the top left of the drawer header */\n title = input.required<string>();\n\n /** The main content of the drawer. Can be a string or a Component Type. */\n content = input<string | Type<T> | null>(null);\n\n /** Optional header action button (displayed before close button) */\n headerAction = input<DrawerHeaderAction | null>(null);\n\n /** Drawer size: 'small' (500px), 'large' (1024px) */\n size = input<DrawerSizeType>('small');\n\n /** Whether the drawer can be closed by the user via close button */\n closable = input<boolean>(true);\n\n /** Whether clicking the mask closes the drawer */\n dismissible = input<boolean>(true);\n\n /** Optional data to be passed as inputs to the dynamic component. */\n data = input<Partial<T>>({});\n\n /** Optional interceptor called before the drawer closes. */\n interceptor = input<TkCloseInterceptor | undefined>(undefined);\n\n isContentString = computed(() => typeof this.content() === 'string');\n hasHeaderAction = computed(() => this.headerAction() != null);\n\n /** Computed: drawer width (responsive) and max-width based on `size`. Always right position. */\n drawerStyle = computed(() => {\n const sz = this.size();\n const maxWidth = sz === 'large' ? '1024px' : '500px';\n return {\n width: 'calc(100vw - 1rem)',\n maxWidth,\n };\n });\n\n /** Visibility flag. Use model for two-way binding when using drawer in template. */\n isOpened = model<boolean>(false);\n\n /** Whether the drawer content has a scrollbar */\n hasScroll = false;\n\n /** Emits when the drawer closes, passing the return value from header action or null */\n readonly onClose = new EventEmitter<unknown>();\n private alreadyEmitted = false;\n private returnValueOnClose: unknown = null;\n\n constructor(private readonly elementRef: ElementRef) {\n /**\n * @summary Orchestrates the reactive dynamic lifecycle.\n */\n effect(() => {\n const opened = this.isOpened();\n const host = this.contentHost();\n\n untracked(() => {\n if (opened && host) {\n this.attachDynamicContent();\n } else if (!opened) {\n this.detachDynamicContent();\n }\n });\n });\n\n effect(() => {\n const currentData = this.data();\n untracked(() => this.syncDynamicInputs(currentData));\n });\n\n afterRender(() => {\n this.checkScroll();\n });\n }\n\n ngOnDestroy(): void {\n this.detachDynamicContent();\n }\n\n private attachDynamicContent(): void {\n const type = this.content();\n const host = this.contentHost();\n\n if (!type || typeof type === 'string' || !host) return;\n this.detachDynamicContent();\n this.componentRef = host.createComponent(type);\n this.syncDynamicInputs(this.data());\n }\n\n private syncDynamicInputs(data: Partial<T>): void {\n if (!this.componentRef) return;\n Object.entries(data).forEach(([key, value]) => {\n this.componentRef?.setInput(key, value);\n });\n }\n\n private detachDynamicContent(): void {\n if (this.componentRef) {\n this.componentRef.destroy();\n this.componentRef = undefined;\n }\n }\n\n /**\n * Checks if the drawer content has a scrollbar and updates `hasScroll` state.\n */\n checkScroll(): void {\n const contentEl =\n this.elementRef.nativeElement.querySelector('.p-drawer-content');\n if (contentEl) {\n this.hasScroll = contentEl.scrollHeight > contentEl.clientHeight;\n }\n }\n\n /** Opens the drawer */\n open(): void {\n this.isOpened.set(true);\n this.resetClosureState();\n }\n\n /**\n * @summary Main entry point for closure requests.\n * @returns true if closure was executed.\n */\n tryClose(returnValue: unknown = null): boolean {\n if (this.canExecuteClosure()) {\n this.executeClosure(returnValue, arguments.length > 0);\n return true;\n } else {\n const instance = this.componentRef?.instance as TkCanClose | undefined;\n instance?.onBlockedClose?.();\n return false;\n }\n }\n\n private canExecuteClosure(): boolean {\n const instance = this.componentRef?.instance as TkCanClose | undefined;\n const canClose = instance?.canClose ? instance.canClose() : true;\n if (!canClose) return false;\n\n const configInterceptor = this.interceptor();\n if (configInterceptor && !configInterceptor()) return false;\n\n return true;\n }\n\n private executeClosure(returnValue: unknown, hasReturnValue: boolean): void {\n if (hasReturnValue) {\n this.alreadyEmitted = true;\n this.returnValueOnClose = returnValue;\n }\n this.isOpened.set(false);\n }\n\n /** Handles external visibility changes (from p-drawer close button or mask) */\n onVisibleChange(visible: boolean): void {\n if (!visible) {\n const closed = this.tryClose();\n\n if (!closed) {\n this.isOpened.set(true);\n }\n }\n }\n\n /** Closes the drawer and emits onClose */\n handleClose(): void {\n if (this.isOpened()) {\n return;\n }\n const valueToEmit = this.alreadyEmitted ? this.returnValueOnClose : null;\n this.onClose.emit(valueToEmit);\n this.resetClosureState();\n }\n\n /** Forcefully closes the drawer without checks */\n close(): void {\n this.tryClose();\n }\n\n /**\n * Handles header action button click.\n */\n handleHeaderAction(\n action: (() => void) | undefined,\n returnValue: unknown\n ): void {\n if (action) action();\n this.tryClose(returnValue);\n }\n\n private resetClosureState(): void {\n this.alreadyEmitted = false;\n this.returnValueOnClose = null;\n }\n}\n","<p-drawer\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"onVisibleChange($event)\"\n [closable]=\"closable()\"\n [dismissible]=\"dismissible()\"\n [closeOnEscape]=\"true\"\n position=\"right\"\n [style]=\"drawerStyle()\"\n [styleClass]=\"'tk-drawer'\"\n [class.tk-drawer--has-scroll]=\"hasScroll\"\n (onHide)=\"handleClose()\">\n <ng-template pTemplate=\"header\">\n <div class=\"tk-drawer__header\">\n <h2 class=\"tk-drawer__title\" [title]=\"title()\">{{ title() }}</h2>\n @if (hasHeaderAction()) {\n <div class=\"tk-drawer__actions\">\n <tk-button\n [label]=\"headerAction()!.label\"\n [severity]=\"headerAction()!.severity\"\n [variant]=\"headerAction()!.variant\"\n (clicked)=\"\n handleHeaderAction(\n headerAction()!.action,\n headerAction()!.returnValue\n )\n \" />\n </div>\n }\n </div>\n </ng-template>\n\n <section class=\"tk-drawer__content\">\n @if (content()) {\n @if (isContentString()) {\n <p [innerHTML]=\"content()\"></p>\n } @else {\n <ng-template #contentHost></ng-template>\n }\n }\n </section>\n</p-drawer>\n","import {\n Injectable,\n ApplicationRef,\n ComponentRef,\n createComponent,\n EmbeddedViewRef,\n} from '@angular/core';\nimport { DrawerComponent } from '../drawer.component';\nimport { Observable, Subject } from 'rxjs';\nimport { DrawerConfig } from '../drawer.types';\n\n@Injectable({ providedIn: 'root' })\nexport class DrawerService {\n private drawerRef: ComponentRef<DrawerComponent<unknown>> | null = null;\n\n constructor(private readonly appRef: ApplicationRef) {}\n\n get _drawerRefForTesting(): ComponentRef<DrawerComponent<unknown>> | null {\n return this.drawerRef;\n }\n set _drawerRefForTesting(ref: ComponentRef<DrawerComponent<unknown>> | null) {\n this.drawerRef = ref;\n }\n\n open(config: DrawerConfig): Observable<unknown> {\n if (this.drawerRef) {\n this.drawerRef.instance.close();\n this.appRef.detachView(this.drawerRef.hostView);\n this.drawerRef.destroy();\n this.drawerRef = null;\n }\n\n const componentRef = createComponent(DrawerComponent, {\n environmentInjector: this.appRef.injector,\n });\n\n this.appRef.attachView(componentRef.hostView);\n\n const domElem = (componentRef.hostView as EmbeddedViewRef<unknown>)\n .rootNodes[0] as HTMLElement;\n document.body.appendChild(domElem);\n\n componentRef.setInput('title', config.title);\n componentRef.setInput('content', config.content ?? null);\n componentRef.setInput('headerAction', config.headerAction ?? null);\n componentRef.setInput('size', config.size ?? 'small');\n componentRef.setInput('closable', config.closable ?? true);\n componentRef.setInput('dismissible', config.dismissible ?? true);\n componentRef.setInput('data', config.data ?? {});\n componentRef.setInput('interceptor', config.interceptor ?? undefined);\n\n const close$ = new Subject<unknown>();\n\n componentRef.instance.onClose.subscribe(value => {\n close$.next(value);\n close$.complete();\n\n this.appRef.detachView(componentRef.hostView);\n componentRef.destroy();\n if (this.drawerRef === (componentRef as unknown)) {\n this.drawerRef = null;\n }\n });\n\n componentRef.instance.open();\n this.drawerRef = componentRef as unknown as ComponentRef<\n DrawerComponent<unknown>\n >;\n\n return close$.asObservable();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|