@masterteam/components 0.0.129 → 0.0.131

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.
Files changed (50) hide show
  1. package/fesm2022/masterteam-components-tooltip.mjs.map +1 -1
  2. package/package.json +1 -1
  3. package/fesm2022/masterteam-components-business-fields.mjs +0 -597
  4. package/fesm2022/masterteam-components-business-fields.mjs.map +0 -1
  5. package/fesm2022/masterteam-components-button-group.mjs +0 -20
  6. package/fesm2022/masterteam-components-button-group.mjs.map +0 -1
  7. package/fesm2022/masterteam-components-chip.mjs +0 -35
  8. package/fesm2022/masterteam-components-chip.mjs.map +0 -1
  9. package/fesm2022/masterteam-components-client-page-menu.mjs +0 -92
  10. package/fesm2022/masterteam-components-client-page-menu.mjs.map +0 -1
  11. package/fesm2022/masterteam-components-client-page.mjs +0 -160
  12. package/fesm2022/masterteam-components-client-page.mjs.map +0 -1
  13. package/fesm2022/masterteam-components-color-picker-field.mjs +0 -94
  14. package/fesm2022/masterteam-components-color-picker-field.mjs.map +0 -1
  15. package/fesm2022/masterteam-components-date-field.mjs +0 -93
  16. package/fesm2022/masterteam-components-date-field.mjs.map +0 -1
  17. package/fesm2022/masterteam-components-drawer.mjs +0 -69
  18. package/fesm2022/masterteam-components-drawer.mjs.map +0 -1
  19. package/fesm2022/masterteam-components-editor-field.mjs +0 -96
  20. package/fesm2022/masterteam-components-editor-field.mjs.map +0 -1
  21. package/fesm2022/masterteam-components-entities.mjs +0 -864
  22. package/fesm2022/masterteam-components-entities.mjs.map +0 -1
  23. package/fesm2022/masterteam-components-formula.mjs +0 -3116
  24. package/fesm2022/masterteam-components-formula.mjs.map +0 -1
  25. package/fesm2022/masterteam-components-list.mjs +0 -31
  26. package/fesm2022/masterteam-components-list.mjs.map +0 -1
  27. package/fesm2022/masterteam-components-progress.mjs +0 -49
  28. package/fesm2022/masterteam-components-progress.mjs.map +0 -1
  29. package/fesm2022/masterteam-components-table.mjs +0 -1153
  30. package/fesm2022/masterteam-components-table.mjs.map +0 -1
  31. package/fesm2022/masterteam-components-upload-field.mjs +0 -554
  32. package/fesm2022/masterteam-components-upload-field.mjs.map +0 -1
  33. package/fesm2022/masterteam-components-user-search-field.mjs +0 -153
  34. package/fesm2022/masterteam-components-user-search-field.mjs.map +0 -1
  35. package/types/masterteam-components-business-fields.d.ts +0 -213
  36. package/types/masterteam-components-button-group.d.ts +0 -8
  37. package/types/masterteam-components-chip.d.ts +0 -19
  38. package/types/masterteam-components-client-page-menu.d.ts +0 -35
  39. package/types/masterteam-components-client-page.d.ts +0 -56
  40. package/types/masterteam-components-color-picker-field.d.ts +0 -35
  41. package/types/masterteam-components-date-field.d.ts +0 -41
  42. package/types/masterteam-components-drawer.d.ts +0 -30
  43. package/types/masterteam-components-editor-field.d.ts +0 -34
  44. package/types/masterteam-components-entities.d.ts +0 -367
  45. package/types/masterteam-components-formula.d.ts +0 -654
  46. package/types/masterteam-components-list.d.ts +0 -18
  47. package/types/masterteam-components-progress.d.ts +0 -22
  48. package/types/masterteam-components-table.d.ts +0 -255
  49. package/types/masterteam-components-upload-field.d.ts +0 -77
  50. package/types/masterteam-components-user-search-field.d.ts +0 -61
