@tekus/design-system 5.20.0 → 5.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/tekus-design-system-components-autocomplete.mjs +15 -15
- package/fesm2022/tekus-design-system-components-autocomplete.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-badge.mjs +8 -8
- package/fesm2022/tekus-design-system-components-badge.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-button.mjs +3 -3
- package/fesm2022/tekus-design-system-components-button.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-checkbox.mjs +14 -16
- package/fesm2022/tekus-design-system-components-checkbox.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-date-picker.mjs +166 -167
- package/fesm2022/tekus-design-system-components-date-picker.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-drawer.mjs +29 -29
- package/fesm2022/tekus-design-system-components-drawer.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-fallback-view.mjs +4 -5
- package/fesm2022/tekus-design-system-components-fallback-view.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-icon.mjs +13 -15
- package/fesm2022/tekus-design-system-components-icon.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-input-number.mjs +12 -14
- package/fesm2022/tekus-design-system-components-input-number.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-input-text.mjs +17 -18
- package/fesm2022/tekus-design-system-components-input-text.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-modal.mjs +31 -31
- package/fesm2022/tekus-design-system-components-modal.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-multiselect.mjs +19 -19
- package/fesm2022/tekus-design-system-components-multiselect.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-pagination.mjs +12 -12
- package/fesm2022/tekus-design-system-components-pagination.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-panel.mjs +3 -3
- package/fesm2022/tekus-design-system-components-panel.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-radio-button.mjs +13 -15
- package/fesm2022/tekus-design-system-components-radio-button.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-select.mjs +16 -16
- package/fesm2022/tekus-design-system-components-select.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-table.mjs +13 -13
- package/fesm2022/tekus-design-system-components-table.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-tabs.mjs +18 -21
- package/fesm2022/tekus-design-system-components-tabs.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-tag.mjs +11 -19
- package/fesm2022/tekus-design-system-components-tag.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-textarea.mjs +16 -18
- package/fesm2022/tekus-design-system-components-textarea.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-toolbar.mjs +18 -18
- package/fesm2022/tekus-design-system-components-toolbar.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-tooltip.mjs +6 -6
- package/fesm2022/tekus-design-system-components-tooltip.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-topbar.mjs +9 -9
- package/fesm2022/tekus-design-system-components-topbar.mjs.map +1 -1
- package/fesm2022/tekus-design-system-core-types.mjs +6 -6
- package/fesm2022/tekus-design-system-core-types.mjs.map +1 -1
- package/fesm2022/tekus-design-system-core.mjs +6 -6
- package/fesm2022/tekus-design-system-core.mjs.map +1 -1
- package/fesm2022/tekus-design-system-directives-gird-item.mjs +4 -4
- package/fesm2022/tekus-design-system-directives-gird-item.mjs.map +1 -1
- package/fesm2022/tekus-design-system-utils-sanitizer-utils.mjs.map +1 -1
- package/package.json +47 -42
- package/{components/autocomplete/src/autocomplete.component.d.ts → types/tekus-design-system-components-autocomplete.d.ts} +18 -16
- package/{components/badge/src/badge.component.d.ts → types/tekus-design-system-components-badge.d.ts} +12 -8
- package/{components/button/src/button.component.d.ts → types/tekus-design-system-components-button.d.ts} +8 -4
- package/{components/checkbox/src/checkbox.component.d.ts → types/tekus-design-system-components-checkbox.d.ts} +18 -15
- package/types/tekus-design-system-components-date-picker.d.ts +193 -0
- package/{components/drawer/src/drawer.component.d.ts → types/tekus-design-system-components-drawer.d.ts} +54 -19
- package/{components/fallback-view/src/fallback-view.component.d.ts → types/tekus-design-system-components-fallback-view.d.ts} +7 -3
- package/types/tekus-design-system-components-icon.d.ts +108 -0
- package/{components/input-number/src/input-number.component.d.ts → types/tekus-design-system-components-input-number.d.ts} +15 -12
- package/{components/input-text/src/input-text.component.d.ts → types/tekus-design-system-components-input-text.d.ts} +20 -17
- package/types/tekus-design-system-components-modal.d.ts +186 -0
- package/{components/multiselect/src/multiselect.component.d.ts → types/tekus-design-system-components-multiselect.d.ts} +30 -22
- package/{components/pagination/src/pagination.component.d.ts → types/tekus-design-system-components-pagination.d.ts} +16 -13
- package/{components/panel/src/panel.component.d.ts → types/tekus-design-system-components-panel.d.ts} +5 -2
- package/{components/radio-button/src/radio-button.component.d.ts → types/tekus-design-system-components-radio-button.d.ts} +16 -13
- package/{components/select/src/select.component.d.ts → types/tekus-design-system-components-select.d.ts} +20 -17
- package/{components/table/src/table.component.d.ts → types/tekus-design-system-components-table.d.ts} +30 -12
- package/{components/tabs/src/tabs.component.d.ts → types/tekus-design-system-components-tabs.d.ts} +23 -14
- package/{components/tag/src/tag.component.d.ts → types/tekus-design-system-components-tag.d.ts} +14 -10
- package/{components/textarea/src/textarea.component.d.ts → types/tekus-design-system-components-textarea.d.ts} +18 -15
- package/{components/toolbar/src/toolbar.component.d.ts → types/tekus-design-system-components-toolbar.d.ts} +21 -18
- package/types/tekus-design-system-components-tooltip.d.ts +39 -0
- package/types/tekus-design-system-components-topbar.d.ts +37 -0
- package/types/tekus-design-system-core-types.d.ts +182 -0
- package/types/tekus-design-system-core.d.ts +182 -0
- package/{directives/gird-item/src/grid-item.directive.d.ts → types/tekus-design-system-directives-gird-item.d.ts} +11 -7
- package/{utils/sanitizer-utils/src/sanitizer-utils.d.ts → types/tekus-design-system-utils-sanitizer-utils.d.ts} +5 -3
- package/types/tekus-design-system.d.ts +2 -0
- package/components/autocomplete/index.d.ts +0 -5
- package/components/autocomplete/public-api.d.ts +0 -1
- package/components/badge/index.d.ts +0 -5
- package/components/badge/public-api.d.ts +0 -1
- package/components/button/index.d.ts +0 -5
- package/components/button/public-api.d.ts +0 -1
- package/components/checkbox/index.d.ts +0 -5
- package/components/checkbox/public-api.d.ts +0 -1
- package/components/date-picker/index.d.ts +0 -5
- package/components/date-picker/public-api.d.ts +0 -1
- package/components/date-picker/src/date-picker.component.d.ts +0 -163
- package/components/drawer/index.d.ts +0 -5
- package/components/drawer/public-api.d.ts +0 -3
- package/components/drawer/src/drawer.types.d.ts +0 -22
- package/components/drawer/src/services/drawer.service.d.ts +0 -15
- package/components/fallback-view/index.d.ts +0 -5
- package/components/fallback-view/public-api.d.ts +0 -1
- package/components/icon/core/icon-catalog.d.ts +0 -76
- package/components/icon/core/icons/ads.icons.d.ts +0 -2
- package/components/icon/core/icons/angle.icons.d.ts +0 -2
- package/components/icon/core/icons/arrow.icons.d.ts +0 -2
- package/components/icon/core/icons/arrows-rotate.d.ts +0 -2
- package/components/icon/core/icons/bars.icons.d.ts +0 -2
- package/components/icon/core/icons/bolt.icons.d.ts +0 -2
- package/components/icon/core/icons/book.icons.d.ts +0 -2
- package/components/icon/core/icons/calendar.icons.d.ts +0 -2
- package/components/icon/core/icons/camera.icons.d.ts +0 -2
- package/components/icon/core/icons/chart.icons.d.ts +0 -2
- package/components/icon/core/icons/check.icons.d.ts +0 -2
- package/components/icon/core/icons/chevron.icons.d.ts +0 -2
- package/components/icon/core/icons/circle.icons.d.ts +0 -2
- package/components/icon/core/icons/clock.icons.d.ts +0 -2
- package/components/icon/core/icons/clone.icons.d.ts +0 -2
- package/components/icon/core/icons/download.icons.d.ts +0 -2
- package/components/icon/core/icons/edit.d.ts +0 -2
- package/components/icon/core/icons/ellipsis.icons.d.ts +0 -2
- package/components/icon/core/icons/eye.icons.d.ts +0 -2
- package/components/icon/core/icons/filter.icons.d.ts +0 -2
- package/components/icon/core/icons/folders.icons.d.ts +0 -2
- package/components/icon/core/icons/gears.icons.d.ts +0 -2
- package/components/icon/core/icons/globe-pointer.d.ts +0 -2
- package/components/icon/core/icons/grip-vertical.d.ts +0 -2
- package/components/icon/core/icons/hand.icons.d.ts +0 -2
- package/components/icon/core/icons/language.icons.d.ts +0 -2
- package/components/icon/core/icons/layer.icons.d.ts +0 -2
- package/components/icon/core/icons/link.icons.d.ts +0 -2
- package/components/icon/core/icons/list.icons.d.ts +0 -2
- package/components/icon/core/icons/location.icons.d.ts +0 -2
- package/components/icon/core/icons/lock.icons.d.ts +0 -2
- package/components/icon/core/icons/magnifying-glass.icons.d.ts +0 -2
- package/components/icon/core/icons/media.icons.d.ts +0 -2
- package/components/icon/core/icons/megaphone.icons.d.ts +0 -2
- package/components/icon/core/icons/money.icons.d.ts +0 -2
- package/components/icon/core/icons/pen.icons.d.ts +0 -2
- package/components/icon/core/icons/pencil.icons.d.ts +0 -2
- package/components/icon/core/icons/plug.icons.d.ts +0 -2
- package/components/icon/core/icons/plus.icons.d.ts +0 -2
- package/components/icon/core/icons/qr-code.icons.d.ts +0 -2
- package/components/icon/core/icons/screwdriver-wrench.icons.d.ts +0 -2
- package/components/icon/core/icons/shuffle.icons.d.ts +0 -2
- package/components/icon/core/icons/square.icons.d.ts +0 -2
- package/components/icon/core/icons/tag.icons.d.ts +0 -2
- package/components/icon/core/icons/thumbs.icons.d.ts +0 -2
- package/components/icon/core/icons/trash.icons.d.ts +0 -2
- package/components/icon/core/icons/triangle.icons.d.ts +0 -2
- package/components/icon/core/icons/user.icons.d.ts +0 -2
- package/components/icon/core/icons/xmark.icons.d.ts +0 -2
- package/components/icon/core/svg-icons/ads-icon.svg.d.ts +0 -2
- package/components/icon/core/svg-icons/index.d.ts +0 -1
- package/components/icon/index.d.ts +0 -5
- package/components/icon/public-api.d.ts +0 -2
- package/components/icon/src/icon.component.d.ts +0 -79
- package/components/input-number/index.d.ts +0 -5
- package/components/input-number/public-api.d.ts +0 -1
- package/components/input-text/index.d.ts +0 -5
- package/components/input-text/public-api.d.ts +0 -1
- package/components/modal/index.d.ts +0 -5
- package/components/modal/public-api.d.ts +0 -3
- package/components/modal/src/modal.component.d.ts +0 -118
- package/components/modal/src/modal.types.d.ts +0 -39
- package/components/modal/src/services/modal.service.d.ts +0 -31
- package/components/multiselect/index.d.ts +0 -5
- package/components/multiselect/public-api.d.ts +0 -2
- package/components/multiselect/src/multiselect.types.d.ts +0 -4
- package/components/pagination/index.d.ts +0 -5
- package/components/pagination/public-api.d.ts +0 -1
- package/components/panel/index.d.ts +0 -5
- package/components/panel/public-api.d.ts +0 -1
- package/components/radio-button/index.d.ts +0 -5
- package/components/radio-button/public-api.d.ts +0 -1
- package/components/select/index.d.ts +0 -5
- package/components/select/public-api.d.ts +0 -1
- package/components/table/index.d.ts +0 -5
- package/components/table/public-api.d.ts +0 -2
- package/components/table/src/table.interface.d.ts +0 -14
- package/components/tabs/index.d.ts +0 -5
- package/components/tabs/public-api.d.ts +0 -2
- package/components/tabs/src/tabs.interface.d.ts +0 -11
- package/components/tag/index.d.ts +0 -5
- package/components/tag/public-api.d.ts +0 -1
- package/components/textarea/index.d.ts +0 -5
- package/components/textarea/public-api.d.ts +0 -1
- package/components/toolbar/index.d.ts +0 -5
- package/components/toolbar/public-api.d.ts +0 -1
- package/components/tooltip/index.d.ts +0 -5
- package/components/tooltip/public-api.d.ts +0 -1
- package/components/tooltip/src/tooltip.component.d.ts +0 -35
- package/components/topbar/index.d.ts +0 -5
- package/components/topbar/public-api.d.ts +0 -2
- package/components/topbar/src/topbar.component.d.ts +0 -20
- package/components/topbar/src/topbar.types.d.ts +0 -13
- package/core/index.d.ts +0 -5
- package/core/public-api.d.ts +0 -1
- package/core/types/index.d.ts +0 -5
- package/core/types/public-api.d.ts +0 -10
- package/core/types/src/branding/branding.types.d.ts +0 -15
- package/core/types/src/branding/index.d.ts +0 -1
- package/core/types/src/breakpoints/breakpoints.d.ts +0 -10
- package/core/types/src/breakpoints/index.d.ts +0 -1
- package/core/types/src/grids/grid.enum.d.ts +0 -18
- package/core/types/src/grids/grid.model.d.ts +0 -10
- package/core/types/src/grids/grid.type.d.ts +0 -40
- package/core/types/src/grids/index.d.ts +0 -3
- package/core/types/src/illustration-config/illustration-config.model.d.ts +0 -4
- package/core/types/src/illustration-config/index.d.ts +0 -1
- package/core/types/src/interception/index.d.ts +0 -1
- package/core/types/src/interception/interception.types.d.ts +0 -21
- package/core/types/src/option/index.d.ts +0 -1
- package/core/types/src/option/option.model.d.ts +0 -8
- package/core/types/src/theme/theme.provider.d.ts +0 -1
- package/core/types/src/theme/tk-preset.d.ts +0 -1
- package/core/types/src/typography-styles/index.d.ts +0 -1
- package/core/types/src/typography-styles/typographyStyles.model.d.ts +0 -36
- package/core/types/src/validator-with-message/index.d.ts +0 -1
- package/core/types/src/validator-with-message/validator-with-message.model.d.ts +0 -5
- package/directives/gird-item/index.d.ts +0 -5
- package/directives/gird-item/public-api.d.ts +0 -1
- package/index.d.ts +0 -1
- package/utils/sanitizer-utils/index.d.ts +0 -5
- package/utils/sanitizer-utils/public-api.d.ts +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { viewChild, ViewContainerRef, input, computed, model, EventEmitter, effect, untracked,
|
|
2
|
+
import { inject, ElementRef, viewChild, ViewContainerRef, input, computed, model, EventEmitter, effect, untracked, afterEveryRender, Component, Injector, ApplicationRef, createComponent, Injectable } from '@angular/core';
|
|
3
3
|
import { ButtonComponent } from '@tekus/design-system/components/button';
|
|
4
4
|
import * as i1 from 'primeng/dialog';
|
|
5
5
|
import { DialogModule } from 'primeng/dialog';
|
|
@@ -13,43 +13,41 @@ import { Subject } from 'rxjs';
|
|
|
13
13
|
* Modernized for Angular 19 with 100% synchronous Signal-based closing interception.
|
|
14
14
|
*/
|
|
15
15
|
class ModalComponent {
|
|
16
|
-
constructor(
|
|
16
|
+
constructor() {
|
|
17
17
|
/**
|
|
18
18
|
* @summary Orchestrates the reactive dynamic lifecycle.
|
|
19
19
|
*/
|
|
20
|
-
this.elementRef =
|
|
21
|
-
this.contentHost = viewChild('contentHost', {
|
|
22
|
-
read: ViewContainerRef,
|
|
23
|
-
});
|
|
20
|
+
this.elementRef = inject(ElementRef);
|
|
21
|
+
this.contentHost = viewChild('contentHost', { ...(ngDevMode ? { debugName: "contentHost" } : /* istanbul ignore next */ {}), read: ViewContainerRef });
|
|
24
22
|
/** The title displayed at the top of the modal */
|
|
25
|
-
this.title = input('');
|
|
23
|
+
this.title = input('', ...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
26
24
|
/** The main content of the modal. Can be a string or a Component Type. */
|
|
27
|
-
this.content = input(null);
|
|
25
|
+
this.content = input(null, ...(ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []));
|
|
28
26
|
/** Array of footer buttons with label, callback, and return value */
|
|
29
|
-
this.footerButtons = input([]);
|
|
27
|
+
this.footerButtons = input([], ...(ngDevMode ? [{ debugName: "footerButtons" }] : /* istanbul ignore next */ []));
|
|
30
28
|
/** Modal size: 'small', 'large', 'medium' or 'full' */
|
|
31
|
-
this.size = input('small');
|
|
29
|
+
this.size = input('small', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
32
30
|
/** Whether the modal can be closed by the user via close button */
|
|
33
|
-
this.closable = input(true);
|
|
31
|
+
this.closable = input(true, ...(ngDevMode ? [{ debugName: "closable" }] : /* istanbul ignore next */ []));
|
|
34
32
|
/** Whether clicking outside the modal mask closes the modal */
|
|
35
|
-
this.closeOnOutsideClick = input(false);
|
|
33
|
+
this.closeOnOutsideClick = input(false, ...(ngDevMode ? [{ debugName: "closeOnOutsideClick" }] : /* istanbul ignore next */ []));
|
|
36
34
|
/**
|
|
37
35
|
* Optional data to be passed as inputs to the dynamic component.
|
|
38
36
|
*/
|
|
39
|
-
this.data = input({});
|
|
37
|
+
this.data = input({}, ...(ngDevMode ? [{ debugName: "data" }] : /* istanbul ignore next */ []));
|
|
40
38
|
/**
|
|
41
39
|
* Optional interceptor called before the modal closes.
|
|
42
40
|
* MUST be synchronous. Returns true to allow closing.
|
|
43
41
|
*/
|
|
44
|
-
this.interceptor = input(undefined);
|
|
42
|
+
this.interceptor = input(undefined, ...(ngDevMode ? [{ debugName: "interceptor" }] : /* istanbul ignore next */ []));
|
|
45
43
|
/** Computed: whether the content is a simple string */
|
|
46
|
-
this.isContentString = computed(() => typeof this.content() === 'string');
|
|
44
|
+
this.isContentString = computed(() => typeof this.content() === 'string', ...(ngDevMode ? [{ debugName: "isContentString" }] : /* istanbul ignore next */ []));
|
|
47
45
|
/** Computed: whether the modal has footer buttons to display */
|
|
48
|
-
this.hasFooter = computed(() => (this.footerButtons() ?? []).length > 0);
|
|
46
|
+
this.hasFooter = computed(() => (this.footerButtons() ?? []).length > 0, ...(ngDevMode ? [{ debugName: "hasFooter" }] : /* istanbul ignore next */ []));
|
|
49
47
|
/** Whether the modal should be responsive on mobile screens */
|
|
50
|
-
this.responsive = input(true);
|
|
48
|
+
this.responsive = input(true, ...(ngDevMode ? [{ debugName: "responsive" }] : /* istanbul ignore next */ []));
|
|
51
49
|
/** Visibility flag as Model Signal (allows two-way binding) */
|
|
52
|
-
this.isOpened = model(false);
|
|
50
|
+
this.isOpened = model(false, ...(ngDevMode ? [{ debugName: "isOpened" }] : /* istanbul ignore next */ []));
|
|
53
51
|
/** Whether the modal content has a scrollbar */
|
|
54
52
|
this.hasScroll = false;
|
|
55
53
|
// --- Internals ---
|
|
@@ -69,7 +67,7 @@ class ModalComponent {
|
|
|
69
67
|
default:
|
|
70
68
|
return '25rem';
|
|
71
69
|
}
|
|
72
|
-
});
|
|
70
|
+
}, ...(ngDevMode ? [{ debugName: "modalMaxWidth" }] : /* istanbul ignore next */ []));
|
|
73
71
|
effect(() => {
|
|
74
72
|
const opened = this.isOpened();
|
|
75
73
|
const host = this.contentHost();
|
|
@@ -86,7 +84,7 @@ class ModalComponent {
|
|
|
86
84
|
const currentData = this.data();
|
|
87
85
|
untracked(() => this.syncDynamicInputs(currentData));
|
|
88
86
|
});
|
|
89
|
-
|
|
87
|
+
afterEveryRender(() => {
|
|
90
88
|
this.checkScroll();
|
|
91
89
|
});
|
|
92
90
|
}
|
|
@@ -222,13 +220,15 @@ class ModalComponent {
|
|
|
222
220
|
this.alreadyEmitted = false;
|
|
223
221
|
this.returnValueOnClose = null;
|
|
224
222
|
}
|
|
225
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
226
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
223
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: ModalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
224
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.3", type: ModalComponent, isStandalone: true, selector: "tk-modal", inputs: { title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, footerButtons: { classPropertyName: "footerButtons", publicName: "footerButtons", 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 }, closeOnOutsideClick: { classPropertyName: "closeOnOutsideClick", publicName: "closeOnOutsideClick", 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 }, responsive: { classPropertyName: "responsive", publicName: "responsive", 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-dialog\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"onVisibleChange($event)\"\n [closable]=\"closable()\"\n [dismissableMask]=\"closeOnOutsideClick()\"\n [draggable]=\"false\"\n [focusOnShow]=\"false\"\n [header]=\"title()\"\n [style]=\"{\n 'max-width': modalMaxWidth(),\n width: 'calc(100% - var(--tk-spacing-base-200))',\n }\"\n (onHide)=\"handleClose()\"\n (onShow)=\"checkScroll()\"\n class=\"tk-modal\">\n <section class=\"tk-modal__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\n <ng-template pTemplate=\"footer\">\n @if (hasFooter()) {\n <section\n class=\"tk-modal__footer\"\n [class.tk-modal__footer--with-content]=\"hasScroll\">\n @for (btn of footerButtons()!; track $index) {\n <tk-button\n [label]=\"btn.label\"\n [severity]=\"btn.severity\"\n [variant]=\"btn.variant\"\n (clicked)=\"handleAction(btn.action, btn.returnValue)\"\n (keydown.enter)=\"handleAction(btn.action, btn.returnValue)\"\n (keydown.space)=\"handleAction(btn.action, btn.returnValue)\" />\n }\n </section>\n }\n </ng-template>\n</p-dialog>\n", styles: [":host ::ng-deep .p-dialog{max-height:90vh;display:flex;flex-direction:column}:host ::ng-deep .p-dialog-content{overflow-y:auto}:host ::ng-deep .p-dialog-title{color:var(--tk-color-text-default, #212121)}:host ::ng-deep .p-dialog-close-button{color:var(--tk-surface-500, #8a8a8b)}:host ::ng-deep .p-dialog-close-button:hover{background:var(--tk-color-base-surface-100, #f0f0f0)!important;color:var(--tk-surface-500, #8a8a8b)}.tk-modal__content{padding-bottom:var(--tk-spacing-paddingY-l, 1.25rem);color:var(--tk-surface-1000, #000000)}.tk-modal__footer{display:flex;flex-direction:row;justify-content:end;align-items:center;gap:var(--tk-spacing-base-50, .5rem)}.tk-modal__footer--with-content{padding-right:var(--tk-spacing-paddingX-l, 1.25rem)}\n"], dependencies: [{ kind: "ngmodule", type: DialogModule }, { kind: "component", type: i1.Dialog, selector: "p-dialog", inputs: ["hostName", "header", "draggable", "resizable", "contentStyle", "contentStyleClass", "modal", "closeOnEscape", "dismissableMask", "rtl", "closable", "breakpoints", "styleClass", "maskStyleClass", "maskStyle", "showHeader", "blockScroll", "autoZIndex", "baseZIndex", "minX", "minY", "focusOnShow", "maximizable", "keepInViewport", "focusTrap", "transitionOptions", "maskMotionOptions", "motionOptions", "closeIcon", "closeAriaLabel", "closeTabindex", "minimizeIcon", "maximizeIcon", "closeButtonProps", "maximizeButtonProps", "visible", "style", "position", "role", "appendTo", "content", "contentTemplate", "footerTemplate", "closeIconTemplate", "maximizeIconTemplate", "minimizeIconTemplate", "headlessTemplate"], outputs: ["onShow", "onHide", "visibleChange", "onResizeInit", "onResizeEnd", "onDragEnd", "onMaximize"] }, { 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"] }] }); }
|
|
227
225
|
}
|
|
228
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
226
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: ModalComponent, decorators: [{
|
|
229
227
|
type: Component,
|
|
230
228
|
args: [{ selector: 'tk-modal', standalone: true, imports: [DialogModule, ButtonComponent], template: "<p-dialog\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"onVisibleChange($event)\"\n [closable]=\"closable()\"\n [dismissableMask]=\"closeOnOutsideClick()\"\n [draggable]=\"false\"\n [focusOnShow]=\"false\"\n [header]=\"title()\"\n [style]=\"{\n 'max-width': modalMaxWidth(),\n width: 'calc(100% - var(--tk-spacing-base-200))',\n }\"\n (onHide)=\"handleClose()\"\n (onShow)=\"checkScroll()\"\n class=\"tk-modal\">\n <section class=\"tk-modal__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\n <ng-template pTemplate=\"footer\">\n @if (hasFooter()) {\n <section\n class=\"tk-modal__footer\"\n [class.tk-modal__footer--with-content]=\"hasScroll\">\n @for (btn of footerButtons()!; track $index) {\n <tk-button\n [label]=\"btn.label\"\n [severity]=\"btn.severity\"\n [variant]=\"btn.variant\"\n (clicked)=\"handleAction(btn.action, btn.returnValue)\"\n (keydown.enter)=\"handleAction(btn.action, btn.returnValue)\"\n (keydown.space)=\"handleAction(btn.action, btn.returnValue)\" />\n }\n </section>\n }\n </ng-template>\n</p-dialog>\n", styles: [":host ::ng-deep .p-dialog{max-height:90vh;display:flex;flex-direction:column}:host ::ng-deep .p-dialog-content{overflow-y:auto}:host ::ng-deep .p-dialog-title{color:var(--tk-color-text-default, #212121)}:host ::ng-deep .p-dialog-close-button{color:var(--tk-surface-500, #8a8a8b)}:host ::ng-deep .p-dialog-close-button:hover{background:var(--tk-color-base-surface-100, #f0f0f0)!important;color:var(--tk-surface-500, #8a8a8b)}.tk-modal__content{padding-bottom:var(--tk-spacing-paddingY-l, 1.25rem);color:var(--tk-surface-1000, #000000)}.tk-modal__footer{display:flex;flex-direction:row;justify-content:end;align-items:center;gap:var(--tk-spacing-base-50, .5rem)}.tk-modal__footer--with-content{padding-right:var(--tk-spacing-paddingX-l, 1.25rem)}\n"] }]
|
|
231
|
-
}], ctorParameters: () => [{ type: i0.
|
|
229
|
+
}], ctorParameters: () => [], propDecorators: { contentHost: [{ type: i0.ViewChild, args: ['contentHost', { ...{
|
|
230
|
+
read: ViewContainerRef,
|
|
231
|
+
}, isSignal: true }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], content: [{ type: i0.Input, args: [{ isSignal: true, alias: "content", required: false }] }], footerButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerButtons", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], closable: [{ type: i0.Input, args: [{ isSignal: true, alias: "closable", required: false }] }], closeOnOutsideClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnOutsideClick", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], interceptor: [{ type: i0.Input, args: [{ isSignal: true, alias: "interceptor", required: false }] }], responsive: [{ type: i0.Input, args: [{ isSignal: true, alias: "responsive", required: false }] }], isOpened: [{ type: i0.Input, args: [{ isSignal: true, alias: "isOpened", required: false }] }, { type: i0.Output, args: ["isOpenedChange"] }] } });
|
|
232
232
|
|
|
233
233
|
/**
|
|
234
234
|
* @service ModalService
|
|
@@ -237,9 +237,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
237
237
|
* It handles component creation, attachment to the document body, and cleanup.
|
|
238
238
|
*/
|
|
239
239
|
class ModalService {
|
|
240
|
-
constructor(
|
|
241
|
-
this.injector =
|
|
242
|
-
this.appRef =
|
|
240
|
+
constructor() {
|
|
241
|
+
this.injector = inject(Injector);
|
|
242
|
+
this.appRef = inject(ApplicationRef);
|
|
243
243
|
/** Reference to the currently open modal component */
|
|
244
244
|
this.modalRef = null;
|
|
245
245
|
}
|
|
@@ -287,13 +287,13 @@ class ModalService {
|
|
|
287
287
|
this.modalRef = componentRef;
|
|
288
288
|
return close$.asObservable();
|
|
289
289
|
}
|
|
290
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
291
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
290
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: ModalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
291
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: ModalService, providedIn: 'root' }); }
|
|
292
292
|
}
|
|
293
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
293
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: ModalService, decorators: [{
|
|
294
294
|
type: Injectable,
|
|
295
295
|
args: [{ providedIn: 'root' }]
|
|
296
|
-
}]
|
|
296
|
+
}] });
|
|
297
297
|
|
|
298
298
|
/**
|
|
299
299
|
* Generated bundle index. Do not edit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tekus-design-system-components-modal.mjs","sources":["../../../projects/design-system/components/modal/src/modal.component.ts","../../../projects/design-system/components/modal/src/modal.component.html","../../../projects/design-system/components/modal/src/services/modal.service.ts","../../../projects/design-system/components/modal/tekus-design-system-components-modal.ts"],"sourcesContent":["import {\n Component,\n computed,\n input,\n EventEmitter,\n Type,\n ElementRef,\n model,\n viewChild,\n ViewContainerRef,\n ComponentRef,\n effect,\n OnDestroy,\n untracked,\n afterRender,\n} from '@angular/core';\nimport { ButtonComponent } from '@tekus/design-system/components/button';\nimport { DialogModule } from 'primeng/dialog';\nimport { ModalFooterButton, ModalSizeType } from './modal.types';\nimport {\n TkCanClose,\n TkCloseInterceptor,\n} from '@tekus/design-system/core/types';\n\n/**\n * @component ModalComponent\n * @description\n * A programmatically controlled modal dialog used for displaying dynamic content.\n * Modernized for Angular 19 with 100% synchronous Signal-based closing interception.\n */\n@Component({\n selector: 'tk-modal',\n standalone: true,\n imports: [DialogModule, ButtonComponent],\n templateUrl: './modal.component.html',\n styleUrls: ['./modal.component.scss'],\n})\nexport class ModalComponent<T = unknown> implements OnDestroy {\n private readonly contentHost = viewChild('contentHost', {\n read: ViewContainerRef,\n });\n private componentRef?: ComponentRef<T>;\n\n /** The title displayed at the top of the modal */\n title = input<string>('');\n\n /** The main content of the modal. Can be a string or a Component Type. */\n content = input<string | Type<T> | null>(null);\n\n /** Array of footer buttons with label, callback, and return value */\n footerButtons = input<ModalFooterButton[]>([]);\n\n /** Modal size: 'small', 'large', 'medium' or 'full' */\n size = input<ModalSizeType>('small');\n\n /** Whether the modal can be closed by the user via close button */\n closable = input<boolean>(true);\n\n /** Whether clicking outside the modal mask closes the modal */\n closeOnOutsideClick = input<boolean>(false);\n\n /**\n * Optional data to be passed as inputs to the dynamic component.\n */\n data = input<Partial<T>>({});\n\n /**\n * Optional interceptor called before the modal closes.\n * MUST be synchronous. Returns true to allow closing.\n */\n interceptor = input<TkCloseInterceptor | undefined>(undefined);\n\n /** Computed: whether the content is a simple string */\n isContentString = computed(() => typeof this.content() === 'string');\n\n /** Computed: whether the modal has footer buttons to display */\n hasFooter = computed(() => (this.footerButtons() ?? []).length > 0);\n\n /** Whether the modal should be responsive on mobile screens */\n responsive = input<boolean>(true);\n\n /** Visibility flag as Model Signal (allows two-way binding) */\n isOpened = model<boolean>(false);\n\n /** Whether the modal content has a scrollbar */\n hasScroll = false;\n\n // --- Internals ---\n /** Emits when the modal closes, passing the return value from footer buttons 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\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 /** Computed: calculates modal max-width based on `size` */\n modalMaxWidth = computed(() => {\n switch (this.size()) {\n case 'large':\n return '67.5rem';\n case 'medium':\n return '35rem';\n case 'full':\n return '98vw';\n default:\n return '25rem';\n }\n });\n\n ngOnDestroy(): void {\n this.detachDynamicContent();\n }\n\n /**\n * @summary Orchestrates dynamic rendering and destruction based on visibility.\n * @private\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 /**\n * @summary Synchronizes incoming data record with the dynamic instance @Inputs.\n * @private\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 /**\n * @summary Safely destroys the dynamic component and clears references.\n * @private\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 modal content has a scrollbar and updates `hasScroll` state.\n */\n checkScroll(): void {\n const contentEl =\n this.elementRef.nativeElement.querySelector('.p-dialog-content');\n if (contentEl) {\n this.hasScroll = contentEl.scrollHeight > contentEl.clientHeight;\n }\n }\n\n /**\n * Opens the modal dialog.\n */\n open(): void {\n this.isOpened.set(true);\n this.resetClosureState();\n }\n\n /**\n * @summary Main entry point for closure requests.\n * Evaluation is 100% synchronous based on current Signal state.\n * @param returnValue (Optional) Value to emit on close.\n */\n tryClose(returnValue: unknown = null): void {\n if (this.canExecuteClosure()) {\n this.executeClosure(returnValue, arguments.length > 0);\n } else {\n const instance = this.componentRef?.instance as TkCanClose | undefined;\n instance?.onBlockedClose?.();\n }\n }\n\n /**\n * @summary Synchronous evaluator of hierarchical guards.\n * @returns true if closure is allowed.\n * @private\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 /**\n * @summary Unified logic to execute the final closure state change.\n * @private\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 /**\n * @summary Handles external visibility changes (from p-dialog 'X' or Escape).\n * Ensures the reactive guard is respected before allowing closure.\n */\n onVisibleChange(visible: boolean): void {\n if (!visible) {\n this.tryClose();\n }\n }\n\n /**\n * Handles the close event from the underlying dialog component.\n */\n handleClose(): void {\n const valueToEmit = this.alreadyEmitted ? this.returnValueOnClose : null;\n this.onClose.emit(valueToEmit);\n this.resetClosureState();\n }\n\n /**\n * @summary Handles actions triggered by footer buttons.\n */\n handleAction(action: (() => void) | undefined, returnValue: unknown): void {\n if (action) action();\n this.tryClose(returnValue);\n }\n\n /**\n * @summary Safely closes the modal forcefully without checks.\n */\n close(): void {\n this.tryClose();\n }\n\n /**\n * @private\n * Encapsulates state cleanup to avoid repetitive assignments\n */\n private resetClosureState(): void {\n this.alreadyEmitted = false;\n this.returnValueOnClose = null;\n }\n}\n","<p-dialog\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"onVisibleChange($event)\"\n [closable]=\"closable()\"\n [dismissableMask]=\"closeOnOutsideClick()\"\n [draggable]=\"false\"\n [focusOnShow]=\"false\"\n [header]=\"title()\"\n [style]=\"{\n 'max-width': modalMaxWidth(),\n width: 'calc(100% - var(--tk-spacing-base-200))',\n }\"\n (onHide)=\"handleClose()\"\n (onShow)=\"checkScroll()\"\n class=\"tk-modal\">\n <section class=\"tk-modal__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\n <ng-template pTemplate=\"footer\">\n @if (hasFooter()) {\n <section\n class=\"tk-modal__footer\"\n [class.tk-modal__footer--with-content]=\"hasScroll\">\n @for (btn of footerButtons()!; track $index) {\n <tk-button\n [label]=\"btn.label\"\n [severity]=\"btn.severity\"\n [variant]=\"btn.variant\"\n (clicked)=\"handleAction(btn.action, btn.returnValue)\"\n (keydown.enter)=\"handleAction(btn.action, btn.returnValue)\"\n (keydown.space)=\"handleAction(btn.action, btn.returnValue)\" />\n }\n </section>\n }\n </ng-template>\n</p-dialog>\n","import {\n Injectable,\n ApplicationRef,\n ComponentRef,\n Injector,\n createComponent,\n EmbeddedViewRef,\n} from '@angular/core';\nimport { ModalComponent } from '../modal.component';\nimport { Observable, Subject } from 'rxjs';\nimport { ModalConfig } from '../modal.types';\n\n/**\n * @service ModalService\n * @description\n * Service responsible for programmatically opening and managing modal dialogs.\n * It handles component creation, attachment to the document body, and cleanup.\n */\n@Injectable({ providedIn: 'root' })\nexport class ModalService {\n /** Reference to the currently open modal component */\n private modalRef: ComponentRef<ModalComponent> | null = null;\n\n constructor(\n private readonly injector: Injector,\n private readonly appRef: ApplicationRef\n ) {}\n\n /** Internal getter for testing purposes */\n get _modalRefForTesting(): ComponentRef<ModalComponent> | null {\n return this.modalRef;\n }\n /** Internal setter for testing purposes */\n set _modalRefForTesting(ref: ComponentRef<ModalComponent> | null) {\n this.modalRef = ref;\n }\n\n /**\n * Opens a modal dialog with the provided configuration.\n * Only one modal can be open at a time.\n * @param config Configuration object for the modal (title, content, buttons, etc.)\n * @returns An observable that emits the modal's return value when it closes.\n */\n open(config: ModalConfig): Observable<unknown> {\n if (this.modalRef) {\n return this.modalRef.instance.onClose.asObservable();\n }\n\n const componentRef = createComponent(ModalComponent, {\n environmentInjector: this.appRef.injector,\n });\n\n this.appRef.attachView(componentRef.hostView);\n\n const domElem = (componentRef.hostView as EmbeddedViewRef<unknown>).rootNodes[0] as HTMLElement;\n document.body.appendChild(domElem);\n\n componentRef.setInput('title', config.title);\n componentRef.setInput('content', config.content);\n componentRef.setInput('footerButtons', config.footerButtons || []);\n componentRef.setInput('size', config.size || 'small');\n componentRef.setInput('closable', config.closable ?? true);\n componentRef.setInput('closeOnOutsideClick', config.closeOnOutsideClick ?? false);\n componentRef.setInput('interceptor', config.interceptor);\n componentRef.setInput('data', config.data || {});\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.modalRef = null;\n });\n\n componentRef.instance.open();\n this.modalRef = 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-modal.mjs","sources":["../../../projects/design-system/components/modal/src/modal.component.ts","../../../projects/design-system/components/modal/src/modal.component.html","../../../projects/design-system/components/modal/src/services/modal.service.ts","../../../projects/design-system/components/modal/tekus-design-system-components-modal.ts"],"sourcesContent":["import { Component, computed, input, EventEmitter, Type, ElementRef, model, viewChild, ViewContainerRef, ComponentRef, effect, OnDestroy, untracked, afterEveryRender, inject } from '@angular/core';\nimport { ButtonComponent } from '@tekus/design-system/components/button';\nimport { DialogModule } from 'primeng/dialog';\nimport { ModalFooterButton, ModalSizeType } from './modal.types';\nimport {\n TkCanClose,\n TkCloseInterceptor,\n} from '@tekus/design-system/core/types';\n\n/**\n * @component ModalComponent\n * @description\n * A programmatically controlled modal dialog used for displaying dynamic content.\n * Modernized for Angular 19 with 100% synchronous Signal-based closing interception.\n */\n@Component({\n selector: 'tk-modal',\n standalone: true,\n imports: [DialogModule, ButtonComponent],\n templateUrl: './modal.component.html',\n styleUrls: ['./modal.component.scss'],\n})\nexport class ModalComponent<T = unknown> implements OnDestroy {\n private readonly elementRef = inject(ElementRef);\n\n private readonly contentHost = viewChild('contentHost', {\n read: ViewContainerRef,\n });\n private componentRef?: ComponentRef<T>;\n\n /** The title displayed at the top of the modal */\n title = input<string>('');\n\n /** The main content of the modal. Can be a string or a Component Type. */\n content = input<string | Type<T> | null>(null);\n\n /** Array of footer buttons with label, callback, and return value */\n footerButtons = input<ModalFooterButton[]>([]);\n\n /** Modal size: 'small', 'large', 'medium' or 'full' */\n size = input<ModalSizeType>('small');\n\n /** Whether the modal can be closed by the user via close button */\n closable = input<boolean>(true);\n\n /** Whether clicking outside the modal mask closes the modal */\n closeOnOutsideClick = input<boolean>(false);\n\n /**\n * Optional data to be passed as inputs to the dynamic component.\n */\n data = input<Partial<T>>({});\n\n /**\n * Optional interceptor called before the modal closes.\n * MUST be synchronous. Returns true to allow closing.\n */\n interceptor = input<TkCloseInterceptor | undefined>(undefined);\n\n /** Computed: whether the content is a simple string */\n isContentString = computed(() => typeof this.content() === 'string');\n\n /** Computed: whether the modal has footer buttons to display */\n hasFooter = computed(() => (this.footerButtons() ?? []).length > 0);\n\n /** Whether the modal should be responsive on mobile screens */\n responsive = input<boolean>(true);\n\n /** Visibility flag as Model Signal (allows two-way binding) */\n isOpened = model<boolean>(false);\n\n /** Whether the modal content has a scrollbar */\n hasScroll = false;\n\n // --- Internals ---\n /** Emits when the modal closes, passing the return value from footer buttons or null */\n readonly onClose = new EventEmitter<unknown>();\n private alreadyEmitted = false;\n private returnValueOnClose: unknown = null;\n\n constructor() {\n /**\n * @summary Orchestrates the reactive dynamic lifecycle.\n */\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 afterEveryRender(() => {\n this.checkScroll();\n });\n }\n\n /** Computed: calculates modal max-width based on `size` */\n modalMaxWidth = computed(() => {\n switch (this.size()) {\n case 'large':\n return '67.5rem';\n case 'medium':\n return '35rem';\n case 'full':\n return '98vw';\n default:\n return '25rem';\n }\n });\n\n ngOnDestroy(): void {\n this.detachDynamicContent();\n }\n\n /**\n * @summary Orchestrates dynamic rendering and destruction based on visibility.\n * @private\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 /**\n * @summary Synchronizes incoming data record with the dynamic instance @Inputs.\n * @private\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 /**\n * @summary Safely destroys the dynamic component and clears references.\n * @private\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 modal content has a scrollbar and updates `hasScroll` state.\n */\n checkScroll(): void {\n const contentEl =\n this.elementRef.nativeElement.querySelector('.p-dialog-content');\n if (contentEl) {\n this.hasScroll = contentEl.scrollHeight > contentEl.clientHeight;\n }\n }\n\n /**\n * Opens the modal dialog.\n */\n open(): void {\n this.isOpened.set(true);\n this.resetClosureState();\n }\n\n /**\n * @summary Main entry point for closure requests.\n * Evaluation is 100% synchronous based on current Signal state.\n * @param returnValue (Optional) Value to emit on close.\n */\n tryClose(returnValue: unknown = null): void {\n if (this.canExecuteClosure()) {\n this.executeClosure(returnValue, arguments.length > 0);\n } else {\n const instance = this.componentRef?.instance as TkCanClose | undefined;\n instance?.onBlockedClose?.();\n }\n }\n\n /**\n * @summary Synchronous evaluator of hierarchical guards.\n * @returns true if closure is allowed.\n * @private\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 /**\n * @summary Unified logic to execute the final closure state change.\n * @private\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 /**\n * @summary Handles external visibility changes (from p-dialog 'X' or Escape).\n * Ensures the reactive guard is respected before allowing closure.\n */\n onVisibleChange(visible: boolean): void {\n if (!visible) {\n this.tryClose();\n }\n }\n\n /**\n * Handles the close event from the underlying dialog component.\n */\n handleClose(): void {\n const valueToEmit = this.alreadyEmitted ? this.returnValueOnClose : null;\n this.onClose.emit(valueToEmit);\n this.resetClosureState();\n }\n\n /**\n * @summary Handles actions triggered by footer buttons.\n */\n handleAction(action: (() => void) | undefined, returnValue: unknown): void {\n if (action) action();\n this.tryClose(returnValue);\n }\n\n /**\n * @summary Safely closes the modal forcefully without checks.\n */\n close(): void {\n this.tryClose();\n }\n\n /**\n * @private\n * Encapsulates state cleanup to avoid repetitive assignments\n */\n private resetClosureState(): void {\n this.alreadyEmitted = false;\n this.returnValueOnClose = null;\n }\n}\n","<p-dialog\n [modal]=\"true\"\n [visible]=\"isOpened()\"\n (visibleChange)=\"onVisibleChange($event)\"\n [closable]=\"closable()\"\n [dismissableMask]=\"closeOnOutsideClick()\"\n [draggable]=\"false\"\n [focusOnShow]=\"false\"\n [header]=\"title()\"\n [style]=\"{\n 'max-width': modalMaxWidth(),\n width: 'calc(100% - var(--tk-spacing-base-200))',\n }\"\n (onHide)=\"handleClose()\"\n (onShow)=\"checkScroll()\"\n class=\"tk-modal\">\n <section class=\"tk-modal__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\n <ng-template pTemplate=\"footer\">\n @if (hasFooter()) {\n <section\n class=\"tk-modal__footer\"\n [class.tk-modal__footer--with-content]=\"hasScroll\">\n @for (btn of footerButtons()!; track $index) {\n <tk-button\n [label]=\"btn.label\"\n [severity]=\"btn.severity\"\n [variant]=\"btn.variant\"\n (clicked)=\"handleAction(btn.action, btn.returnValue)\"\n (keydown.enter)=\"handleAction(btn.action, btn.returnValue)\"\n (keydown.space)=\"handleAction(btn.action, btn.returnValue)\" />\n }\n </section>\n }\n </ng-template>\n</p-dialog>\n","import { Injectable, ApplicationRef, ComponentRef, Injector, createComponent, EmbeddedViewRef, inject } from '@angular/core';\nimport { ModalComponent } from '../modal.component';\nimport { Observable, Subject } from 'rxjs';\nimport { ModalConfig } from '../modal.types';\n\n/**\n * @service ModalService\n * @description\n * Service responsible for programmatically opening and managing modal dialogs.\n * It handles component creation, attachment to the document body, and cleanup.\n */\n@Injectable({ providedIn: 'root' })\nexport class ModalService {\n private readonly injector = inject(Injector);\n private readonly appRef = inject(ApplicationRef);\n\n /** Reference to the currently open modal component */\n private modalRef: ComponentRef<ModalComponent> | null = null;\n\n /** Internal getter for testing purposes */\n get _modalRefForTesting(): ComponentRef<ModalComponent> | null {\n return this.modalRef;\n }\n /** Internal setter for testing purposes */\n set _modalRefForTesting(ref: ComponentRef<ModalComponent> | null) {\n this.modalRef = ref;\n }\n\n /**\n * Opens a modal dialog with the provided configuration.\n * Only one modal can be open at a time.\n * @param config Configuration object for the modal (title, content, buttons, etc.)\n * @returns An observable that emits the modal's return value when it closes.\n */\n open(config: ModalConfig): Observable<unknown> {\n if (this.modalRef) {\n return this.modalRef.instance.onClose.asObservable();\n }\n\n const componentRef = createComponent(ModalComponent, {\n environmentInjector: this.appRef.injector,\n });\n\n this.appRef.attachView(componentRef.hostView);\n\n const domElem = (componentRef.hostView as EmbeddedViewRef<unknown>).rootNodes[0] as HTMLElement;\n document.body.appendChild(domElem);\n\n componentRef.setInput('title', config.title);\n componentRef.setInput('content', config.content);\n componentRef.setInput('footerButtons', config.footerButtons || []);\n componentRef.setInput('size', config.size || 'small');\n componentRef.setInput('closable', config.closable ?? true);\n componentRef.setInput('closeOnOutsideClick', config.closeOnOutsideClick ?? false);\n componentRef.setInput('interceptor', config.interceptor);\n componentRef.setInput('data', config.data || {});\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.modalRef = null;\n });\n\n componentRef.instance.open();\n this.modalRef = 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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"}
|
|
@@ -17,19 +17,19 @@ class MultiselectComponent {
|
|
|
17
17
|
* @description
|
|
18
18
|
* Internal signal to keep track of selected items even if they are filtered out from the main options list.
|
|
19
19
|
*/
|
|
20
|
-
this.selectionPool = signal([]);
|
|
20
|
+
this.selectionPool = signal([], ...(ngDevMode ? [{ debugName: "selectionPool" }] : /* istanbul ignore next */ []));
|
|
21
21
|
/**
|
|
22
22
|
* @property {ModelSignal<MultiSelectOption[] | null>} model
|
|
23
23
|
* @description
|
|
24
24
|
* The model signal for two-way binding.
|
|
25
25
|
*/
|
|
26
|
-
this.model = model([]);
|
|
26
|
+
this.model = model([], ...(ngDevMode ? [{ debugName: "model" }] : /* istanbul ignore next */ []));
|
|
27
27
|
/**
|
|
28
28
|
* @property {MultiSelectOption[]} options
|
|
29
29
|
* @description
|
|
30
30
|
* Array of available options shown in the multiselect dropdown.
|
|
31
31
|
*/
|
|
32
|
-
this.options = input([]);
|
|
32
|
+
this.options = input([], ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
33
33
|
/**
|
|
34
34
|
* @property {string} labelText
|
|
35
35
|
* @description
|
|
@@ -37,7 +37,7 @@ class MultiselectComponent {
|
|
|
37
37
|
*
|
|
38
38
|
* @default 'Select'
|
|
39
39
|
*/
|
|
40
|
-
this.labelText = input('Select');
|
|
40
|
+
this.labelText = input('Select', ...(ngDevMode ? [{ debugName: "labelText" }] : /* istanbul ignore next */ []));
|
|
41
41
|
/**
|
|
42
42
|
* @property {string} display
|
|
43
43
|
* @description
|
|
@@ -45,7 +45,7 @@ class MultiselectComponent {
|
|
|
45
45
|
*
|
|
46
46
|
* @default 'chip'
|
|
47
47
|
*/
|
|
48
|
-
this.display = input('chip');
|
|
48
|
+
this.display = input('chip', ...(ngDevMode ? [{ debugName: "display" }] : /* istanbul ignore next */ []));
|
|
49
49
|
/**
|
|
50
50
|
* @property {number} maxSelectedLabels
|
|
51
51
|
* @description
|
|
@@ -53,7 +53,7 @@ class MultiselectComponent {
|
|
|
53
53
|
*
|
|
54
54
|
* @default 4
|
|
55
55
|
*/
|
|
56
|
-
this.maxSelectedLabels = input(4);
|
|
56
|
+
this.maxSelectedLabels = input(4, ...(ngDevMode ? [{ debugName: "maxSelectedLabels" }] : /* istanbul ignore next */ []));
|
|
57
57
|
/**
|
|
58
58
|
* @property {string} selectedItemsLabel
|
|
59
59
|
* @description
|
|
@@ -61,7 +61,7 @@ class MultiselectComponent {
|
|
|
61
61
|
*
|
|
62
62
|
* @default '{0} elementos seleccionados'
|
|
63
63
|
*/
|
|
64
|
-
this.selectedItemsLabel = input('{0} elementos seleccionados');
|
|
64
|
+
this.selectedItemsLabel = input('{0} elementos seleccionados', ...(ngDevMode ? [{ debugName: "selectedItemsLabel" }] : /* istanbul ignore next */ []));
|
|
65
65
|
/**
|
|
66
66
|
* @property {string} emptyFilterMessage
|
|
67
67
|
* @description
|
|
@@ -69,7 +69,7 @@ class MultiselectComponent {
|
|
|
69
69
|
*
|
|
70
70
|
* @default 'No hay resultados'
|
|
71
71
|
*/
|
|
72
|
-
this.emptyFilterMessage = input('No hay resultados');
|
|
72
|
+
this.emptyFilterMessage = input('No hay resultados', ...(ngDevMode ? [{ debugName: "emptyFilterMessage" }] : /* istanbul ignore next */ []));
|
|
73
73
|
/**
|
|
74
74
|
* @property {boolean} filter
|
|
75
75
|
* @description
|
|
@@ -77,13 +77,13 @@ class MultiselectComponent {
|
|
|
77
77
|
*
|
|
78
78
|
* @default true
|
|
79
79
|
*/
|
|
80
|
-
this.filter = input(true);
|
|
80
|
+
this.filter = input(true, ...(ngDevMode ? [{ debugName: "filter" }] : /* istanbul ignore next */ []));
|
|
81
81
|
/**
|
|
82
82
|
* @property {string} filterPlaceHolder
|
|
83
83
|
* @description
|
|
84
84
|
* Placeholder text for the filter input.
|
|
85
85
|
*/
|
|
86
|
-
this.filterPlaceHolder = input('');
|
|
86
|
+
this.filterPlaceHolder = input('', ...(ngDevMode ? [{ debugName: "filterPlaceHolder" }] : /* istanbul ignore next */ []));
|
|
87
87
|
/**
|
|
88
88
|
* @property {string} id
|
|
89
89
|
* @description
|
|
@@ -91,25 +91,25 @@ class MultiselectComponent {
|
|
|
91
91
|
*
|
|
92
92
|
* @default 'multiselect'
|
|
93
93
|
*/
|
|
94
|
-
this.id = input('multiselect');
|
|
94
|
+
this.id = input('multiselect', ...(ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []));
|
|
95
95
|
/**
|
|
96
96
|
* @property {string} styleClass
|
|
97
97
|
* @description
|
|
98
98
|
* Additional CSS class applied to the multiselect container.
|
|
99
99
|
*/
|
|
100
|
-
this.styleClass = input('');
|
|
100
|
+
this.styleClass = input('', ...(ngDevMode ? [{ debugName: "styleClass" }] : /* istanbul ignore next */ []));
|
|
101
101
|
/**
|
|
102
102
|
* @property {InputSignal<string>} errorMessage
|
|
103
103
|
* @description
|
|
104
104
|
* Message to display when the control is invalid and touched.
|
|
105
105
|
*/
|
|
106
|
-
this.errorMessage = input('');
|
|
106
|
+
this.errorMessage = input('', ...(ngDevMode ? [{ debugName: "errorMessage" }] : /* istanbul ignore next */ []));
|
|
107
107
|
/**
|
|
108
108
|
* @property {InputSignal<string>} hint
|
|
109
109
|
* @description
|
|
110
110
|
* Hint text to display below the input.
|
|
111
111
|
*/
|
|
112
|
-
this.hint = input('');
|
|
112
|
+
this.hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
113
113
|
/**
|
|
114
114
|
* @event selectionChange
|
|
115
115
|
* @description
|
|
@@ -142,7 +142,7 @@ class MultiselectComponent {
|
|
|
142
142
|
uniqueMap.set(item.code, item);
|
|
143
143
|
});
|
|
144
144
|
return Array.from(uniqueMap.values());
|
|
145
|
-
});
|
|
145
|
+
}, ...(ngDevMode ? [{ debugName: "internalOptions" }] : /* istanbul ignore next */ []));
|
|
146
146
|
/**
|
|
147
147
|
* @callback onChange
|
|
148
148
|
* @description
|
|
@@ -249,10 +249,10 @@ class MultiselectComponent {
|
|
|
249
249
|
get effectiveControl() {
|
|
250
250
|
return this.ngControl?.control || null;
|
|
251
251
|
}
|
|
252
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
253
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
252
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: MultiselectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
253
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.3", type: MultiselectComponent, isStandalone: true, selector: "tk-multiselect", inputs: { model: { classPropertyName: "model", publicName: "model", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, labelText: { classPropertyName: "labelText", publicName: "labelText", isSignal: true, isRequired: false, transformFunction: null }, display: { classPropertyName: "display", publicName: "display", isSignal: true, isRequired: false, transformFunction: null }, maxSelectedLabels: { classPropertyName: "maxSelectedLabels", publicName: "maxSelectedLabels", isSignal: true, isRequired: false, transformFunction: null }, selectedItemsLabel: { classPropertyName: "selectedItemsLabel", publicName: "selectedItemsLabel", isSignal: true, isRequired: false, transformFunction: null }, emptyFilterMessage: { classPropertyName: "emptyFilterMessage", publicName: "emptyFilterMessage", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterPlaceHolder: { classPropertyName: "filterPlaceHolder", publicName: "filterPlaceHolder", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, styleClass: { classPropertyName: "styleClass", publicName: "styleClass", isSignal: true, isRequired: false, transformFunction: null }, errorMessage: { classPropertyName: "errorMessage", publicName: "errorMessage", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { model: "modelChange", selectionChange: "selectionChange", filterChange: "filterChange" }, ngImport: i0, template: "<p-floatlabel>\n <p-multiselect\n optionLabel=\"name\"\n [id]=\"id()\"\n [options]=\"options()\"\n [(ngModel)]=\"model\"\n [display]=\"display()\"\n [maxSelectedLabels]=\"maxSelectedLabels()\"\n [selectedItemsLabel]=\"selectedItemsLabel()\"\n [emptyFilterMessage]=\"emptyFilterMessage()\"\n [filter]=\"filter()\"\n [filterPlaceHolder]=\"filterPlaceHolder()\"\n [styleClass]=\"styleClass()\"\n [class.ng-invalid]=\"\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched)\n \"\n [class.ng-dirty]=\"effectiveControl?.dirty\"\n [class.ng-touched]=\"effectiveControl?.touched\"\n (onFilter)=\"handleFilter($event)\"\n (onChange)=\"handleChange($event)\">\n </p-multiselect>\n <label [for]=\"id()\">{{ labelText() }}</label>\n</p-floatlabel>\n\n<div class=\"tk-select-bottom\">\n <div class=\"tk-select-messages\">\n @if (\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched) &&\n errorMessage()\n ) {\n <p-message severity=\"error\" size=\"small\" variant=\"simple\">{{\n errorMessage()\n }}</p-message>\n } @else if (hint()) {\n <p-message severity=\"secondary\" size=\"small\" variant=\"simple\">{{\n hint()\n }}</p-message>\n }\n </div>\n</div>\n", styles: [":host ::ng-deep .p-multiselect{width:100%;border:none;border-bottom:1px solid var(--tk-color-border-default, #cecdcd);border-radius:0;background-color:transparent}:host ::ng-deep .p-multiselect:focus{border-color:var(--tk-color-accent-default, #16006f)}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-filled) label,:host ::ng-deep .p-floatlabel:has(input:focus) label{color:var(--tk-primary-500, #16006f)}:host ::ng-deep .p-floatlabel label{color:var(--tk-surface-700, #424243);font-family:var(--tk-font-family, Poppins, sans-serif);font-size:var(--tk-font-size-2xs, 1rem);font-weight:var(--tk-font-weight-400, 400);left:var(--tk-spacing-base-25, .25rem)}:host ::ng-deep .p-multiselect-option span{color:var(--tk-color-accent-default, #16006f)!important;display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .p-multiselect-option-selected{background-color:var(--tk-color-accent-muted, #b7b0d2)!important}:host ::ng-deep .p-multiselect-chip{background-color:var(--tk-surface-100, #f4f4f5);color:var(--tk-surface-700, #424243);border-radius:var(--tk-borderRadius-full, 999px)!important;padding:4px 8px}:host ::ng-deep .p-multiselect-filter{border:none;border-radius:0;box-shadow:none;border-bottom:1px solid var(--tk-surface-300, #d2d2d2)}:host ::ng-deep .p-overlay{width:-webkit-fill-available}:host ::ng-deep .p-chip-label{display:inline-block;max-width:10ch;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .p-multiselect-label{gap:.313rem;padding:var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-25, 4px)!important}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i2.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "ngmodule", type: FloatLabelModule }, { kind: "component", type: i3.FloatLabel, selector: "p-floatlabel, p-floatLabel, p-float-label", inputs: ["variant"] }, { kind: "ngmodule", type: MessageModule }, { kind: "component", type: i4.Message, selector: "p-message", inputs: ["severity", "text", "escape", "style", "styleClass", "closable", "icon", "closeIcon", "life", "showTransitionOptions", "hideTransitionOptions", "size", "variant", "motionOptions"], outputs: ["onClose"] }] }); }
|
|
254
254
|
}
|
|
255
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
255
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.3", ngImport: i0, type: MultiselectComponent, decorators: [{
|
|
256
256
|
type: Component,
|
|
257
257
|
args: [{ selector: 'tk-multiselect', standalone: true, imports: [
|
|
258
258
|
ReactiveFormsModule,
|
|
@@ -261,7 +261,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.18", ngImpo
|
|
|
261
261
|
FloatLabelModule,
|
|
262
262
|
MessageModule
|
|
263
263
|
], template: "<p-floatlabel>\n <p-multiselect\n optionLabel=\"name\"\n [id]=\"id()\"\n [options]=\"options()\"\n [(ngModel)]=\"model\"\n [display]=\"display()\"\n [maxSelectedLabels]=\"maxSelectedLabels()\"\n [selectedItemsLabel]=\"selectedItemsLabel()\"\n [emptyFilterMessage]=\"emptyFilterMessage()\"\n [filter]=\"filter()\"\n [filterPlaceHolder]=\"filterPlaceHolder()\"\n [styleClass]=\"styleClass()\"\n [class.ng-invalid]=\"\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched)\n \"\n [class.ng-dirty]=\"effectiveControl?.dirty\"\n [class.ng-touched]=\"effectiveControl?.touched\"\n (onFilter)=\"handleFilter($event)\"\n (onChange)=\"handleChange($event)\">\n </p-multiselect>\n <label [for]=\"id()\">{{ labelText() }}</label>\n</p-floatlabel>\n\n<div class=\"tk-select-bottom\">\n <div class=\"tk-select-messages\">\n @if (\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched) &&\n errorMessage()\n ) {\n <p-message severity=\"error\" size=\"small\" variant=\"simple\">{{\n errorMessage()\n }}</p-message>\n } @else if (hint()) {\n <p-message severity=\"secondary\" size=\"small\" variant=\"simple\">{{\n hint()\n }}</p-message>\n }\n </div>\n</div>\n", styles: [":host ::ng-deep .p-multiselect{width:100%;border:none;border-bottom:1px solid var(--tk-color-border-default, #cecdcd);border-radius:0;background-color:transparent}:host ::ng-deep .p-multiselect:focus{border-color:var(--tk-color-accent-default, #16006f)}:host ::ng-deep .p-floatlabel:has(.p-inputwrapper-filled) label,:host ::ng-deep .p-floatlabel:has(input:focus) label{color:var(--tk-primary-500, #16006f)}:host ::ng-deep .p-floatlabel label{color:var(--tk-surface-700, #424243);font-family:var(--tk-font-family, Poppins, sans-serif);font-size:var(--tk-font-size-2xs, 1rem);font-weight:var(--tk-font-weight-400, 400);left:var(--tk-spacing-base-25, .25rem)}:host ::ng-deep .p-multiselect-option span{color:var(--tk-color-accent-default, #16006f)!important;display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}:host ::ng-deep .p-multiselect-option-selected{background-color:var(--tk-color-accent-muted, #b7b0d2)!important}:host ::ng-deep .p-multiselect-chip{background-color:var(--tk-surface-100, #f4f4f5);color:var(--tk-surface-700, #424243);border-radius:var(--tk-borderRadius-full, 999px)!important;padding:4px 8px}:host ::ng-deep .p-multiselect-filter{border:none;border-radius:0;box-shadow:none;border-bottom:1px solid var(--tk-surface-300, #d2d2d2)}:host ::ng-deep .p-overlay{width:-webkit-fill-available}:host ::ng-deep .p-chip-label{display:inline-block;max-width:10ch;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}:host ::ng-deep .p-multiselect-label{gap:.313rem;padding:var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-75, 12px) var(--tk-spacing-base-25, 4px)!important}\n"] }]
|
|
264
|
-
}], ctorParameters: () => [] });
|
|
264
|
+
}], ctorParameters: () => [], propDecorators: { model: [{ type: i0.Input, args: [{ isSignal: true, alias: "model", required: false }] }, { type: i0.Output, args: ["modelChange"] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: false }] }], labelText: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelText", required: false }] }], display: [{ type: i0.Input, args: [{ isSignal: true, alias: "display", required: false }] }], maxSelectedLabels: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSelectedLabels", required: false }] }], selectedItemsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedItemsLabel", required: false }] }], emptyFilterMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyFilterMessage", required: false }] }], filter: [{ type: i0.Input, args: [{ isSignal: true, alias: "filter", required: false }] }], filterPlaceHolder: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterPlaceHolder", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], styleClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "styleClass", required: false }] }], errorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "errorMessage", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], filterChange: [{ type: i0.Output, args: ["filterChange"] }] } });
|
|
265
265
|
|
|
266
266
|
/**
|
|
267
267
|
* Generated bundle index. Do not edit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tekus-design-system-components-multiselect.mjs","sources":["../../../projects/design-system/components/multiselect/src/multiselect.component.ts","../../../projects/design-system/components/multiselect/src/multiselect.component.html","../../../projects/design-system/components/multiselect/tekus-design-system-components-multiselect.ts"],"sourcesContent":["import {\n Component,\n computed,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport {\n ControlValueAccessor,\n FormControl,\n FormsModule,\n NgControl,\n ReactiveFormsModule,\n} from '@angular/forms';\nimport { MultiSelectModule } from 'primeng/multiselect';\nimport { FloatLabelModule } from 'primeng/floatlabel';\nimport { MultiSelectOption } from './multiselect.types';\nimport { MessageModule } from 'primeng/message';\n@Component({\n selector: 'tk-multiselect',\n standalone: true,\n imports: [\n ReactiveFormsModule,\n FormsModule,\n MultiSelectModule,\n FloatLabelModule,\n MessageModule\n ],\n templateUrl: './multiselect.component.html',\n styleUrls: ['./multiselect.component.scss'],\n})\nexport class MultiselectComponent implements ControlValueAccessor {\n readonly ngControl = inject(NgControl, { self: true, optional: true });\n\n constructor() {\n if (this.ngControl) {\n this.ngControl.valueAccessor = this;\n }\n }\n\n /**\n * @property {Signal<MultiSelectOption[]>} selectionPool\n * @description\n * Internal signal to keep track of selected items even if they are filtered out from the main options list.\n */\n private readonly selectionPool = signal<MultiSelectOption[]>([]);\n\n /**\n * @property {ModelSignal<MultiSelectOption[] | null>} model\n * @description\n * The model signal for two-way binding.\n */\n readonly model = model<MultiSelectOption[] | null>([]);\n\n /**\n * @property {MultiSelectOption[]} options\n * @description\n * Array of available options shown in the multiselect dropdown.\n */\n options = input<MultiSelectOption[]>([]);\n\n /**\n * @property {string} labelText\n * @description\n * Label displayed above the multiselect input.\n *\n * @default 'Select'\n */\n labelText = input<string>('Select');\n\n /**\n * @property {string} display\n * @description\n * Display mode for selected items. Examples: 'chip', 'comma'.\n *\n * @default 'chip'\n */\n display = input<string>('chip');\n\n /**\n * @property {number} maxSelectedLabels\n * @description\n * Maximum number of labels shown when multiple items are selected.\n *\n * @default 4\n */\n maxSelectedLabels = input<number>(4);\n\n /**\n * @property {string} selectedItemsLabel\n * @description\n * Label template used when multiple items are selected (supports placeholders).\n *\n * @default '{0} elementos seleccionados'\n */\n selectedItemsLabel = input<string>('{0} elementos seleccionados');\n\n /**\n * @property {string} emptyFilterMessage\n * @description\n * Message displayed when the filter returns no results.\n *\n * @default 'No hay resultados'\n */\n emptyFilterMessage = input<string>('No hay resultados');\n\n /**\n * @property {boolean} filter\n * @description\n * Enables the search/filter input inside the multiselect dropdown.\n *\n * @default true\n */\n filter = input<boolean>(true);\n\n /**\n * @property {string} filterPlaceHolder\n * @description\n * Placeholder text for the filter input.\n */\n filterPlaceHolder = input<string>('');\n\n /**\n * @property {string} id\n * @description\n * HTML id attribute for the multiselect input.\n *\n * @default 'multiselect'\n */\n id = input<string>('multiselect');\n\n /**\n * @property {string} styleClass\n * @description\n * Additional CSS class applied to the multiselect container.\n */\n styleClass = input<string>('');\n\n /**\n * @property {InputSignal<string>} errorMessage\n * @description\n * Message to display when the control is invalid and touched.\n */\n errorMessage = input<string>('');\n\n /**\n * @property {InputSignal<string>} hint\n * @description\n * Hint text to display below the input.\n */\n hint = input<string>('');\n\n /**\n * @event selectionChange\n * @description\n * Emits when the selected options change.\n * Payload: an array of selected MultiSelectOption or null.\n *\n * @example\n * <tk-multiselect (selectionChange)=\"onChange($event)\"></tk-multiselect>\n */\n selectionChange = output<MultiSelectOption[] | null>();\n\n /**\n * @event filterChange\n * @description\n * Emits the filter text when the user types in the search input.\n */\n readonly filterChange = output<string>();\n\n /**\n * @property internalOptions\n * @description\n * Computed signal that merges the current options with the selected items pool\n * to ensure selected items are always visible.\n */\n readonly internalOptions = computed(() => {\n const currentFromParent = this.options();\n const selected = this.selectionPool();\n\n const merged = [...selected, ...currentFromParent];\n const uniqueMap = new Map();\n\n merged.forEach(item => {\n if (item) uniqueMap.set(item.code, item);\n });\n\n return Array.from(uniqueMap.values());\n });\n\n /**\n * @method handleFilter\n * @description\n * Handles the filter event from the PrimeNG component and emits the filter value.\n *\n * @param event - The filter event object.\n */\n handleFilter(event: { filter: string }) {\n this.filterChange.emit(event.filter || '');\n }\n\n /**\n * @callback onChange\n * @description\n * Callback function to notify the parent component of value changes.\n */\n onChange: (value: MultiSelectOption[] | null) => void = () => {};\n\n /**\n * @callback onTouched\n * @description\n * Callback function to notify the parent component when the control is touched.\n */\n onTouched: () => void = () => {};\n\n /**\n * @method handleChange\n * @description\n * Handler forwarded from the PrimeNG MultiSelect change event.\n * Emits the selectionChange output with the selected values.\n *\n * @param event - Change event containing the `value` property with selected items.\n */\n handleChange(event: { value: MultiSelectOption[] | null }): void {\n const val = event.value || [];\n this.model.set(val);\n this.updateSelectionPool(val);\n\n this.onChange(val);\n this.selectionChange.emit(val);\n\n if (this.effectiveControl) {\n this.effectiveControl.setValue(val);\n this.effectiveControl.markAsDirty();\n this.effectiveControl.markAsTouched();\n }\n }\n\n /**\n * @method updateSelectionPool\n * @description\n * Updates the internal selection pool to ensure selected items persist\n * even if they are filtered out from the main options list.\n *\n * @param items - The items to add to the pool.\n */\n private updateSelectionPool(items: MultiSelectOption[]) {\n this.selectionPool.update(prev => {\n const combined = [...prev, ...items];\n const map = new Map();\n combined.forEach(i => map.set(i.code, i));\n return Array.from(map.values());\n });\n }\n\n /**\n * @method writeValue\n * @description\n * Writes a new value to the element.\n * Part of the ControlValueAccessor interface.\n *\n * @param value - The new value.\n */\n writeValue(value: MultiSelectOption[] | null): void {\n this.model.set(value || []);\n if (value) this.updateSelectionPool(value);\n }\n\n /**\n * @method registerOnChange\n * @description\n * Registers a callback function that is called when the control's value changes in the UI.\n * Part of the ControlValueAccessor interface.\n *\n * @param fn - The callback function.\n */\n registerOnChange(fn: (value: MultiSelectOption[] | null) => void): void {\n this.onChange = fn;\n }\n\n /**\n * @method registerOnTouched\n * @description\n * Registers a callback function that is called by the forms API on initialization to update the form control on 'blur'.\n * Part of the ControlValueAccessor interface.\n *\n * @param fn - The callback function.\n */\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n /**\n * @method effectiveControl\n * @description\n * Gets the effective FormControl associated with this component,\n * either from NgControl or the internal model.\n */\n get effectiveControl(): FormControl | null {\n return (this.ngControl?.control as FormControl) || null;\n }\n}\n","<p-floatlabel>\n <p-multiselect\n optionLabel=\"name\"\n [id]=\"id()\"\n [options]=\"options()\"\n [(ngModel)]=\"model\"\n [display]=\"display()\"\n [maxSelectedLabels]=\"maxSelectedLabels()\"\n [selectedItemsLabel]=\"selectedItemsLabel()\"\n [emptyFilterMessage]=\"emptyFilterMessage()\"\n [filter]=\"filter()\"\n [filterPlaceHolder]=\"filterPlaceHolder()\"\n [styleClass]=\"styleClass()\"\n [class.ng-invalid]=\"\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched)\n \"\n [class.ng-dirty]=\"effectiveControl?.dirty\"\n [class.ng-touched]=\"effectiveControl?.touched\"\n (onFilter)=\"handleFilter($event)\"\n (onChange)=\"handleChange($event)\">\n </p-multiselect>\n <label [for]=\"id()\">{{ labelText() }}</label>\n</p-floatlabel>\n\n<div class=\"tk-select-bottom\">\n <div class=\"tk-select-messages\">\n @if (\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched) &&\n errorMessage()\n ) {\n <p-message severity=\"error\" size=\"small\" variant=\"simple\">{{\n errorMessage()\n }}</p-message>\n } @else if (hint()) {\n <p-message severity=\"secondary\" size=\"small\" variant=\"simple\">{{\n hint()\n }}</p-message>\n }\n </div>\n</div>\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-multiselect.mjs","sources":["../../../projects/design-system/components/multiselect/src/multiselect.component.ts","../../../projects/design-system/components/multiselect/src/multiselect.component.html","../../../projects/design-system/components/multiselect/tekus-design-system-components-multiselect.ts"],"sourcesContent":["import {\n Component,\n computed,\n inject,\n input,\n model,\n output,\n signal,\n} from '@angular/core';\nimport {\n ControlValueAccessor,\n FormControl,\n FormsModule,\n NgControl,\n ReactiveFormsModule,\n} from '@angular/forms';\nimport { MultiSelectModule } from 'primeng/multiselect';\nimport { FloatLabelModule } from 'primeng/floatlabel';\nimport { MultiSelectOption } from './multiselect.types';\nimport { MessageModule } from 'primeng/message';\n@Component({\n selector: 'tk-multiselect',\n standalone: true,\n imports: [\n ReactiveFormsModule,\n FormsModule,\n MultiSelectModule,\n FloatLabelModule,\n MessageModule\n ],\n templateUrl: './multiselect.component.html',\n styleUrls: ['./multiselect.component.scss'],\n})\nexport class MultiselectComponent implements ControlValueAccessor {\n readonly ngControl = inject(NgControl, { self: true, optional: true });\n\n constructor() {\n if (this.ngControl) {\n this.ngControl.valueAccessor = this;\n }\n }\n\n /**\n * @property {Signal<MultiSelectOption[]>} selectionPool\n * @description\n * Internal signal to keep track of selected items even if they are filtered out from the main options list.\n */\n private readonly selectionPool = signal<MultiSelectOption[]>([]);\n\n /**\n * @property {ModelSignal<MultiSelectOption[] | null>} model\n * @description\n * The model signal for two-way binding.\n */\n readonly model = model<MultiSelectOption[] | null>([]);\n\n /**\n * @property {MultiSelectOption[]} options\n * @description\n * Array of available options shown in the multiselect dropdown.\n */\n options = input<MultiSelectOption[]>([]);\n\n /**\n * @property {string} labelText\n * @description\n * Label displayed above the multiselect input.\n *\n * @default 'Select'\n */\n labelText = input<string>('Select');\n\n /**\n * @property {string} display\n * @description\n * Display mode for selected items. Examples: 'chip', 'comma'.\n *\n * @default 'chip'\n */\n display = input<string>('chip');\n\n /**\n * @property {number} maxSelectedLabels\n * @description\n * Maximum number of labels shown when multiple items are selected.\n *\n * @default 4\n */\n maxSelectedLabels = input<number>(4);\n\n /**\n * @property {string} selectedItemsLabel\n * @description\n * Label template used when multiple items are selected (supports placeholders).\n *\n * @default '{0} elementos seleccionados'\n */\n selectedItemsLabel = input<string>('{0} elementos seleccionados');\n\n /**\n * @property {string} emptyFilterMessage\n * @description\n * Message displayed when the filter returns no results.\n *\n * @default 'No hay resultados'\n */\n emptyFilterMessage = input<string>('No hay resultados');\n\n /**\n * @property {boolean} filter\n * @description\n * Enables the search/filter input inside the multiselect dropdown.\n *\n * @default true\n */\n filter = input<boolean>(true);\n\n /**\n * @property {string} filterPlaceHolder\n * @description\n * Placeholder text for the filter input.\n */\n filterPlaceHolder = input<string>('');\n\n /**\n * @property {string} id\n * @description\n * HTML id attribute for the multiselect input.\n *\n * @default 'multiselect'\n */\n id = input<string>('multiselect');\n\n /**\n * @property {string} styleClass\n * @description\n * Additional CSS class applied to the multiselect container.\n */\n styleClass = input<string>('');\n\n /**\n * @property {InputSignal<string>} errorMessage\n * @description\n * Message to display when the control is invalid and touched.\n */\n errorMessage = input<string>('');\n\n /**\n * @property {InputSignal<string>} hint\n * @description\n * Hint text to display below the input.\n */\n hint = input<string>('');\n\n /**\n * @event selectionChange\n * @description\n * Emits when the selected options change.\n * Payload: an array of selected MultiSelectOption or null.\n *\n * @example\n * <tk-multiselect (selectionChange)=\"onChange($event)\"></tk-multiselect>\n */\n selectionChange = output<MultiSelectOption[] | null>();\n\n /**\n * @event filterChange\n * @description\n * Emits the filter text when the user types in the search input.\n */\n readonly filterChange = output<string>();\n\n /**\n * @property internalOptions\n * @description\n * Computed signal that merges the current options with the selected items pool\n * to ensure selected items are always visible.\n */\n readonly internalOptions = computed(() => {\n const currentFromParent = this.options();\n const selected = this.selectionPool();\n\n const merged = [...selected, ...currentFromParent];\n const uniqueMap = new Map();\n\n merged.forEach(item => {\n if (item) uniqueMap.set(item.code, item);\n });\n\n return Array.from(uniqueMap.values());\n });\n\n /**\n * @method handleFilter\n * @description\n * Handles the filter event from the PrimeNG component and emits the filter value.\n *\n * @param event - The filter event object.\n */\n handleFilter(event: { filter: string }) {\n this.filterChange.emit(event.filter || '');\n }\n\n /**\n * @callback onChange\n * @description\n * Callback function to notify the parent component of value changes.\n */\n onChange: (value: MultiSelectOption[] | null) => void = () => {};\n\n /**\n * @callback onTouched\n * @description\n * Callback function to notify the parent component when the control is touched.\n */\n onTouched: () => void = () => {};\n\n /**\n * @method handleChange\n * @description\n * Handler forwarded from the PrimeNG MultiSelect change event.\n * Emits the selectionChange output with the selected values.\n *\n * @param event - Change event containing the `value` property with selected items.\n */\n handleChange(event: { value: MultiSelectOption[] | null }): void {\n const val = event.value || [];\n this.model.set(val);\n this.updateSelectionPool(val);\n\n this.onChange(val);\n this.selectionChange.emit(val);\n\n if (this.effectiveControl) {\n this.effectiveControl.setValue(val);\n this.effectiveControl.markAsDirty();\n this.effectiveControl.markAsTouched();\n }\n }\n\n /**\n * @method updateSelectionPool\n * @description\n * Updates the internal selection pool to ensure selected items persist\n * even if they are filtered out from the main options list.\n *\n * @param items - The items to add to the pool.\n */\n private updateSelectionPool(items: MultiSelectOption[]) {\n this.selectionPool.update(prev => {\n const combined = [...prev, ...items];\n const map = new Map();\n combined.forEach(i => map.set(i.code, i));\n return Array.from(map.values());\n });\n }\n\n /**\n * @method writeValue\n * @description\n * Writes a new value to the element.\n * Part of the ControlValueAccessor interface.\n *\n * @param value - The new value.\n */\n writeValue(value: MultiSelectOption[] | null): void {\n this.model.set(value || []);\n if (value) this.updateSelectionPool(value);\n }\n\n /**\n * @method registerOnChange\n * @description\n * Registers a callback function that is called when the control's value changes in the UI.\n * Part of the ControlValueAccessor interface.\n *\n * @param fn - The callback function.\n */\n registerOnChange(fn: (value: MultiSelectOption[] | null) => void): void {\n this.onChange = fn;\n }\n\n /**\n * @method registerOnTouched\n * @description\n * Registers a callback function that is called by the forms API on initialization to update the form control on 'blur'.\n * Part of the ControlValueAccessor interface.\n *\n * @param fn - The callback function.\n */\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n /**\n * @method effectiveControl\n * @description\n * Gets the effective FormControl associated with this component,\n * either from NgControl or the internal model.\n */\n get effectiveControl(): FormControl | null {\n return (this.ngControl?.control as FormControl) || null;\n }\n}\n","<p-floatlabel>\n <p-multiselect\n optionLabel=\"name\"\n [id]=\"id()\"\n [options]=\"options()\"\n [(ngModel)]=\"model\"\n [display]=\"display()\"\n [maxSelectedLabels]=\"maxSelectedLabels()\"\n [selectedItemsLabel]=\"selectedItemsLabel()\"\n [emptyFilterMessage]=\"emptyFilterMessage()\"\n [filter]=\"filter()\"\n [filterPlaceHolder]=\"filterPlaceHolder()\"\n [styleClass]=\"styleClass()\"\n [class.ng-invalid]=\"\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched)\n \"\n [class.ng-dirty]=\"effectiveControl?.dirty\"\n [class.ng-touched]=\"effectiveControl?.touched\"\n (onFilter)=\"handleFilter($event)\"\n (onChange)=\"handleChange($event)\">\n </p-multiselect>\n <label [for]=\"id()\">{{ labelText() }}</label>\n</p-floatlabel>\n\n<div class=\"tk-select-bottom\">\n <div class=\"tk-select-messages\">\n @if (\n effectiveControl?.invalid &&\n (effectiveControl?.dirty || effectiveControl?.touched) &&\n errorMessage()\n ) {\n <p-message severity=\"error\" size=\"small\" variant=\"simple\">{{\n errorMessage()\n }}</p-message>\n } @else if (hint()) {\n <p-message severity=\"secondary\" size=\"small\" variant=\"simple\">{{\n hint()\n }}</p-message>\n }\n </div>\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|