@@ -1,864 +0,0 @@
1
- import * as i0 from '@angular/core';
2
- import { input, computed, ChangeDetectionStrategy, Component, inject, signal, effect, ElementRef, NgZone, output, Directive, model } from '@angular/core';
3
- import { TruncateTooltip } from '@masterteam/components/tooltip';
4
- import { HttpContext, HttpClient } from '@angular/common/http';
5
- import { Avatar } from '@masterteam/components/avatar';
6
- import { Button } from '@masterteam/components/button';
7
- import { SecureImagePipe, UploadField } from '@masterteam/components/upload-field';
8
- import { REQUEST_CONTEXT } from '@masterteam/components';
9
- import { Progress } from '@masterteam/components/progress';
10
- import * as i1 from '@angular/forms';
11
- import { FormsModule } from '@angular/forms';
12
- import { forkJoin, finalize, of, take, switchMap, EMPTY, map, catchError } from 'rxjs';
13
- import { CdkDrag, CdkDropList, CdkDragPlaceholder } from '@angular/cdk/drag-drop';
14
- import { DOCUMENT } from '@angular/common';
15
-
16
- const ENTITY_EMPTY_VALUE_PLACEHOLDER = '_';
17
- function isValueMissing(value) {
18
- if (value === null || value === undefined) {
19
- return true;
20
- }
21
- if (typeof value === 'string') {
22
- return value.trim().length === 0;
23
- }
24
- return false;
25
- }
26
- function displayOrPlaceholder(value) {
27
- if (isValueMissing(value)) {
28
- return ENTITY_EMPTY_VALUE_PLACEHOLDER;
29
- }
30
- return String(value);
31
- }
32
- function isEntityLabelHidden(configuration) {
33
- const config = configuration;
34
- return config?.hideLabel ?? config?.hideName ?? false;
35
- }
36
- function resolveEntityLabelPosition(configuration) {
37
- const config = configuration;
38
- return config?.labelPosition ?? config?.labelPostion ?? 'bottom';
39
- }
40
-
41
- class EntityField {
42
- label = input('', ...(ngDevMode ? [{ debugName: "label" }] : []));
43
- configuration = input(...(ngDevMode ? [undefined, { debugName: "configuration" }] : []));
44
- gap = input('compact', ...(ngDevMode ? [{ debugName: "gap" }] : []));
45
- hideLabel = computed(() => isEntityLabelHidden(this.configuration()), ...(ngDevMode ? [{ debugName: "hideLabel" }] : []));
46
- labelPosition = computed(() => resolveEntityLabelPosition(this.configuration()), ...(ngDevMode ? [{ debugName: "labelPosition" }] : []));
47
- containerClass = computed(() => {
48
- const gapClass = this.gap() === 'relaxed'
49
- ? 'gap-2'
50
- : this.gap() === 'normal'
51
- ? 'gap-1'
52
- : 'gap-0.5';
53
- const directionClass = this.labelPosition() === 'top' ? 'flex-col-reverse' : 'flex-col';
54
- return `flex min-w-0 ${directionClass} ${gapClass}`;
55
- }, ...(ngDevMode ? [{ debugName: "containerClass" }] : []));
56
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityField, deps: [], target: i0.ɵɵFactoryTarget.Component });
57
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntityField, isStandalone: true, selector: "mt-entity-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, configuration: { classPropertyName: "configuration", publicName: "configuration", isSignal: true, isRequired: false, transformFunction: null }, gap: { classPropertyName: "gap", publicName: "gap", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "block min-w-0 w-full" }, ngImport: i0, template: `
58
- <div [class]="containerClass()">
59
- <ng-content />
60
- @if (!hideLabel()) {
61
- <span
62
- class="block min-w-0 truncate text-sm text-gray-500"
63
- mtTruncateTooltip
64
- tooltipPosition="top"
65
- >
66
- {{ label() }}
67
- </span>
68
- }
69
- </div>
70
- `, isInline: true, dependencies: [{ kind: "directive", type: TruncateTooltip, selector: "[mtTruncateTooltip]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
71
- }
72
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityField, decorators: [{
73
- type: Component,
74
- args: [{
75
- selector: 'mt-entity-field',
76
- changeDetection: ChangeDetectionStrategy.OnPush,
77
- imports: [TruncateTooltip],
78
- template: `
79
- <div [class]="containerClass()">
80
- <ng-content />
81
- @if (!hideLabel()) {
82
- <span
83
- class="block min-w-0 truncate text-sm text-gray-500"
84
- mtTruncateTooltip
85
- tooltipPosition="top"
86
- >
87
- {{ label() }}
88
- </span>
89
- }
90
- </div>
91
- `,
92
- host: {
93
- class: 'block min-w-0 w-full',
94
- },
95
- }]
96
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], configuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "configuration", required: false }] }], gap: [{ type: i0.Input, args: [{ isSignal: true, alias: "gap", required: false }] }] } });
97
-
98
- class EntityText {
99
- /** Full entity data object */
100
- data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
101
- /** Individual inputs (used when data is not provided) */
102
- name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
103
- value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
104
- displayName = computed(() => this.data()?.name ?? this.name() ?? '', ...(ngDevMode ? [{ debugName: "displayName" }] : []));
105
- displayValue = computed(() => {
106
- const d = this.data();
107
- if (d) {
108
- return displayOrPlaceholder(typeof d.value === 'string' ? d.value : null);
109
- }
110
- return displayOrPlaceholder(this.value());
111
- }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
112
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityText, deps: [], target: i0.ɵɵFactoryTarget.Component });
113
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.3", type: EntityText, isStandalone: true, selector: "mt-entity-text", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n>\n <div\n class=\"min-w-0 truncate text-sm font-semibold\"\n mtTruncateTooltip\n tooltipPosition=\"top\"\n [innerHTML]=\"displayValue()\"\n ></div>\n</mt-entity-field>\n", dependencies: [{ kind: "component", type: EntityField, selector: "mt-entity-field", inputs: ["label", "configuration", "gap"] }, { kind: "directive", type: TruncateTooltip, selector: "[mtTruncateTooltip]" }] });
114
- }
115
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityText, decorators: [{
116
- type: Component,
117
- args: [{ selector: 'mt-entity-text', standalone: true, imports: [EntityField, TruncateTooltip], template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n>\n <div\n class=\"min-w-0 truncate text-sm font-semibold\"\n mtTruncateTooltip\n tooltipPosition=\"top\"\n [innerHTML]=\"displayValue()\"\n ></div>\n</mt-entity-field>\n" }]
118
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }] } });
119
-
120
- class EntityDate {
121
- /** Full entity data object */
122
- data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
123
- /** Individual inputs (used when data is not provided) */
124
- name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
125
- value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
126
- displayName = computed(() => this.data()?.name ?? this.name() ?? '', ...(ngDevMode ? [{ debugName: "displayName" }] : []));
127
- displayValue = computed(() => {
128
- const d = this.data();
129
- if (d) {
130
- return displayOrPlaceholder(typeof d.value === 'string' ? d.value : null);
131
- }
132
- return displayOrPlaceholder(this.value());
133
- }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
134
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityDate, deps: [], target: i0.ɵɵFactoryTarget.Component });
135
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.3", type: EntityDate, isStandalone: true, selector: "mt-entity-date", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n>\n <span\n class=\"block min-w-0 truncate text-sm font-semibold\"\n mtTruncateTooltip\n tooltipPosition=\"top\"\n >\n {{ displayValue() }}\n </span>\n</mt-entity-field>\n", dependencies: [{ kind: "component", type: EntityField, selector: "mt-entity-field", inputs: ["label", "configuration", "gap"] }, { kind: "directive", type: TruncateTooltip, selector: "[mtTruncateTooltip]" }] });
136
- }
137
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityDate, decorators: [{
138
- type: Component,
139
- args: [{ selector: 'mt-entity-date', standalone: true, imports: [EntityField, TruncateTooltip], template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n>\n <span\n class=\"block min-w-0 truncate text-sm font-semibold\"\n mtTruncateTooltip\n tooltipPosition=\"top\"\n >\n {{ displayValue() }}\n </span>\n</mt-entity-field>\n" }]
140
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }] } });
141
-
142
- class EntityStatus {
143
- /** Full entity data object */
144
- data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
145
- /** Individual inputs (used when data is not provided) */
146
- name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
147
- value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
148
- displayName = computed(() => this.data()?.name ?? this.name() ?? '', ...(ngDevMode ? [{ debugName: "displayName" }] : []));
149
- statusValue = computed(() => {
150
- const d = this.data();
151
- if (d && typeof d.value === 'object' && d.value !== null) {
152
- return d.value;
153
- }
154
- return this.value() ?? null;
155
- }, ...(ngDevMode ? [{ debugName: "statusValue" }] : []));
156
- badgeStyle = computed(() => {
157
- const status = this.statusValue();
158
- if (!status?.color)
159
- return {};
160
- return {
161
- color: status.color,
162
- backgroundColor: this.hexToRgba(status.color, 0.12),
163
- };
164
- }, ...(ngDevMode ? [{ debugName: "badgeStyle" }] : []));
165
- emptyLabel = ENTITY_EMPTY_VALUE_PLACEHOLDER;
166
- statusLabel = computed(() => displayOrPlaceholder(this.statusValue()?.display), ...(ngDevMode ? [{ debugName: "statusLabel" }] : []));
167
- hexToRgba(hex, alpha) {
168
- const r = parseInt(hex.slice(1, 3), 16);
169
- const g = parseInt(hex.slice(3, 5), 16);
170
- const b = parseInt(hex.slice(5, 7), 16);
171
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
172
- }
173
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityStatus, deps: [], target: i0.ɵɵFactoryTarget.Component });
174
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntityStatus, isStandalone: true, selector: "mt-entity-status", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n gap=\"normal\"\n>\n @if (statusValue(); as status) {\n <span\n class=\"inline-flex items-center px-3 py-2 rounded-md text-xs font-semibold w-fit\"\n [style]=\"badgeStyle()\"\n >\n {{ statusLabel() }}\n </span>\n } @else {\n <span\n class=\"inline-flex items-center px-3 py-2 rounded-md text-xs font-semibold w-fit text-gray-500 bg-gray-100\"\n >\n {{ emptyLabel }}\n </span>\n }\n</mt-entity-field>\n", dependencies: [{ kind: "component", type: EntityField, selector: "mt-entity-field", inputs: ["label", "configuration", "gap"] }] });
175
- }
176
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityStatus, decorators: [{
177
- type: Component,
178
- args: [{ selector: 'mt-entity-status', standalone: true, imports: [EntityField], template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n gap=\"normal\"\n>\n @if (statusValue(); as status) {\n <span\n class=\"inline-flex items-center px-3 py-2 rounded-md text-xs font-semibold w-fit\"\n [style]=\"badgeStyle()\"\n >\n {{ statusLabel() }}\n </span>\n } @else {\n <span\n class=\"inline-flex items-center px-3 py-2 rounded-md text-xs font-semibold w-fit text-gray-500 bg-gray-100\"\n >\n {{ emptyLabel }}\n </span>\n }\n</mt-entity-field>\n" }]
179
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }] } });
180
-
181
- class EntityUser {
182
- httpContext = new HttpContext().set(REQUEST_CONTEXT, {
183
- useBaseUrl: true,
184
- });
185
- /** Full entity data object */
186
- data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
187
- /** Resolved user value object from data().value */
188
- userValue = computed(() => {
189
- const val = this.data()?.value;
190
- if (val && typeof val === 'object' && 'displayName' in val) {
191
- return val;
192
- }
193
- return null;
194
- }, ...(ngDevMode ? [{ debugName: "userValue" }] : []));
195
- rawUserName = computed(() => this.userValue()?.displayName ?? null, ...(ngDevMode ? [{ debugName: "rawUserName" }] : []));
196
- userName = computed(() => displayOrPlaceholder(this.rawUserName()), ...(ngDevMode ? [{ debugName: "userName" }] : []));
197
- userPhoto = computed(() => this.userValue()?.photoUrl ?? '', ...(ngDevMode ? [{ debugName: "userPhoto" }] : []));
198
- labelText = computed(() => this.userValue()?.name ?? '', ...(ngDevMode ? [{ debugName: "labelText" }] : []));
199
- // ── Configuration-driven visibility ──
200
- config = computed(() => this.data()?.configuration ?? {}, ...(ngDevMode ? [{ debugName: "config" }] : []));
201
- showDisplayName = computed(() => this.config().showDisplayName ?? true, ...(ngDevMode ? [{ debugName: "showDisplayName" }] : []));
202
- showPhoneNumber = computed(() => this.config().showPhoneNumber ?? false, ...(ngDevMode ? [{ debugName: "showPhoneNumber" }] : []));
203
- showEmail = computed(() => this.config().showEmail ?? false, ...(ngDevMode ? [{ debugName: "showEmail" }] : []));
204
- phoneNumber = computed(() => this.userValue()?.phoneNumber ?? '', ...(ngDevMode ? [{ debugName: "phoneNumber" }] : []));
205
- email = computed(() => this.userValue()?.email ?? '', ...(ngDevMode ? [{ debugName: "email" }] : []));
206
- hasContactInfo = computed(() => (this.showPhoneNumber() && !!this.phoneNumber()) ||
207
- (this.showEmail() && !!this.email()), ...(ngDevMode ? [{ debugName: "hasContactInfo" }] : []));
208
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityUser, deps: [], target: i0.ɵɵFactoryTarget.Component });
209
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntityUser, isStandalone: true, selector: "mt-entity-user", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"flex items-center gap-2\">\r\n <mt-avatar\r\n [image]=\"\r\n userPhoto()\r\n ? (userPhoto() | secureImage: true : httpContext : 'avatar/')\r\n : ''\r\n \"\r\n [icon]=\"'user.user-01'\"\r\n styleClass=\"w-10! h-10! text-white! text-xl! bg-primary-500!\"\r\n ></mt-avatar>\r\n\r\n @if (showDisplayName()) {\r\n <div class=\"flex flex-col min-w-0 flex-1\">\r\n <span class=\"text-sm text-gray-700 truncate\">{{ userName() }}</span>\r\n @if (labelText()) {\r\n <span class=\"text-xs text-gray-500 truncate\">{{ labelText() }}</span>\r\n }\r\n </div>\r\n }\r\n\r\n @if (hasContactInfo()) {\r\n <div class=\"flex items-center gap-1 ms-auto shrink-0\">\r\n @if (showPhoneNumber() && phoneNumber()) {\r\n <a [href]=\"'tel:' + phoneNumber()\" [title]=\"phoneNumber()\">\r\n <mt-button\r\n icon=\"communication.phone\"\r\n [rounded]=\"true\"\r\n [text]=\"true\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [tooltip]=\"phoneNumber()\"\r\n />\r\n </a>\r\n }\r\n @if (showEmail() && email()) {\r\n <a [href]=\"'mailto:' + email()\" [title]=\"email()\">\r\n <mt-button\r\n icon=\"communication.mail-01\"\r\n [rounded]=\"true\"\r\n [text]=\"true\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [tooltip]=\"email()\"\r\n />\r\n </a>\r\n }\r\n </div>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "component", type: Avatar, selector: "mt-avatar", inputs: ["label", "icon", "image", "styleClass", "size", "shape", "badge", "badgeSize", "badgeSeverity"], outputs: ["onImageError"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "pipe", type: SecureImagePipe, name: "secureImage" }] });
210
- }
211
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityUser, decorators: [{
212
- type: Component,
213
- args: [{ selector: 'mt-entity-user', standalone: true, imports: [Avatar, Button, SecureImagePipe], template: "<div class=\"flex items-center gap-2\">\r\n <mt-avatar\r\n [image]=\"\r\n userPhoto()\r\n ? (userPhoto() | secureImage: true : httpContext : 'avatar/')\r\n : ''\r\n \"\r\n [icon]=\"'user.user-01'\"\r\n styleClass=\"w-10! h-10! text-white! text-xl! bg-primary-500!\"\r\n ></mt-avatar>\r\n\r\n @if (showDisplayName()) {\r\n <div class=\"flex flex-col min-w-0 flex-1\">\r\n <span class=\"text-sm text-gray-700 truncate\">{{ userName() }}</span>\r\n @if (labelText()) {\r\n <span class=\"text-xs text-gray-500 truncate\">{{ labelText() }}</span>\r\n }\r\n </div>\r\n }\r\n\r\n @if (hasContactInfo()) {\r\n <div class=\"flex items-center gap-1 ms-auto shrink-0\">\r\n @if (showPhoneNumber() && phoneNumber()) {\r\n <a [href]=\"'tel:' + phoneNumber()\" [title]=\"phoneNumber()\">\r\n <mt-button\r\n icon=\"communication.phone\"\r\n [rounded]=\"true\"\r\n [text]=\"true\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [tooltip]=\"phoneNumber()\"\r\n />\r\n </a>\r\n }\r\n @if (showEmail() && email()) {\r\n <a [href]=\"'mailto:' + email()\" [title]=\"email()\">\r\n <mt-button\r\n icon=\"communication.mail-01\"\r\n [rounded]=\"true\"\r\n [text]=\"true\"\r\n severity=\"secondary\"\r\n size=\"small\"\r\n [tooltip]=\"email()\"\r\n />\r\n </a>\r\n }\r\n </div>\r\n }\r\n</div>\r\n" }]
214
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }] } });
215
-
216
- class EntityPercentage {
217
- /** Full entity data object */
218
- data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
219
- /** Individual inputs (used when data is not provided) */
220
- name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
221
- value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
222
- rawValue = input(...(ngDevMode ? [undefined, { debugName: "rawValue" }] : []));
223
- displayName = computed(() => this.data()?.name ?? this.name() ?? '', ...(ngDevMode ? [{ debugName: "displayName" }] : []));
224
- displayValue = computed(() => {
225
- const d = this.data();
226
- if (d) {
227
- return displayOrPlaceholder(typeof d.value === 'string' ? d.value : null);
228
- }
229
- return displayOrPlaceholder(this.value());
230
- }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
231
- rawNumericValue = computed(() => this.data()?.rawValue ??
232
- this.rawValue() ??
233
- this.value() ??
234
- this.displayValue(), ...(ngDevMode ? [{ debugName: "rawNumericValue" }] : []));
235
- hasNumericValue = computed(() => {
236
- return this.parseNumericValue(this.rawNumericValue()) !== null;
237
- }, ...(ngDevMode ? [{ debugName: "hasNumericValue" }] : []));
238
- numericValue = computed(() => {
239
- const num = this.parseNumericValue(this.rawNumericValue());
240
- return num === null ? 0 : Math.min(num, 100);
241
- }, ...(ngDevMode ? [{ debugName: "numericValue" }] : []));
242
- maxValue = computed(() => {
243
- const num = this.parseNumericValue(this.rawNumericValue());
244
- if (num === null)
245
- return 100;
246
- return num > 100 ? Math.ceil(num) : 100;
247
- }, ...(ngDevMode ? [{ debugName: "maxValue" }] : []));
248
- // ── Configuration-driven visibility ──
249
- hideName = computed(() => isEntityLabelHidden(this.data()?.configuration), ...(ngDevMode ? [{ debugName: "hideName" }] : []));
250
- progressColor = computed(() => {
251
- const configuration = this.data()?.configuration;
252
- return configuration?.color?.trim() || 'primary';
253
- }, ...(ngDevMode ? [{ debugName: "progressColor" }] : []));
254
- parseNumericValue(raw) {
255
- if (isValueMissing(raw)) {
256
- return null;
257
- }
258
- const normalizedRawValue = String(raw).replace(/%/g, '').trim();
259
- if (!normalizedRawValue) {
260
- return null;
261
- }
262
- const numericValue = Number.parseFloat(normalizedRawValue);
263
- return Number.isNaN(numericValue) ? null : numericValue;
264
- }
265
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityPercentage, deps: [], target: i0.ɵɵFactoryTarget.Component });
266
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntityPercentage, isStandalone: true, selector: "mt-entity-percentage", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, rawValue: { classPropertyName: "rawValue", publicName: "rawValue", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"flex flex-col gap-1\">\r\n <div class=\"flex items-center justify-between\">\r\n @if (!hideName()) {\r\n <span class=\"text-xs font-semibold\">{{ displayName() }}</span>\r\n }\r\n <span class=\"text-xs font-bold\" [class.ms-auto]=\"hideName()\">{{\r\n displayValue()\r\n }}</span>\r\n </div>\r\n @if (hasNumericValue()) {\r\n <mt-progress\r\n [value]=\"numericValue()\"\r\n [showLabel]=\"false\"\r\n [height]=\"9\"\r\n [maxValue]=\"maxValue()\"\r\n [color]=\"progressColor()\"\r\n >\r\n </mt-progress>\r\n } @else {\r\n <div class=\"h-[9px] rounded-full bg-gray-200\"></div>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "component", type: Progress, selector: "mt-progress", inputs: ["value", "mode", "showLabel", "unit", "color", "minValue", "maxValue", "height", "circleSize", "strokeWidth", "customClass"] }] });
267
- }
268
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityPercentage, decorators: [{
269
- type: Component,
270
- args: [{ selector: 'mt-entity-percentage', standalone: true, imports: [Progress], template: "<div class=\"flex flex-col gap-1\">\r\n <div class=\"flex items-center justify-between\">\r\n @if (!hideName()) {\r\n <span class=\"text-xs font-semibold\">{{ displayName() }}</span>\r\n }\r\n <span class=\"text-xs font-bold\" [class.ms-auto]=\"hideName()\">{{\r\n displayValue()\r\n }}</span>\r\n </div>\r\n @if (hasNumericValue()) {\r\n <mt-progress\r\n [value]=\"numericValue()\"\r\n [showLabel]=\"false\"\r\n [height]=\"9\"\r\n [maxValue]=\"maxValue()\"\r\n [color]=\"progressColor()\"\r\n >\r\n </mt-progress>\r\n } @else {\r\n <div class=\"h-[9px] rounded-full bg-gray-200\"></div>\r\n }\r\n</div>\r\n" }]
271
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], rawValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "rawValue", required: false }] }] } });
272
-
273
- class EntityCurrency {
274
- /** Full entity data object */
275
- data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
276
- /** Individual inputs (used when data is not provided) */
277
- name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
278
- value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
279
- displayName = computed(() => this.data()?.name ?? this.name() ?? '', ...(ngDevMode ? [{ debugName: "displayName" }] : []));
280
- displayValue = computed(() => {
281
- const d = this.data();
282
- if (d) {
283
- return displayOrPlaceholder(typeof d.value === 'string' ? d.value : null);
284
- }
285
- return displayOrPlaceholder(this.value());
286
- }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
287
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityCurrency, deps: [], target: i0.ɵɵFactoryTarget.Component });
288
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.3", type: EntityCurrency, isStandalone: true, selector: "mt-entity-currency", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n>\n <span\n class=\"block min-w-0 truncate text-sm font-semibold\"\n mtTruncateTooltip\n tooltipPosition=\"top\"\n >\n {{ displayValue() }}\n </span>\n</mt-entity-field>\n", dependencies: [{ kind: "component", type: EntityField, selector: "mt-entity-field", inputs: ["label", "configuration", "gap"] }, { kind: "directive", type: TruncateTooltip, selector: "[mtTruncateTooltip]" }] });
289
- }
290
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityCurrency, decorators: [{
291
- type: Component,
292
- args: [{ selector: 'mt-entity-currency', standalone: true, imports: [EntityField, TruncateTooltip], template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n>\n <span\n class=\"block min-w-0 truncate text-sm font-semibold\"\n mtTruncateTooltip\n tooltipPosition=\"top\"\n >\n {{ displayValue() }}\n </span>\n</mt-entity-field>\n" }]
293
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }] } });
294
-
295
- class EntityCheckbox {
296
- /** Full entity data object */
297
- data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
298
- /** Individual inputs (used when data is not provided) */
299
- name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
300
- value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
301
- rawValue = input(...(ngDevMode ? [undefined, { debugName: "rawValue" }] : []));
302
- displayName = computed(() => this.data()?.name ?? this.name() ?? '', ...(ngDevMode ? [{ debugName: "displayName" }] : []));
303
- emptyLabel = ENTITY_EMPTY_VALUE_PLACEHOLDER;
304
- hideName = computed(() => isEntityLabelHidden(this.data()?.configuration), ...(ngDevMode ? [{ debugName: "hideName" }] : []));
305
- checkboxState = computed(() => {
306
- const raw = this.data()?.rawValue ?? this.rawValue();
307
- if (raw !== undefined && raw !== null) {
308
- return this.parseBoolean(raw);
309
- }
310
- const val = this.data()?.value ?? this.value();
311
- if (typeof val === 'string') {
312
- return this.parseBoolean(val);
313
- }
314
- return null;
315
- }, ...(ngDevMode ? [{ debugName: "checkboxState" }] : []));
316
- parseBoolean(value) {
317
- const normalized = value.trim().toLowerCase();
318
- if (!normalized.length) {
319
- return null;
320
- }
321
- if (normalized === 'true') {
322
- return true;
323
- }
324
- if (normalized === 'false') {
325
- return false;
326
- }
327
- return null;
328
- }
329
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityCheckbox, deps: [], target: i0.ɵɵFactoryTarget.Component });
330
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntityCheckbox, isStandalone: true, selector: "mt-entity-checkbox", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, rawValue: { classPropertyName: "rawValue", publicName: "rawValue", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"flex items-center gap-2\">\r\n @if (checkboxState() === true) {\r\n <svg class=\"w-5 h-5 text-green-500\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z\"\r\n clip-rule=\"evenodd\"\r\n />\r\n </svg>\r\n } @else if (checkboxState() === false) {\r\n <svg class=\"w-5 h-5 text-gray-300\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm-1-5.414l-2.293-2.293a1 1 0 011.414-1.414L10 11.172l3.879-3.879a1 1 0 111.414 1.414L10 13.414l-.707-.707-.293-.293z\"\r\n clip-rule=\"evenodd\"\r\n />\r\n </svg>\r\n } @else {\r\n <span\r\n class=\"inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-gray-100 px-1 text-[10px] font-semibold text-gray-500\"\r\n >\r\n {{ emptyLabel }}\r\n </span>\r\n }\r\n @if (!hideName()) {\r\n <span class=\"text-sm font-semibold\">{{ displayName() }}</span>\r\n }\r\n</div>\r\n" });
331
- }
332
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityCheckbox, decorators: [{
333
- type: Component,
334
- args: [{ selector: 'mt-entity-checkbox', standalone: true, template: "<div class=\"flex items-center gap-2\">\r\n @if (checkboxState() === true) {\r\n <svg class=\"w-5 h-5 text-green-500\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z\"\r\n clip-rule=\"evenodd\"\r\n />\r\n </svg>\r\n } @else if (checkboxState() === false) {\r\n <svg class=\"w-5 h-5 text-gray-300\" viewBox=\"0 0 20 20\" fill=\"currentColor\">\r\n <path\r\n fill-rule=\"evenodd\"\r\n d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm-1-5.414l-2.293-2.293a1 1 0 011.414-1.414L10 11.172l3.879-3.879a1 1 0 111.414 1.414L10 13.414l-.707-.707-.293-.293z\"\r\n clip-rule=\"evenodd\"\r\n />\r\n </svg>\r\n } @else {\r\n <span\r\n class=\"inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-gray-100 px-1 text-[10px] font-semibold text-gray-500\"\r\n >\r\n {{ emptyLabel }}\r\n </span>\r\n }\r\n @if (!hideName()) {\r\n <span class=\"text-sm font-semibold\">{{ displayName() }}</span>\r\n }\r\n</div>\r\n" }]
335
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], rawValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "rawValue", required: false }] }] } });
336
-
337
- class EntityLongText {
338
- /** Full entity data object */
339
- data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
340
- /** Individual inputs (used when data is not provided) */
341
- name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
342
- value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
343
- displayName = computed(() => this.data()?.name ?? this.name() ?? '', ...(ngDevMode ? [{ debugName: "displayName" }] : []));
344
- displayValue = computed(() => {
345
- const d = this.data();
346
- const raw = d
347
- ? typeof d.value === 'string'
348
- ? d.value
349
- : null
350
- : this.value();
351
- if (isValueMissing(raw)) {
352
- return ENTITY_EMPTY_VALUE_PLACEHOLDER;
353
- }
354
- return raw;
355
- }, ...(ngDevMode ? [{ debugName: "displayValue" }] : []));
356
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityLongText, deps: [], target: i0.ɵɵFactoryTarget.Component });
357
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.3", type: EntityLongText, isStandalone: true, selector: "mt-entity-long-text", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n>\n <div class=\"text-sm font-semibold\" [innerHTML]=\"displayValue()\"></div>\n</mt-entity-field>\n", dependencies: [{ kind: "component", type: EntityField, selector: "mt-entity-field", inputs: ["label", "configuration", "gap"] }] });
358
- }
359
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityLongText, decorators: [{
360
- type: Component,
361
- args: [{ selector: 'mt-entity-long-text', standalone: true, imports: [EntityField], template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n>\n <div class=\"text-sm font-semibold\" [innerHTML]=\"displayValue()\"></div>\n</mt-entity-field>\n" }]
362
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }] } });
363
-
364
- class EntityLookup {
365
- /** Full entity data object */
366
- data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
367
- /** Individual inputs (used when data is not provided) */
368
- name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
369
- value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
370
- displayName = computed(() => this.data()?.name ?? this.name() ?? '', ...(ngDevMode ? [{ debugName: "displayName" }] : []));
371
- lookupValue = computed(() => {
372
- const d = this.data();
373
- if (d && typeof d.value === 'object' && d.value !== null) {
374
- return d.value;
375
- }
376
- return this.value() ?? null;
377
- }, ...(ngDevMode ? [{ debugName: "lookupValue" }] : []));
378
- badgeStyle = computed(() => {
379
- const lookup = this.lookupValue();
380
- if (!lookup?.color)
381
- return {};
382
- return {
383
- color: lookup.color,
384
- backgroundColor: this.hexToRgba(lookup.color, 0.12),
385
- };
386
- }, ...(ngDevMode ? [{ debugName: "badgeStyle" }] : []));
387
- emptyLabel = ENTITY_EMPTY_VALUE_PLACEHOLDER;
388
- lookupLabel = computed(() => displayOrPlaceholder(this.lookupValue()?.display), ...(ngDevMode ? [{ debugName: "lookupLabel" }] : []));
389
- hexToRgba(hex, alpha) {
390
- const r = parseInt(hex.slice(1, 3), 16);
391
- const g = parseInt(hex.slice(3, 5), 16);
392
- const b = parseInt(hex.slice(5, 7), 16);
393
- return `rgba(${r}, ${g}, ${b}, ${alpha})`;
394
- }
395
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityLookup, deps: [], target: i0.ɵɵFactoryTarget.Component });
396
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntityLookup, isStandalone: true, selector: "mt-entity-lookup", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n gap=\"normal\"\n>\n @if (lookupValue(); as lookup) {\n <span\n class=\"inline-flex items-center px-3 py-2 rounded-md text-xs font-semibold w-fit\"\n [style]=\"badgeStyle()\"\n >\n {{ lookupLabel() }}\n </span>\n } @else {\n <span\n class=\"inline-flex items-center px-3 py-2 rounded-md text-xs font-semibold w-fit text-gray-500 bg-gray-100\"\n >\n {{ emptyLabel }}\n </span>\n }\n</mt-entity-field>\n", dependencies: [{ kind: "component", type: EntityField, selector: "mt-entity-field", inputs: ["label", "configuration", "gap"] }] });
397
- }
398
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityLookup, decorators: [{
399
- type: Component,
400
- args: [{ selector: 'mt-entity-lookup', standalone: true, imports: [EntityField], template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n gap=\"normal\"\n>\n @if (lookupValue(); as lookup) {\n <span\n class=\"inline-flex items-center px-3 py-2 rounded-md text-xs font-semibold w-fit\"\n [style]=\"badgeStyle()\"\n >\n {{ lookupLabel() }}\n </span>\n } @else {\n <span\n class=\"inline-flex items-center px-3 py-2 rounded-md text-xs font-semibold w-fit text-gray-500 bg-gray-100\"\n >\n {{ emptyLabel }}\n </span>\n }\n</mt-entity-field>\n" }]
401
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }] } });
402
-
403
- class EntityAttachment {
404
- data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : []));
405
- name = input(...(ngDevMode ? [undefined, { debugName: "name" }] : []));
406
- shape = input('default', ...(ngDevMode ? [{ debugName: "shape" }] : []));
407
- value = input(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
408
- endPoint = input('uploader', ...(ngDevMode ? [{ debugName: "endPoint" }] : []));
409
- context = input(undefined, ...(ngDevMode ? [{ debugName: "context" }] : []));
410
- httpClient = inject(HttpClient);
411
- displayName = computed(() => this.data()?.name ?? this.name() ?? '', ...(ngDevMode ? [{ debugName: "displayName" }] : []));
412
- loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : []));
413
- attachments = signal([], ...(ngDevMode ? [{ debugName: "attachments" }] : []));
414
- attachmentReferences = computed(() => this.normalizeAttachmentValue(this.data()?.value ?? this.value()), ...(ngDevMode ? [{ debugName: "attachmentReferences" }] : []));
415
- uploadValue = computed(() => {
416
- const references = this.attachmentReferences().map((reference) => {
417
- if (typeof reference === 'string') {
418
- return reference.trim();
419
- }
420
- if (reference.fileName) {
421
- return reference;
422
- }
423
- return reference.id?.trim() || reference;
424
- });
425
- if (!references.length) {
426
- return null;
427
- }
428
- return references.length === 1 ? references[0] : references;
429
- }, ...(ngDevMode ? [{ debugName: "uploadValue" }] : []));
430
- hasAttachments = computed(() => this.shape() === 'compact'
431
- ? this.attachments().length > 0
432
- : this.uploadValue() != null, ...(ngDevMode ? [{ debugName: "hasAttachments" }] : []));
433
- isMultiple = computed(() => this.attachmentReferences().length > 1, ...(ngDevMode ? [{ debugName: "isMultiple" }] : []));
434
- empty = '-';
435
- constructor() {
436
- effect((onCleanup) => {
437
- if (this.shape() !== 'compact') {
438
- this.loading.set(false);
439
- this.attachments.set([]);
440
- return;
441
- }
442
- const references = this.attachmentReferences();
443
- if (!references.length) {
444
- this.loading.set(false);
445
- this.attachments.set([]);
446
- return;
447
- }
448
- const shouldFetchMetadata = references.some((reference) => this.requiresMetadataRequest(reference));
449
- if (!shouldFetchMetadata) {
450
- this.attachments.set(references.filter(this.isAttachmentItemValue).map((reference) => ({
451
- ...reference,
452
- name: reference.name ??
453
- reference.fileName ??
454
- reference.id ??
455
- reference.name,
456
- extension: this.resolveExtension(reference),
457
- })));
458
- this.loading.set(false);
459
- return;
460
- }
461
- this.loading.set(true);
462
- const sub = forkJoin(references.map((reference) => this.resolveAttachment$(reference)))
463
- .pipe(finalize(() => this.loading.set(false)))
464
- .subscribe((attachments) => {
465
- this.attachments.set(attachments.filter((attachment) => attachment != null));
466
- });
467
- onCleanup(() => sub.unsubscribe());
468
- });
469
- }
470
- attachmentTrackBy(index, attachment) {
471
- return (attachment.id ?? attachment.fileName ?? attachment.name ?? String(index));
472
- }
473
- attachmentTooltip(attachment) {
474
- return (attachment.name ?? attachment.fileName ?? attachment.id ?? 'Attachment');
475
- }
476
- attachmentIcon(attachment) {
477
- const extension = this.resolveExtension(attachment);
478
- const contentType = attachment.contentType?.toLowerCase() ?? '';
479
- if (contentType.startsWith('image/')) {
480
- return 'image.image-03';
481
- }
482
- switch (extension) {
483
- case '.pdf':
484
- return 'file.file-06';
485
- case '.doc':
486
- case '.docx':
487
- case '.txt':
488
- case '.rtf':
489
- return 'file.file-04';
490
- case '.xls':
491
- case '.xlsx':
492
- case '.csv':
493
- return 'file.file-03';
494
- case '.ppt':
495
- case '.pptx':
496
- return 'file.file-05';
497
- default:
498
- return 'file.clipboard-attachment';
499
- }
500
- }
501
- onCompactAttachmentClick(event, attachment) {
502
- event.stopPropagation();
503
- this.downloadAttachment(attachment);
504
- }
505
- downloadAttachment(attachment) {
506
- const resolvedAttachment$ = this.requiresMetadataRequest(attachment)
507
- ? this.resolveAttachment$(attachment)
508
- : of(this.normalizeAttachmentItem(attachment));
509
- resolvedAttachment$
510
- .pipe(take(1), switchMap((resolvedAttachment) => {
511
- if (!resolvedAttachment?.fileName) {
512
- return EMPTY;
513
- }
514
- return this.httpClient
515
- .get(`${this.endPoint()}/${resolvedAttachment.fileName}`, {
516
- responseType: 'blob',
517
- context: this.context(),
518
- })
519
- .pipe(take(1), map((blob) => ({
520
- attachment: resolvedAttachment,
521
- blob,
522
- })));
523
- }))
524
- .subscribe(({ attachment, blob }) => {
525
- const downloadBlob = new Blob([blob], {
526
- type: attachment.contentType || blob.type || 'application/octet-stream',
527
- });
528
- const objectUrl = window.URL.createObjectURL(downloadBlob);
529
- const anchor = document.createElement('a');
530
- anchor.href = objectUrl;
531
- anchor.download =
532
- attachment.name ??
533
- attachment.fileName ??
534
- attachment.id ??
535
- 'attachment';
536
- anchor.click();
537
- window.URL.revokeObjectURL(objectUrl);
538
- });
539
- }
540
- resolveAttachment$(reference) {
541
- const normalizedAttachment = this.normalizeAttachmentItem(reference);
542
- if (!this.requiresMetadataRequest(reference)) {
543
- return of(normalizedAttachment);
544
- }
545
- const attachmentId = typeof reference === 'string' ? reference.trim() : reference.id?.trim();
546
- if (!attachmentId) {
547
- return of(normalizedAttachment);
548
- }
549
- return this.httpClient
550
- .get(`${this.endPoint()}/${attachmentId}/metaData`, {
551
- context: this.context(),
552
- })
553
- .pipe(take(1), map((response) => this.normalizeAttachmentItem(response.data)), catchError(() => of(normalizedAttachment)));
554
- }
555
- normalizeAttachmentValue(value) {
556
- if (value === null || value === undefined) {
557
- return [];
558
- }
559
- if (Array.isArray(value)) {
560
- return value.flatMap((item) => this.normalizeAttachmentValue(item));
561
- }
562
- if (typeof value === 'string') {
563
- const trimmedValue = value.trim();
564
- if (!trimmedValue || trimmedValue === '[]') {
565
- return [];
566
- }
567
- if ((trimmedValue.startsWith('[') && trimmedValue.endsWith(']')) ||
568
- (trimmedValue.startsWith('{') && trimmedValue.endsWith('}'))) {
569
- try {
570
- return this.normalizeAttachmentValue(JSON.parse(trimmedValue));
571
- }
572
- catch {
573
- return [trimmedValue];
574
- }
575
- }
576
- return [trimmedValue];
577
- }
578
- if (typeof value === 'object') {
579
- return [value];
580
- }
581
- return [];
582
- }
583
- normalizeAttachmentItem(value) {
584
- if (!value) {
585
- return null;
586
- }
587
- if (typeof value === 'string') {
588
- const trimmedValue = value.trim();
589
- return trimmedValue
590
- ? {
591
- id: trimmedValue,
592
- name: trimmedValue,
593
- }
594
- : null;
595
- }
596
- const normalizedAttachment = {
597
- ...value,
598
- name: value.name ?? value.fileName ?? value.id ?? '',
599
- extension: this.resolveExtension(value),
600
- };
601
- return normalizedAttachment.name ||
602
- normalizedAttachment.fileName ||
603
- normalizedAttachment.id
604
- ? normalizedAttachment
605
- : null;
606
- }
607
- requiresMetadataRequest(reference) {
608
- if (typeof reference === 'string') {
609
- return reference.trim().length > 0;
610
- }
611
- return !!reference.id?.trim() && !reference.fileName;
612
- }
613
- isAttachmentItemValue(reference) {
614
- return typeof reference === 'object' && reference != null;
615
- }
616
- resolveExtension(value) {
617
- const explicitExtension = value.extension?.trim();
618
- if (explicitExtension) {
619
- return explicitExtension.startsWith('.')
620
- ? explicitExtension.toLowerCase()
621
- : `.${explicitExtension.toLowerCase()}`;
622
- }
623
- const fileName = value.fileName ?? value.name;
624
- if (!fileName || !fileName.includes('.')) {
625
- return undefined;
626
- }
627
- return `.${fileName.split('.').pop().toLowerCase()}`;
628
- }
629
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityAttachment, deps: [], target: i0.ɵɵFactoryTarget.Component });
630
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntityAttachment, isStandalone: true, selector: "mt-entity-attachment", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, shape: { classPropertyName: "shape", publicName: "shape", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, endPoint: { classPropertyName: "endPoint", publicName: "endPoint", isSignal: true, isRequired: false, transformFunction: null }, context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n gap=\"relaxed\"\n>\n @if (hasAttachments()) {\n @if (shape() === \"compact\") {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (\n attachment of attachments();\n track attachmentTrackBy($index, attachment)\n ) {\n <mt-button\n iconPos=\"top\"\n size=\"small\"\n severity=\"secondary\"\n variant=\"outlined\"\n [icon]=\"attachmentIcon(attachment)\"\n [tooltip]=\"attachmentTooltip(attachment)\"\n styleClass=\"h-9! w-9! rounded-lg!\"\n (onClick)=\"onCompactAttachmentClick($event, attachment)\"\n />\n }\n </div>\n } @else {\n <mt-upload-field\n class=\"w-full\"\n [ngModel]=\"uploadValue()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [shape]=\"'card'\"\n [multiple]=\"isMultiple()\"\n [readonly]=\"true\"\n [endPoint]=\"endPoint()\"\n [context]=\"context()\"\n />\n }\n } @else {\n <span class=\"text-sm font-semibold\">{{ empty }}</span>\n }\n</mt-entity-field>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: UploadField, selector: "mt-upload-field", inputs: ["label", "title", "description", "endPoint", "size", "userImgClass", "shape", "multiple", "accept", "isDragging", "fileSizeLimit", "readonly", "context"], outputs: ["isDraggingChange", "onChange"] }, { kind: "component", type: Button, selector: "mt-button", inputs: ["icon", "label", "tooltip", "class", "type", "styleClass", "severity", "badge", "variant", "badgeSeverity", "size", "iconPos", "autofocus", "fluid", "raised", "rounded", "text", "plain", "outlined", "link", "disabled", "loading", "pInputs"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "component", type: EntityField, selector: "mt-entity-field", inputs: ["label", "configuration", "gap"] }] });
631
- }
632
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityAttachment, decorators: [{
633
- type: Component,
634
- args: [{ selector: 'mt-entity-attachment', standalone: true, imports: [FormsModule, UploadField, Button, EntityField], template: "<mt-entity-field\n [label]=\"displayName()\"\n [configuration]=\"data()?.configuration\"\n gap=\"relaxed\"\n>\n @if (hasAttachments()) {\n @if (shape() === \"compact\") {\n <div class=\"flex flex-wrap items-center gap-2\">\n @for (\n attachment of attachments();\n track attachmentTrackBy($index, attachment)\n ) {\n <mt-button\n iconPos=\"top\"\n size=\"small\"\n severity=\"secondary\"\n variant=\"outlined\"\n [icon]=\"attachmentIcon(attachment)\"\n [tooltip]=\"attachmentTooltip(attachment)\"\n styleClass=\"h-9! w-9! rounded-lg!\"\n (onClick)=\"onCompactAttachmentClick($event, attachment)\"\n />\n }\n </div>\n } @else {\n <mt-upload-field\n class=\"w-full\"\n [ngModel]=\"uploadValue()\"\n [ngModelOptions]=\"{ standalone: true }\"\n [shape]=\"'card'\"\n [multiple]=\"isMultiple()\"\n [readonly]=\"true\"\n [endPoint]=\"endPoint()\"\n [context]=\"context()\"\n />\n }\n } @else {\n <span class=\"text-sm font-semibold\">{{ empty }}</span>\n }\n</mt-entity-field>\n" }]
635
- }], ctorParameters: () => [], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], shape: [{ type: i0.Input, args: [{ isSignal: true, alias: "shape", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], endPoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "endPoint", required: false }] }], context: [{ type: i0.Input, args: [{ isSignal: true, alias: "context", required: false }] }] } });
636
-
637
- class EntityPreview {
638
- /** Single entity data to display */
639
- data = input.required(...(ngDevMode ? [{ debugName: "data" }] : []));
640
- attachmentShape = input('default', ...(ngDevMode ? [{ debugName: "attachmentShape" }] : []));
641
- previewType = computed(() => {
642
- const viewType = this.data().viewType;
643
- return viewType === 'LookupMatrix' ? 'Lookup' : viewType;
644
- }, ...(ngDevMode ? [{ debugName: "previewType" }] : []));
645
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityPreview, deps: [], target: i0.ɵɵFactoryTarget.Component });
646
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntityPreview, isStandalone: true, selector: "mt-entity-preview", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null }, attachmentShape: { classPropertyName: "attachmentShape", publicName: "attachmentShape", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "w-full" }, ngImport: i0, template: "@switch (previewType()) {\r\n @case (\"Text\") {\r\n <mt-entity-text [data]=\"data()\" />\r\n }\r\n @case (\"LongText\") {\r\n <mt-entity-long-text [data]=\"data()\" />\r\n }\r\n @case (\"Date\") {\r\n <mt-entity-date [data]=\"data()\" />\r\n }\r\n @case (\"DateTime\") {\r\n <mt-entity-date [data]=\"data()\" />\r\n }\r\n @case (\"User\") {\r\n <mt-entity-user [data]=\"data()\" />\r\n }\r\n @case (\"Percentage\") {\r\n <mt-entity-percentage [data]=\"data()\" />\r\n }\r\n @case (\"Currency\") {\r\n <mt-entity-currency [data]=\"data()\" />\r\n }\r\n @case (\"Checkbox\") {\r\n <mt-entity-checkbox [data]=\"data()\" />\r\n }\r\n @case (\"Lookup\") {\r\n <mt-entity-lookup [data]=\"data()\" />\r\n }\r\n @case (\"Status\") {\r\n <mt-entity-status [data]=\"data()\" />\r\n }\r\n @case (\"Attachment\") {\r\n <mt-entity-attachment [data]=\"data()\" [shape]=\"attachmentShape()\" />\r\n }\r\n @default {\r\n <mt-entity-text [data]=\"data()\" />\r\n }\r\n}\r\n", dependencies: [{ kind: "component", type: EntityText, selector: "mt-entity-text", inputs: ["data", "name", "value"] }, { kind: "component", type: EntityLongText, selector: "mt-entity-long-text", inputs: ["data", "name", "value"] }, { kind: "component", type: EntityDate, selector: "mt-entity-date", inputs: ["data", "name", "value"] }, { kind: "component", type: EntityUser, selector: "mt-entity-user", inputs: ["data"] }, { kind: "component", type: EntityPercentage, selector: "mt-entity-percentage", inputs: ["data", "name", "value", "rawValue"] }, { kind: "component", type: EntityCurrency, selector: "mt-entity-currency", inputs: ["data", "name", "value"] }, { kind: "component", type: EntityCheckbox, selector: "mt-entity-checkbox", inputs: ["data", "name", "value", "rawValue"] }, { kind: "component", type: EntityLookup, selector: "mt-entity-lookup", inputs: ["data", "name", "value"] }, { kind: "component", type: EntityAttachment, selector: "mt-entity-attachment", inputs: ["data", "name", "shape", "value", "endPoint", "context"] }, { kind: "component", type: EntityStatus, selector: "mt-entity-status", inputs: ["data", "name", "value"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
647
- }
648
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntityPreview, decorators: [{
649
- type: Component,
650
- args: [{ selector: 'mt-entity-preview', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
651
- EntityText,
652
- EntityLongText,
653
- EntityDate,
654
- EntityUser,
655
- EntityPercentage,
656
- EntityCurrency,
657
- EntityCheckbox,
658
- EntityLookup,
659
- EntityAttachment,
660
- EntityStatus,
661
- ], host: {
662
- class: 'w-full',
663
- }, template: "@switch (previewType()) {\r\n @case (\"Text\") {\r\n <mt-entity-text [data]=\"data()\" />\r\n }\r\n @case (\"LongText\") {\r\n <mt-entity-long-text [data]=\"data()\" />\r\n }\r\n @case (\"Date\") {\r\n <mt-entity-date [data]=\"data()\" />\r\n }\r\n @case (\"DateTime\") {\r\n <mt-entity-date [data]=\"data()\" />\r\n }\r\n @case (\"User\") {\r\n <mt-entity-user [data]=\"data()\" />\r\n }\r\n @case (\"Percentage\") {\r\n <mt-entity-percentage [data]=\"data()\" />\r\n }\r\n @case (\"Currency\") {\r\n <mt-entity-currency [data]=\"data()\" />\r\n }\r\n @case (\"Checkbox\") {\r\n <mt-entity-checkbox [data]=\"data()\" />\r\n }\r\n @case (\"Lookup\") {\r\n <mt-entity-lookup [data]=\"data()\" />\r\n }\r\n @case (\"Status\") {\r\n <mt-entity-status [data]=\"data()\" />\r\n }\r\n @case (\"Attachment\") {\r\n <mt-entity-attachment [data]=\"data()\" [shape]=\"attachmentShape()\" />\r\n }\r\n @default {\r\n <mt-entity-text [data]=\"data()\" />\r\n }\r\n}\r\n" }]
664
- }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: true }] }], attachmentShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachmentShape", required: false }] }] } });
665
-
666
- class EntitiesPreview {
667
- /** Array of entity data to display */
668
- entities = input.required(...(ngDevMode ? [{ debugName: "entities" }] : []));
669
- attachmentShape = input('default', ...(ngDevMode ? [{ debugName: "attachmentShape" }] : []));
670
- /** Entities sorted by order */
671
- sortedEntities = computed(() => [...this.entities()].sort((a, b) => (a.order ?? 0) - (b.order ?? 0)), ...(ngDevMode ? [{ debugName: "sortedEntities" }] : []));
672
- /** Returns the grid-column span for a given entity size (1-24) */
673
- getColSpan(entity) {
674
- const size = entity.configuration?.size ?? 8;
675
- return `span ${size}`;
676
- }
677
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntitiesPreview, deps: [], target: i0.ɵɵFactoryTarget.Component });
678
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntitiesPreview, isStandalone: true, selector: "mt-entities-preview", inputs: { entities: { classPropertyName: "entities", publicName: "entities", isSignal: true, isRequired: true, transformFunction: null }, attachmentShape: { classPropertyName: "attachmentShape", publicName: "attachmentShape", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"grid grid-cols-24 gap-x-3 gap-y-5\">\r\n @for (entity of sortedEntities(); track $index) {\r\n <div\r\n class=\"min-w-0 flex items-center p-3\"\r\n [class.border]=\"entity.configuration?.showBorder\"\r\n [class.border-dashed]=\"entity.configuration?.showBorder\"\r\n [class.border-gray-200]=\"entity.configuration?.showBorder\"\r\n [class.rounded-lg]=\"entity.configuration?.showBorder\"\r\n [style.grid-column]=\"getColSpan(entity)\"\r\n >\r\n <mt-entity-preview\r\n [data]=\"entity\"\r\n [attachmentShape]=\"attachmentShape()\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n", dependencies: [{ kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }] });
679
- }
680
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntitiesPreview, decorators: [{
681
- type: Component,
682
- args: [{ selector: 'mt-entities-preview', standalone: true, imports: [EntityPreview], template: "<div class=\"grid grid-cols-24 gap-x-3 gap-y-5\">\r\n @for (entity of sortedEntities(); track $index) {\r\n <div\r\n class=\"min-w-0 flex items-center p-3\"\r\n [class.border]=\"entity.configuration?.showBorder\"\r\n [class.border-dashed]=\"entity.configuration?.showBorder\"\r\n [class.border-gray-200]=\"entity.configuration?.showBorder\"\r\n [class.rounded-lg]=\"entity.configuration?.showBorder\"\r\n [style.grid-column]=\"getColSpan(entity)\"\r\n >\r\n <mt-entity-preview\r\n [data]=\"entity\"\r\n [attachmentShape]=\"attachmentShape()\"\r\n />\r\n </div>\r\n }\r\n</div>\r\n" }]
683
- }], propDecorators: { entities: [{ type: i0.Input, args: [{ isSignal: true, alias: "entities", required: true }] }], attachmentShape: [{ type: i0.Input, args: [{ isSignal: true, alias: "attachmentShape", required: false }] }] } });
684
-
685
- /**
686
- * Base class that encapsulates all entity resize-via-drag logic.
687
- *
688
- * Extend this directive in any component that needs column-resize behaviour
689
- * on a 24-column CSS grid. The subclass must:
690
- * - Provide a `model.required<EntityData[]>()` (or equivalent) for the
691
- * entity list so `updateEntitySize()` can be called after resize.
692
- * - Contain a `.grid` element (or override `getGridElement()`).
693
- *
694
- * Resize flow:
695
- * 1. `onResizeStart(event, entity)` — called from a mousedown on the handle
696
- * 2. mousemove → snaps to nearest column, updates `resizePreviewSize`
697
- * 3. mouseup → emits `entityResized` with previous & new size
698
- */
699
- class EntitiesResizeBase {
700
- elRef = inject(ElementRef);
701
- zone = inject(NgZone);
702
- doc = inject(DOCUMENT);
703
- /** Emits when an entity is resized via the drag handle */
704
- entityResized = output();
705
- // ── Resize state ──
706
- /** The entity currently being resized (null when idle) */
707
- resizingEntity = signal(null, ...(ngDevMode ? [{ debugName: "resizingEntity" }] : []));
708
- /** Live preview size while dragging */
709
- resizePreviewSize = signal(null, ...(ngDevMode ? [{ debugName: "resizePreviewSize" }] : []));
710
- /** Bound listeners kept for cleanup */
711
- _onMouseMove = null;
712
- _onMouseUp = null;
713
- // ── Public API ──
714
- /**
715
- * Returns the grid element used to compute column widths.
716
- * Override if the grid selector differs.
717
- */
718
- getGridElement() {
719
- return this.elRef.nativeElement.querySelector('.grid');
720
- }
721
- /**
722
- * Returns the grid-column span string for a given entity.
723
- * While resizing the active entity, returns the preview size.
724
- */
725
- getResizeColSpan(entity) {
726
- if (this.resizingEntity() === entity && this.resizePreviewSize() !== null) {
727
- return `span ${this.resizePreviewSize()}`;
728
- }
729
- const size = entity.configuration?.size ?? 8;
730
- return `span ${size}`;
731
- }
732
- /** Starts a resize operation from the right-edge handle */
733
- onResizeStart(event, entity) {
734
- // Prevent the drag-drop from starting
735
- event.preventDefault();
736
- event.stopPropagation();
737
- const gridEl = this.getGridElement();
738
- if (!gridEl)
739
- return;
740
- const gridRect = gridEl.getBoundingClientRect();
741
- const gridWidth = gridRect.width;
742
- const columnWidth = gridWidth / 24;
743
- const previousSize = entity.configuration?.size ?? 8;
744
- // Left edge of the entity cell
745
- const cellEl = event.target.closest('.entity-cell');
746
- if (!cellEl)
747
- return;
748
- const cellRect = cellEl.getBoundingClientRect();
749
- const isRtl = this.doc.documentElement.getAttribute('dir') === 'rtl' ||
750
- getComputedStyle(this.doc.documentElement).direction === 'rtl';
751
- this.resizingEntity.set(entity);
752
- this.resizePreviewSize.set(previousSize);
753
- // Run mouse listeners outside Angular zone for performance
754
- this.zone.runOutsideAngular(() => {
755
- this._onMouseMove = (e) => {
756
- // In RTL the logical end is the left edge; dragging left widens the cell
757
- const rawWidth = isRtl
758
- ? cellRect.right - e.clientX
759
- : e.clientX - cellRect.left;
760
- // Snap to nearest full column (min 1, max 12)
761
- let cols = Math.round(rawWidth / columnWidth);
762
- cols = Math.max(1, Math.min(24, cols));
763
- const current = this.resizePreviewSize();
764
- if (current !== cols) {
765
- this.zone.run(() => this.resizePreviewSize.set(cols));
766
- }
767
- };
768
- this._onMouseUp = () => {
769
- this._cleanupListeners();
770
- const newSize = this.resizePreviewSize();
771
- this.resizingEntity.set(null);
772
- this.resizePreviewSize.set(null);
773
- if (newSize !== previousSize) {
774
- this.zone.run(() => {
775
- this.onResizeComplete(entity, previousSize, newSize);
776
- });
777
- }
778
- };
779
- this.doc.addEventListener('mousemove', this._onMouseMove);
780
- this.doc.addEventListener('mouseup', this._onMouseUp, { once: true });
781
- });
782
- }
783
- /** Removes global mouse listeners */
784
- _cleanupListeners() {
785
- if (this._onMouseMove) {
786
- this.doc.removeEventListener('mousemove', this._onMouseMove);
787
- this._onMouseMove = null;
788
- }
789
- if (this._onMouseUp) {
790
- this.doc.removeEventListener('mouseup', this._onMouseUp);
791
- this._onMouseUp = null;
792
- }
793
- }
794
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntitiesResizeBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
795
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.3", type: EntitiesResizeBase, isStandalone: true, outputs: { entityResized: "entityResized" }, ngImport: i0 });
796
- }
797
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntitiesResizeBase, decorators: [{
798
- type: Directive
799
- }], propDecorators: { entityResized: [{ type: i0.Output, args: ["entityResized"] }] } });
800
-
801
- class EntitiesManage extends EntitiesResizeBase {
802
- /** Array of entity data – supports two-way binding to keep order in sync */
803
- entities = model.required(...(ngDevMode ? [{ debugName: "entities" }] : []));
804
- /** Emits the reordered entities array after each drag-drop */
805
- entitiesReordered = output();
806
- /** Entities sorted by their order field */
807
- sortedEntities = computed(() => [...this.entities()].sort((a, b) => (a.order ?? 0) - (b.order ?? 0)), ...(ngDevMode ? [{ debugName: "sortedEntities" }] : []));
808
- /** Returns the grid-column span for a given entity size (1-24) */
809
- getColSpan(entity) {
810
- return this.getResizeColSpan(entity);
811
- }
812
- /** Handle drag-drop reorder */
813
- onDrop(event) {
814
- if (event.previousIndex === event.currentIndex)
815
- return;
816
- const items = [...this.sortedEntities()];
817
- const [moved] = items.splice(event.previousIndex, 1);
818
- items.splice(event.currentIndex, 0, moved);
819
- // Reassign order based on new positions
820
- const reordered = items.map((item, index) => ({
821
- ...item,
822
- order: index + 1,
823
- }));
824
- // Update the model (two-way binding)
825
- this.entities.set(reordered);
826
- // Emit the reordered list
827
- this.entitiesReordered.emit(reordered);
828
- }
829
- // ── Resize completion (from EntitiesResizeBase) ──
830
- onResizeComplete(entity, previousSize, newSize) {
831
- // Update entity in the list
832
- const updated = this.entities().map((e) => e === entity
833
- ? {
834
- ...e,
835
- configuration: {
836
- ...e.configuration,
837
- size: newSize,
838
- },
839
- }
840
- : e);
841
- this.entities.set(updated);
842
- this.entityResized.emit({
843
- entity: {
844
- ...entity,
845
- configuration: { ...entity.configuration, size: newSize },
846
- },
847
- previousSize,
848
- newSize,
849
- });
850
- }
851
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntitiesManage, deps: null, target: i0.ɵɵFactoryTarget.Component });
852
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.3", type: EntitiesManage, isStandalone: true, selector: "mt-entities-manage", inputs: { entities: { classPropertyName: "entities", publicName: "entities", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { entities: "entitiesChange", entitiesReordered: "entitiesReordered" }, usesInheritance: true, ngImport: i0, template: "<div\r\n cdkDropList\r\n cdkDropListOrientation=\"mixed\"\r\n [cdkDropListData]=\"sortedEntities()\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"grid grid-cols-24 gap-x-4 gap-y-6\"\r\n>\r\n @for (entity of sortedEntities(); track entity.order) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"entity\"\r\n class=\"entity-cell group relative min-w-0 flex items-center p-3 cursor-grab active:cursor-grabbing\"\r\n [class.border]=\"entity.configuration?.showBorder\"\r\n [class.border-dashed]=\"entity.configuration?.showBorder\"\r\n [class.border-gray-200]=\"entity.configuration?.showBorder\"\r\n [class.rounded-lg]=\"entity.configuration?.showBorder\"\r\n [class.resizing]=\"resizingEntity() === entity\"\r\n [style.grid-column]=\"getColSpan(entity)\"\r\n >\r\n <!-- Drag placeholder -->\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"h-full min-h-12 bg-black/10 rounded-xl\"\r\n [style.grid-column]=\"getColSpan(entity)\"\r\n ></div>\r\n\r\n <mt-entity-preview [data]=\"entity\" class=\"flex-1 min-w-0\" />\r\n\r\n <!-- Resize handle (right edge) -->\r\n <div class=\"resize-handle\" (mousedown)=\"onResizeStart($event, entity)\">\r\n <div class=\"resize-handle-bar\"></div>\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".cdk-drag{cursor:grab}.cdk-drag:active{cursor:grabbing}.cdk-drag-preview{cursor:grabbing;overflow:hidden}.cdk-drag-placeholder{opacity:.5}.cdk-drop-list-dragging .cdk-drag{cursor:grabbing}.entity-cell{position:relative}.resize-handle{position:absolute;top:0;inset-inline-end:-4px;width:8px;height:100%;cursor:col-resize;z-index:10;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .15s ease}.entity-cell:hover .resize-handle,.entity-cell.resizing .resize-handle{opacity:1}.resize-handle-bar{width:3px;height:24px;border-radius:2px;background-color:var(--p-primary-color, #6366f1);transition:height .15s ease,background-color .15s ease}.resize-handle:hover .resize-handle-bar{height:36px;background-color:var(--p-primary-color, #4f46e5)}.entity-cell.resizing{outline:2px dashed var(--p-primary-color, #6366f1);outline-offset:-1px;border-radius:8px;-webkit-user-select:none;user-select:none}\n"], dependencies: [{ kind: "component", type: EntityPreview, selector: "mt-entity-preview", inputs: ["data", "attachmentShape"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDragPlaceholder, selector: "ng-template[cdkDragPlaceholder]", inputs: ["data"] }] });
853
- }
854
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.3", ngImport: i0, type: EntitiesManage, decorators: [{
855
- type: Component,
856
- args: [{ selector: 'mt-entities-manage', standalone: true, imports: [EntityPreview, CdkDrag, CdkDropList, CdkDragPlaceholder], template: "<div\r\n cdkDropList\r\n cdkDropListOrientation=\"mixed\"\r\n [cdkDropListData]=\"sortedEntities()\"\r\n (cdkDropListDropped)=\"onDrop($event)\"\r\n class=\"grid grid-cols-24 gap-x-4 gap-y-6\"\r\n>\r\n @for (entity of sortedEntities(); track entity.order) {\r\n <div\r\n cdkDrag\r\n [cdkDragData]=\"entity\"\r\n class=\"entity-cell group relative min-w-0 flex items-center p-3 cursor-grab active:cursor-grabbing\"\r\n [class.border]=\"entity.configuration?.showBorder\"\r\n [class.border-dashed]=\"entity.configuration?.showBorder\"\r\n [class.border-gray-200]=\"entity.configuration?.showBorder\"\r\n [class.rounded-lg]=\"entity.configuration?.showBorder\"\r\n [class.resizing]=\"resizingEntity() === entity\"\r\n [style.grid-column]=\"getColSpan(entity)\"\r\n >\r\n <!-- Drag placeholder -->\r\n <div\r\n *cdkDragPlaceholder\r\n class=\"h-full min-h-12 bg-black/10 rounded-xl\"\r\n [style.grid-column]=\"getColSpan(entity)\"\r\n ></div>\r\n\r\n <mt-entity-preview [data]=\"entity\" class=\"flex-1 min-w-0\" />\r\n\r\n <!-- Resize handle (right edge) -->\r\n <div class=\"resize-handle\" (mousedown)=\"onResizeStart($event, entity)\">\r\n <div class=\"resize-handle-bar\"></div>\r\n </div>\r\n </div>\r\n }\r\n</div>\r\n", styles: [".cdk-drag{cursor:grab}.cdk-drag:active{cursor:grabbing}.cdk-drag-preview{cursor:grabbing;overflow:hidden}.cdk-drag-placeholder{opacity:.5}.cdk-drop-list-dragging .cdk-drag{cursor:grabbing}.entity-cell{position:relative}.resize-handle{position:absolute;top:0;inset-inline-end:-4px;width:8px;height:100%;cursor:col-resize;z-index:10;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .15s ease}.entity-cell:hover .resize-handle,.entity-cell.resizing .resize-handle{opacity:1}.resize-handle-bar{width:3px;height:24px;border-radius:2px;background-color:var(--p-primary-color, #6366f1);transition:height .15s ease,background-color .15s ease}.resize-handle:hover .resize-handle-bar{height:36px;background-color:var(--p-primary-color, #4f46e5)}.entity-cell.resizing{outline:2px dashed var(--p-primary-color, #6366f1);outline-offset:-1px;border-radius:8px;-webkit-user-select:none;user-select:none}\n"] }]
857
- }], propDecorators: { entities: [{ type: i0.Input, args: [{ isSignal: true, alias: "entities", required: true }] }, { type: i0.Output, args: ["entitiesChange"] }], entitiesReordered: [{ type: i0.Output, args: ["entitiesReordered"] }] } });
858
-
859
- /**
860
- * Generated bundle index. Do not edit.
861
- */
862
-
863
- export { EntitiesManage, EntitiesPreview, EntitiesResizeBase, EntityAttachment, EntityCheckbox, EntityCurrency, EntityDate, EntityField, EntityLongText, EntityLookup, EntityPercentage, EntityPreview, EntityStatus, EntityText, EntityUser };
864
- //# sourceMappingURL=masterteam-components-entities.mjs.map