quang 19.0.19-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +25 -0
- package/auth/README.md +160 -0
- package/auth/auth-providers.d.ts +39 -0
- package/auth/auth.service.d.ts +52 -0
- package/auth/directives/has-at-least-one-role.directive.d.ts +26 -0
- package/auth/directives/has-every-role.directive.d.ts +26 -0
- package/auth/directives/is-authenticated.directive.d.ts +14 -0
- package/auth/directives/is-not-authenticated.directive.d.ts +14 -0
- package/auth/guards/index.d.ts +2 -0
- package/auth/guards/is-allowed.guard.d.ts +2 -0
- package/auth/guards/is-authenticated.guard.d.ts +2 -0
- package/auth/index.d.ts +9 -0
- package/auth/logout-on-error.interceptor.d.ts +9 -0
- package/auth/mobile/index.d.ts +1 -0
- package/auth/mobile/mobile-auth-feature.d.ts +2 -0
- package/auth/token-storage/index.d.ts +3 -0
- package/auth/token-storage/local-storage-feature.d.ts +2 -0
- package/auth/token-storage/memory-storage-feature.d.ts +12 -0
- package/auth/token-storage/session-storage-feature.d.ts +2 -0
- package/components/autocomplete/autocomplete.component.d.ts +43 -0
- package/components/autocomplete/index.d.ts +1 -0
- package/components/checkbox/checkbox.component.d.ts +11 -0
- package/components/checkbox/index.d.ts +1 -0
- package/components/date/date.component.d.ts +85 -0
- package/components/date/global-date.component.scss +1 -0
- package/components/date/index.d.ts +1 -0
- package/components/input/index.d.ts +1 -0
- package/components/input/input.component.d.ts +15 -0
- package/components/paginator/index.d.ts +5 -0
- package/components/paginator/paginator-language.service.d.ts +10 -0
- package/components/paginator/paginator.component.d.ts +30 -0
- package/components/paginator/paginator.module.d.ts +7 -0
- package/components/paginator/paginator.service.d.ts +6 -0
- package/components/paginator/paginatorIntl.d.ts +12 -0
- package/components/select/index.d.ts +1 -0
- package/components/select/select.component.d.ts +29 -0
- package/components/shared/ErrorData.d.ts +4 -0
- package/components/shared/index.d.ts +4 -0
- package/components/shared/makeId.d.ts +1 -0
- package/components/shared/option-list/option-list.component.d.ts +50 -0
- package/components/shared/quang-base-component.directive.d.ts +50 -0
- package/components/table/index.d.ts +1 -0
- package/components/table/table.component.d.ts +66 -0
- package/components/wysiwyg/global-wysiswyg.component.scss +1 -0
- package/components/wysiwyg/index.d.ts +1 -0
- package/components/wysiwyg/wysiwyg.component.d.ts +46 -0
- package/device/index.d.ts +1 -0
- package/device/resize-observable.service.d.ts +11 -0
- package/fesm2022/quang-auth-mobile.mjs +48 -0
- package/fesm2022/quang-auth-mobile.mjs.map +1 -0
- package/fesm2022/quang-auth.mjs +473 -0
- package/fesm2022/quang-auth.mjs.map +1 -0
- package/fesm2022/quang-components-autocomplete.mjs +196 -0
- package/fesm2022/quang-components-autocomplete.mjs.map +1 -0
- package/fesm2022/quang-components-checkbox.mjs +53 -0
- package/fesm2022/quang-components-checkbox.mjs.map +1 -0
- package/fesm2022/quang-components-date.mjs +392 -0
- package/fesm2022/quang-components-date.mjs.map +1 -0
- package/fesm2022/quang-components-input.mjs +54 -0
- package/fesm2022/quang-components-input.mjs.map +1 -0
- package/fesm2022/quang-components-paginator.mjs +157 -0
- package/fesm2022/quang-components-paginator.mjs.map +1 -0
- package/fesm2022/quang-components-select.mjs +123 -0
- package/fesm2022/quang-components-select.mjs.map +1 -0
- package/fesm2022/quang-components-shared.mjs +386 -0
- package/fesm2022/quang-components-shared.mjs.map +1 -0
- package/fesm2022/quang-components-table.mjs +162 -0
- package/fesm2022/quang-components-table.mjs.map +1 -0
- package/fesm2022/quang-components-wysiwyg.mjs +230 -0
- package/fesm2022/quang-components-wysiwyg.mjs.map +1 -0
- package/fesm2022/quang-device.mjs +42 -0
- package/fesm2022/quang-device.mjs.map +1 -0
- package/fesm2022/quang-forms.mjs +188 -0
- package/fesm2022/quang-forms.mjs.map +1 -0
- package/fesm2022/quang-loader.mjs +116 -0
- package/fesm2022/quang-loader.mjs.map +1 -0
- package/fesm2022/quang-overlay-modal.mjs +118 -0
- package/fesm2022/quang-overlay-modal.mjs.map +1 -0
- package/fesm2022/quang-overlay-popover.mjs +70 -0
- package/fesm2022/quang-overlay-popover.mjs.map +1 -0
- package/fesm2022/quang-overlay-shared.mjs +359 -0
- package/fesm2022/quang-overlay-shared.mjs.map +1 -0
- package/fesm2022/quang-overlay-toast.mjs +105 -0
- package/fesm2022/quang-overlay-toast.mjs.map +1 -0
- package/fesm2022/quang-overlay-tooltip.mjs +56 -0
- package/fesm2022/quang-overlay-tooltip.mjs.map +1 -0
- package/fesm2022/quang-shared.mjs +29 -0
- package/fesm2022/quang-shared.mjs.map +1 -0
- package/fesm2022/quang-translation.mjs +119 -0
- package/fesm2022/quang-translation.mjs.map +1 -0
- package/fesm2022/quang.mjs +23 -0
- package/fesm2022/quang.mjs.map +1 -0
- package/forms/README.md +6 -0
- package/forms/form-group-model.d.ts +18 -0
- package/forms/index.d.ts +2 -0
- package/forms/validators.d.ts +43 -0
- package/index.d.ts +30 -0
- package/loader/README.md +14 -0
- package/loader/index.d.ts +4 -0
- package/loader/loader-providers.d.ts +23 -0
- package/loader/loader.component.d.ts +23 -0
- package/loader/loader.interceptor.d.ts +10 -0
- package/loader/loader.service.d.ts +9 -0
- package/overlay/modal/index.d.ts +1 -0
- package/overlay/modal/modal.component.d.ts +29 -0
- package/overlay/popover/index.d.ts +1 -0
- package/overlay/popover/popover.component.d.ts +13 -0
- package/overlay/popover/popover.directive.d.ts +11 -0
- package/overlay/shared/CustomViewportRuler.d.ts +63 -0
- package/overlay/shared/index.d.ts +3 -0
- package/overlay/shared/quang-base-overlay.component.d.ts +9 -0
- package/overlay/shared/quang-base-overlay.directive.d.ts +44 -0
- package/overlay/toast/index.d.ts +2 -0
- package/overlay/toast/toast.component.d.ts +13 -0
- package/overlay/toast/toast.service.d.ts +27 -0
- package/overlay/tooltip/index.d.ts +2 -0
- package/overlay/tooltip/tooltip.component.d.ts +11 -0
- package/overlay/tooltip/tooltip.directive.d.ts +11 -0
- package/package.json +146 -0
- package/shared/index.d.ts +1 -0
- package/shared/intercept-utils.d.ts +13 -0
- package/translation/README.md +21 -0
- package/translation/index.d.ts +4 -0
- package/translation/translation-loader.service.d.ts +10 -0
- package/translation/translation-providers.d.ts +28 -0
- package/translation/translation.service.d.ts +15 -0
- package/translation/translations.tokens.d.ts +5 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { isBefore, isAfter, isWithinInterval } from 'date-fns';
|
|
2
|
+
|
|
3
|
+
var EuroLocale;
|
|
4
|
+
(function (EuroLocale) {
|
|
5
|
+
EuroLocale["AT"] = "AT";
|
|
6
|
+
EuroLocale["BE"] = "BE";
|
|
7
|
+
EuroLocale["BG"] = "BG";
|
|
8
|
+
EuroLocale["CY"] = "CY";
|
|
9
|
+
EuroLocale["CZ"] = "CZ";
|
|
10
|
+
EuroLocale["DE"] = "DE";
|
|
11
|
+
EuroLocale["DK"] = "DK";
|
|
12
|
+
EuroLocale["EE"] = "EE";
|
|
13
|
+
EuroLocale["GR"] = "GR";
|
|
14
|
+
EuroLocale["ES"] = "ES";
|
|
15
|
+
EuroLocale["FI"] = "FI";
|
|
16
|
+
EuroLocale["FR"] = "FR";
|
|
17
|
+
EuroLocale["GB"] = "GB";
|
|
18
|
+
EuroLocale["HU"] = "HU";
|
|
19
|
+
EuroLocale["IE"] = "IE";
|
|
20
|
+
EuroLocale["IT"] = "IT";
|
|
21
|
+
EuroLocale["LT"] = "LT";
|
|
22
|
+
EuroLocale["LU"] = "LU";
|
|
23
|
+
EuroLocale["LV"] = "LV";
|
|
24
|
+
EuroLocale["MT"] = "MT";
|
|
25
|
+
EuroLocale["NL"] = "NL";
|
|
26
|
+
EuroLocale["PL"] = "PL";
|
|
27
|
+
EuroLocale["PT"] = "PT";
|
|
28
|
+
EuroLocale["RO"] = "RO";
|
|
29
|
+
EuroLocale["SE"] = "SE";
|
|
30
|
+
EuroLocale["SI"] = "SI";
|
|
31
|
+
EuroLocale["SK"] = "SK";
|
|
32
|
+
})(EuroLocale || (EuroLocale = {}));
|
|
33
|
+
const europeanVatNumber = {
|
|
34
|
+
[EuroLocale.AT]: /U[0-9]{8}/gm,
|
|
35
|
+
[EuroLocale.BE]: /0[0-9]{9}/gm,
|
|
36
|
+
[EuroLocale.BG]: /[0-9]{9,10}/gm,
|
|
37
|
+
[EuroLocale.CY]: /[0-9]{8}L/gm,
|
|
38
|
+
[EuroLocale.CZ]: /[0-9]{8,10}/gm,
|
|
39
|
+
[EuroLocale.DE]: /[0-9]{9}/gm,
|
|
40
|
+
[EuroLocale.DK]: /[0-9]{8}/gm,
|
|
41
|
+
[EuroLocale.EE]: /[0-9]{9}/gm,
|
|
42
|
+
[EuroLocale.GR]: /[0-9]{9}/gm,
|
|
43
|
+
[EuroLocale.ES]: /[0-9A-Z][0-9]{7}[0-9A-Z]/gm,
|
|
44
|
+
[EuroLocale.FI]: /[0-9]{8}/gm,
|
|
45
|
+
[EuroLocale.FR]: /[0-9A-Z]{2}[0-9]{9}/gm,
|
|
46
|
+
[EuroLocale.GB]: /([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3})/gm,
|
|
47
|
+
[EuroLocale.HU]: /[0-9]{8}/gm,
|
|
48
|
+
[EuroLocale.IE]: /[0-9]S[0-9]{5}L/gm,
|
|
49
|
+
[EuroLocale.IT]: /[0-9]{11}/gm,
|
|
50
|
+
[EuroLocale.LT]: /([0-9]{9}|[0-9]{12})/gm,
|
|
51
|
+
[EuroLocale.LU]: /[0-9]{8}/gm,
|
|
52
|
+
[EuroLocale.LV]: /[0-9]{11}/gm,
|
|
53
|
+
[EuroLocale.MT]: /[0-9]{8}/gm,
|
|
54
|
+
[EuroLocale.NL]: /[0-9]{9}B[0-9]{2}/gm,
|
|
55
|
+
[EuroLocale.PL]: /[0-9]{10}/gm,
|
|
56
|
+
[EuroLocale.PT]: /[0-9]{9}/gm,
|
|
57
|
+
[EuroLocale.RO]: /[0-9]{2,10}/gm,
|
|
58
|
+
[EuroLocale.SE]: /[0-9]{12}/gm,
|
|
59
|
+
[EuroLocale.SI]: /[0-9]{8}/gm,
|
|
60
|
+
[EuroLocale.SK]: /[0-9]{10}/gm,
|
|
61
|
+
};
|
|
62
|
+
function fileMaxSize(maxSize) {
|
|
63
|
+
return (control) => {
|
|
64
|
+
if (control.value && control.value instanceof File && control.value?.size > maxSize) {
|
|
65
|
+
return { maxSize: { requiredValue: maxSize } };
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function fileMinSize(minSize) {
|
|
71
|
+
return (control) => {
|
|
72
|
+
if (control.value && control.value instanceof File && control.value?.size < minSize) {
|
|
73
|
+
return { minSize: { requiredValue: minSize } };
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function isFile() {
|
|
79
|
+
return (control) => {
|
|
80
|
+
if (control.value && control.value instanceof File) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return { isFile: {} };
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function fileType(fileTypes) {
|
|
87
|
+
return (control) => {
|
|
88
|
+
if (control.value && !fileTypes.includes(control.value?.type)) {
|
|
89
|
+
return { fileType: { requiredValue: fileTypes.toString() } };
|
|
90
|
+
}
|
|
91
|
+
return null;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function fileExtensions(list) {
|
|
95
|
+
return (control) => {
|
|
96
|
+
if (control.value && !list.includes(control.value?.name?.match(/(?:\.([^.]+))?$/g)[0])) {
|
|
97
|
+
return { fileExtension: { requiredValue: list.toString() } };
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function requiredCheckbox() {
|
|
103
|
+
return (control) => {
|
|
104
|
+
if (!control.value) {
|
|
105
|
+
return { required: { requiredValue: control.value } };
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
function minDate(dateToCompare) {
|
|
111
|
+
return (control) => {
|
|
112
|
+
if (isBefore(new Date(control.value), dateToCompare)) {
|
|
113
|
+
return { minDate: { requiredValue: dateToCompare } };
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
function maxDate(dateToCompare) {
|
|
119
|
+
return (control) => {
|
|
120
|
+
if (isAfter(new Date(control.value), dateToCompare)) {
|
|
121
|
+
return { maxDate: { requiredValue: dateToCompare } };
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function dateBetween(start, end) {
|
|
127
|
+
return (control) => {
|
|
128
|
+
if (!isWithinInterval(new Date(control.value), {
|
|
129
|
+
start,
|
|
130
|
+
end,
|
|
131
|
+
})) {
|
|
132
|
+
return { dateBetween: { requiredValue: [start, end] } };
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function isFiscalCode() {
|
|
138
|
+
return (control) => {
|
|
139
|
+
if (control?.value &&
|
|
140
|
+
!/^([A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST]{1}[0-9LMNPQRSTUV]{2}[A-Z]{1}[0-9LMNPQRSTUV]{3}[A-Z]{1})$|([0-9]{11})$/gm.test(control.value.toUpperCase())) {
|
|
141
|
+
return { fiscalCode: true };
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
function isVatNumber(localeList) {
|
|
147
|
+
return (control) => {
|
|
148
|
+
let isInvalidVat = true;
|
|
149
|
+
for (const locale of localeList) {
|
|
150
|
+
if (europeanVatNumber[locale]?.test(control?.value)) {
|
|
151
|
+
isInvalidVat = false;
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return isInvalidVat ? { vatNumber: false } : null;
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
function wysiwygRequired() {
|
|
159
|
+
return (control) => {
|
|
160
|
+
const cleanHTML = control.value.replace(/<\/?[^>]+(>|$)/g, '');
|
|
161
|
+
if (!cleanHTML?.length) {
|
|
162
|
+
return { required: { required: true } };
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @example
|
|
170
|
+
* interface Person {
|
|
171
|
+
* name: string
|
|
172
|
+
* lastName: string
|
|
173
|
+
* age: number
|
|
174
|
+
* }
|
|
175
|
+
*
|
|
176
|
+
* myForm: FormGroupModel<Person> = this.formBuilder.group({
|
|
177
|
+
* name: this.formBuilder.control<string>('', Validators.required),
|
|
178
|
+
* lastName: this.formBuilder.control<string>(''),
|
|
179
|
+
* age: this.formBuilder.control<number>({value: 20, disabled: true})
|
|
180
|
+
* })
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Generated bundle index. Do not edit.
|
|
185
|
+
*/
|
|
186
|
+
|
|
187
|
+
export { EuroLocale, dateBetween, europeanVatNumber, fileExtensions, fileMaxSize, fileMinSize, fileType, isFile, isFiscalCode, isVatNumber, maxDate, minDate, requiredCheckbox, wysiwygRequired };
|
|
188
|
+
//# sourceMappingURL=quang-forms.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quang-forms.mjs","sources":["../../../projects/quang/forms/validators.ts","../../../projects/quang/forms/form-group-model.ts","../../../projects/quang/forms/quang-forms.ts"],"sourcesContent":["import { AbstractControl, ValidatorFn } from '@angular/forms'\n\nimport { isAfter, isBefore, isWithinInterval } from 'date-fns'\n\nexport enum EuroLocale {\n AT = 'AT',\n BE = 'BE',\n BG = 'BG',\n CY = 'CY',\n CZ = 'CZ',\n DE = 'DE',\n DK = 'DK',\n EE = 'EE',\n GR = 'GR',\n ES = 'ES',\n FI = 'FI',\n FR = 'FR',\n GB = 'GB',\n HU = 'HU',\n IE = 'IE',\n IT = 'IT',\n LT = 'LT',\n LU = 'LU',\n LV = 'LV',\n MT = 'MT',\n NL = 'NL',\n PL = 'PL',\n PT = 'PT',\n RO = 'RO',\n SE = 'SE',\n SI = 'SI',\n SK = 'SK',\n}\n\nexport const europeanVatNumber: Record<EuroLocale, RegExp> = {\n [EuroLocale.AT]: /U[0-9]{8}/gm,\n [EuroLocale.BE]: /0[0-9]{9}/gm,\n [EuroLocale.BG]: /[0-9]{9,10}/gm,\n [EuroLocale.CY]: /[0-9]{8}L/gm,\n [EuroLocale.CZ]: /[0-9]{8,10}/gm,\n [EuroLocale.DE]: /[0-9]{9}/gm,\n [EuroLocale.DK]: /[0-9]{8}/gm,\n [EuroLocale.EE]: /[0-9]{9}/gm,\n [EuroLocale.GR]: /[0-9]{9}/gm,\n [EuroLocale.ES]: /[0-9A-Z][0-9]{7}[0-9A-Z]/gm,\n [EuroLocale.FI]: /[0-9]{8}/gm,\n [EuroLocale.FR]: /[0-9A-Z]{2}[0-9]{9}/gm,\n [EuroLocale.GB]: /([0-9]{9}([0-9]{3})?|[A-Z]{2}[0-9]{3})/gm,\n [EuroLocale.HU]: /[0-9]{8}/gm,\n [EuroLocale.IE]: /[0-9]S[0-9]{5}L/gm,\n [EuroLocale.IT]: /[0-9]{11}/gm,\n [EuroLocale.LT]: /([0-9]{9}|[0-9]{12})/gm,\n [EuroLocale.LU]: /[0-9]{8}/gm,\n [EuroLocale.LV]: /[0-9]{11}/gm,\n [EuroLocale.MT]: /[0-9]{8}/gm,\n [EuroLocale.NL]: /[0-9]{9}B[0-9]{2}/gm,\n [EuroLocale.PL]: /[0-9]{10}/gm,\n [EuroLocale.PT]: /[0-9]{9}/gm,\n [EuroLocale.RO]: /[0-9]{2,10}/gm,\n [EuroLocale.SE]: /[0-9]{12}/gm,\n [EuroLocale.SI]: /[0-9]{8}/gm,\n [EuroLocale.SK]: /[0-9]{10}/gm,\n}\nexport function fileMaxSize(maxSize: number): ValidatorFn {\n return (control: AbstractControl): Record<string, any> | null => {\n if (control.value && control.value instanceof File && control.value?.size > maxSize) {\n return { maxSize: { requiredValue: maxSize } }\n }\n return null\n }\n}\n\nexport function fileMinSize(minSize: number): ValidatorFn {\n return (control: AbstractControl): Record<string, any> | null => {\n if (control.value && control.value instanceof File && control.value?.size < minSize) {\n return { minSize: { requiredValue: minSize } }\n }\n return null\n }\n}\n\nexport function isFile(): ValidatorFn {\n return (control: AbstractControl): Record<string, any> | null => {\n if (control.value && control.value instanceof File) {\n return null\n }\n return { isFile: {} }\n }\n}\n\nexport function fileType(fileTypes: string[]) {\n return (control: AbstractControl): Record<string, any> | null => {\n if (control.value && !fileTypes.includes(control.value?.type)) {\n return { fileType: { requiredValue: fileTypes.toString() } }\n }\n return null\n }\n}\n\nexport function fileExtensions(list: string[]) {\n return (control: AbstractControl): Record<string, any> | null => {\n if (control.value && !list.includes(control.value?.name?.match(/(?:\\.([^.]+))?$/g)[0])) {\n return { fileExtension: { requiredValue: list.toString() } }\n }\n return null\n }\n}\n\nexport function requiredCheckbox() {\n return (control: AbstractControl): Record<string, any> | null => {\n if (!control.value) {\n return { required: { requiredValue: control.value } }\n }\n return null\n }\n}\n\nexport function minDate(dateToCompare: Date) {\n return (control: AbstractControl): Record<string, any> | null => {\n if (isBefore(new Date(control.value), dateToCompare)) {\n return { minDate: { requiredValue: dateToCompare } }\n }\n return null\n }\n}\n\nexport function maxDate(dateToCompare: Date) {\n return (control: AbstractControl): Record<string, any> | null => {\n if (isAfter(new Date(control.value), dateToCompare)) {\n return { maxDate: { requiredValue: dateToCompare } }\n }\n return null\n }\n}\n\nexport function dateBetween(start: Date, end: Date) {\n return (control: AbstractControl): Record<string, any> | null => {\n if (\n !isWithinInterval(new Date(control.value), {\n start,\n end,\n })\n ) {\n return { dateBetween: { requiredValue: [start, end] } }\n }\n return null\n }\n}\n\nexport function isFiscalCode() {\n return (control: AbstractControl): Record<string, any> | null => {\n if (\n control?.value &&\n !/^([A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST]{1}[0-9LMNPQRSTUV]{2}[A-Z]{1}[0-9LMNPQRSTUV]{3}[A-Z]{1})$|([0-9]{11})$/gm.test(\n control.value.toUpperCase()\n )\n ) {\n return { fiscalCode: true }\n }\n return null\n }\n}\n\nexport function isVatNumber(localeList: EuroLocale[]) {\n return (control: AbstractControl): Record<string, any> | null => {\n let isInvalidVat = true\n for (const locale of localeList) {\n if (europeanVatNumber[locale]?.test(control?.value)) {\n isInvalidVat = false\n break\n }\n }\n return isInvalidVat ? { vatNumber: false } : null\n }\n}\n\nexport function wysiwygRequired() {\n return (control: AbstractControl): Record<string, any> | null => {\n const cleanHTML = control.value.replace(/<\\/?[^>]+(>|$)/g, '')\n if (!cleanHTML?.length) {\n return { required: { required: true } }\n }\n return null\n }\n}\n","import { FormControl, FormGroup } from '@angular/forms'\n\nexport type FormGroupModel<T> = FormGroup<{\n [K in keyof T]: FormControl<T[K]>\n}>\n\n/**\n * @example\n * interface Person {\n * name: string\n * lastName: string\n * age: number\n * }\n *\n * myForm: FormGroupModel<Person> = this.formBuilder.group({\n * name: this.formBuilder.control<string>('', Validators.required),\n * lastName: this.formBuilder.control<string>(''),\n * age: this.formBuilder.control<number>({value: 20, disabled: true})\n * })\n */\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { computed, Injectable, InjectionToken, inject, input, ChangeDetectionStrategy, Component, makeEnvironmentProviders } from '@angular/core';
|
|
3
|
+
import { getExcludedUrlsByMethod, isHttpMethod } from 'quang/shared';
|
|
4
|
+
import { finalize, map, of, timer, switchAll } from 'rxjs';
|
|
5
|
+
import { signalState, patchState } from '@ngrx/signals';
|
|
6
|
+
import { NgIf } from '@angular/common';
|
|
7
|
+
import { toObservable, toSignal } from '@angular/core/rxjs-interop';
|
|
8
|
+
import { quangFeature } from 'quang';
|
|
9
|
+
|
|
10
|
+
class QuangLoaderService {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.loaderState = signalState({ count: 0 });
|
|
13
|
+
this.isLoading = computed(() => this.loaderState.count() > 0);
|
|
14
|
+
}
|
|
15
|
+
show() {
|
|
16
|
+
patchState(this.loaderState, { count: this.loaderState().count + 1 });
|
|
17
|
+
}
|
|
18
|
+
hide() {
|
|
19
|
+
patchState(this.loaderState, { count: this.loaderState().count - 1 });
|
|
20
|
+
}
|
|
21
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangLoaderService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
22
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangLoaderService, providedIn: 'root' }); }
|
|
23
|
+
}
|
|
24
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangLoaderService, decorators: [{
|
|
25
|
+
type: Injectable,
|
|
26
|
+
args: [{
|
|
27
|
+
providedIn: 'root',
|
|
28
|
+
}]
|
|
29
|
+
}] });
|
|
30
|
+
|
|
31
|
+
const LOADER_EXCLUDED_URLS = new InjectionToken('LOADER_EXCLUDED_URLS');
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated
|
|
34
|
+
* @see {@link LOADER_EXCLUDED_URLS}
|
|
35
|
+
*/
|
|
36
|
+
const EXCLUDED_URL = LOADER_EXCLUDED_URLS;
|
|
37
|
+
const quangLoaderInterceptor = (request, next) => {
|
|
38
|
+
const excludedUrlsByMethod = getExcludedUrlsByMethod(inject(LOADER_EXCLUDED_URLS, { optional: true }) ?? []);
|
|
39
|
+
const loaderService = inject(QuangLoaderService);
|
|
40
|
+
if (!isHttpMethod(request.method)) {
|
|
41
|
+
return next(request);
|
|
42
|
+
}
|
|
43
|
+
if (Array.from(excludedUrlsByMethod.get(request.method) ?? []).some((excludedUrl) => request.url.match(excludedUrl.replace(/\//g, '\\/')))) {
|
|
44
|
+
return next(request);
|
|
45
|
+
}
|
|
46
|
+
loaderService.show();
|
|
47
|
+
return next(request).pipe(finalize(() => {
|
|
48
|
+
loaderService.hide();
|
|
49
|
+
}));
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @example
|
|
54
|
+
* <quang-loader></quang-loader>
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* <quang-loader>
|
|
58
|
+
* custom loader here
|
|
59
|
+
* </quang-loader>
|
|
60
|
+
*/
|
|
61
|
+
class QuangLoaderComponent {
|
|
62
|
+
constructor() {
|
|
63
|
+
/**
|
|
64
|
+
* Minimum time (in milliseconds) to show the loader for
|
|
65
|
+
* @default 500
|
|
66
|
+
*/
|
|
67
|
+
this.showAtLeastFor = input(500);
|
|
68
|
+
this.loaderService = inject(QuangLoaderService);
|
|
69
|
+
this.isLoading = this.loaderService.isLoading;
|
|
70
|
+
this.showLoaderBuffer$ = toObservable(this.isLoading).pipe(map((isLoading) => (isLoading ? of(isLoading) : timer(this.showAtLeastFor()).pipe(map(() => isLoading)))), switchAll());
|
|
71
|
+
this.showLoader = toSignal(this.showLoaderBuffer$);
|
|
72
|
+
}
|
|
73
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangLoaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
74
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.5", type: QuangLoaderComponent, isStandalone: true, selector: "quang-loader", inputs: { showAtLeastFor: { classPropertyName: "showAtLeastFor", publicName: "showAtLeastFor", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n *ngIf=\"showLoader()\"\n class=\"loader-container\"\n>\n <ng-container *ngIf=\"!ref?.children?.length\">\n <span class=\"loader\"></span>\n </ng-container>\n <div #ref>\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{display:block}.loader-container{position:fixed;width:100%;height:100%;display:flex;top:0;left:0;background-color:#00000080;align-items:center;justify-content:center;z-index:99999}.loader-container .loader{width:48px;height:48px;border-radius:50%;display:inline-block;position:relative;border:3px solid;border-color:rgba(255,255,255,.7607843137) rgba(255,255,255,.7607843137) rgba(255,255,255,.7607843137) transparent;box-sizing:border-box;animation:rotation 1s linear infinite}@keyframes rotation{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes rotationBack{0%{transform:rotate(0)}to{transform:rotate(-360deg)}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
75
|
+
}
|
|
76
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangLoaderComponent, decorators: [{
|
|
77
|
+
type: Component,
|
|
78
|
+
args: [{ selector: 'quang-loader', imports: [NgIf], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n *ngIf=\"showLoader()\"\n class=\"loader-container\"\n>\n <ng-container *ngIf=\"!ref?.children?.length\">\n <span class=\"loader\"></span>\n </ng-container>\n <div #ref>\n <ng-content></ng-content>\n </div>\n</div>\n", styles: [":host{display:block}.loader-container{position:fixed;width:100%;height:100%;display:flex;top:0;left:0;background-color:#00000080;align-items:center;justify-content:center;z-index:99999}.loader-container .loader{width:48px;height:48px;border-radius:50%;display:inline-block;position:relative;border:3px solid;border-color:rgba(255,255,255,.7607843137) rgba(255,255,255,.7607843137) rgba(255,255,255,.7607843137) transparent;box-sizing:border-box;animation:rotation 1s linear infinite}@keyframes rotation{0%{transform:rotate(0)}to{transform:rotate(360deg)}}@keyframes rotationBack{0%{transform:rotate(0)}to{transform:rotate(-360deg)}}\n"] }]
|
|
79
|
+
}] });
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @example
|
|
83
|
+
* export const appConfig: ApplicationConfig = {
|
|
84
|
+
* providers: [
|
|
85
|
+
* provideLoader([
|
|
86
|
+
* {
|
|
87
|
+
* url: 'assets',
|
|
88
|
+
* method: 'GET',
|
|
89
|
+
* },
|
|
90
|
+
* ])
|
|
91
|
+
* ]
|
|
92
|
+
* }
|
|
93
|
+
*/
|
|
94
|
+
function provideQuangLoaderExcludedUrls(excludedUrls) {
|
|
95
|
+
return makeEnvironmentProviders([
|
|
96
|
+
{
|
|
97
|
+
provide: LOADER_EXCLUDED_URLS,
|
|
98
|
+
useValue: excludedUrls,
|
|
99
|
+
},
|
|
100
|
+
]);
|
|
101
|
+
}
|
|
102
|
+
function withLoaderExcludedUrls(excludedUrls) {
|
|
103
|
+
return quangFeature(2 /* QuangFeatureKind.LoaderFeature */, [provideQuangLoaderExcludedUrls(excludedUrls)]);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* @deprecated
|
|
107
|
+
* @see {@link provideQuangLoaderExcludedUrls}
|
|
108
|
+
*/
|
|
109
|
+
const provideLoader = provideQuangLoaderExcludedUrls;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Generated bundle index. Do not edit.
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
export { EXCLUDED_URL, LOADER_EXCLUDED_URLS, QuangLoaderComponent, QuangLoaderService, provideLoader, provideQuangLoaderExcludedUrls, quangLoaderInterceptor, withLoaderExcludedUrls };
|
|
116
|
+
//# sourceMappingURL=quang-loader.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quang-loader.mjs","sources":["../../../projects/quang/loader/loader.service.ts","../../../projects/quang/loader/loader.interceptor.ts","../../../projects/quang/loader/loader.component.ts","../../../projects/quang/loader/loader.component.html","../../../projects/quang/loader/loader-providers.ts","../../../projects/quang/loader/quang-loader.ts"],"sourcesContent":["import { Injectable, computed } from '@angular/core'\n\nimport { patchState, signalState } from '@ngrx/signals'\n\n@Injectable({\n providedIn: 'root',\n})\nexport class QuangLoaderService {\n private loaderState = signalState({ count: 0 })\n\n public isLoading = computed(() => this.loaderState.count() > 0)\n\n public show(): void {\n patchState(this.loaderState, { count: this.loaderState().count + 1 })\n }\n\n public hide(): void {\n patchState(this.loaderState, { count: this.loaderState().count - 1 })\n }\n}\n","import { HttpInterceptorFn } from '@angular/common/http'\nimport { InjectionToken, inject } from '@angular/core'\n\nimport { UrlData, getExcludedUrlsByMethod, isHttpMethod } from 'quang/shared'\nimport { finalize } from 'rxjs'\n\nimport { QuangLoaderService } from './loader.service'\n\nexport const LOADER_EXCLUDED_URLS = new InjectionToken<UrlData[]>('LOADER_EXCLUDED_URLS')\n\n/**\n * @deprecated\n * @see {@link LOADER_EXCLUDED_URLS}\n */\nexport const EXCLUDED_URL = LOADER_EXCLUDED_URLS\n\nexport const quangLoaderInterceptor: HttpInterceptorFn = (request, next) => {\n const excludedUrlsByMethod = getExcludedUrlsByMethod(inject(LOADER_EXCLUDED_URLS, { optional: true }) ?? [])\n const loaderService = inject(QuangLoaderService)\n if (!isHttpMethod(request.method)) {\n return next(request)\n }\n\n if (\n Array.from(excludedUrlsByMethod.get(request.method) ?? []).some((excludedUrl) =>\n request.url.match(excludedUrl.replace(/\\//g, '\\\\/'))\n )\n ) {\n return next(request)\n }\n\n loaderService.show()\n\n return next(request).pipe(\n finalize(() => {\n loaderService.hide()\n })\n )\n}\n","import { NgIf } from '@angular/common'\nimport { ChangeDetectionStrategy, Component, inject, input } from '@angular/core'\nimport { toObservable, toSignal } from '@angular/core/rxjs-interop'\n\nimport { map, of, switchAll, timer } from 'rxjs'\n\nimport { QuangLoaderService } from './loader.service'\n\n/**\n * @example\n * <quang-loader></quang-loader>\n *\n * @example\n * <quang-loader>\n * custom loader here\n * </quang-loader>\n */\n@Component({\n selector: 'quang-loader',\n imports: [NgIf],\n templateUrl: './loader.component.html',\n styleUrl: './loader.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class QuangLoaderComponent {\n /**\n * Minimum time (in milliseconds) to show the loader for\n * @default 500\n */\n showAtLeastFor = input<number>(500)\n\n private readonly loaderService = inject(QuangLoaderService)\n\n isLoading = this.loaderService.isLoading\n\n showLoaderBuffer$ = toObservable(this.isLoading).pipe(\n map((isLoading) => (isLoading ? of(isLoading) : timer(this.showAtLeastFor()).pipe(map(() => isLoading)))),\n switchAll()\n )\n\n showLoader = toSignal(this.showLoaderBuffer$)\n}\n","<div\n *ngIf=\"showLoader()\"\n class=\"loader-container\"\n>\n <ng-container *ngIf=\"!ref?.children?.length\">\n <span class=\"loader\"></span>\n </ng-container>\n <div #ref>\n <ng-content></ng-content>\n </div>\n</div>\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core'\n\nimport { QuangFeature, QuangFeatureKind, quangFeature } from 'quang'\nimport { UrlData } from 'quang/shared'\n\nimport { LOADER_EXCLUDED_URLS } from './loader.interceptor'\n\n/**\n * @example\n * export const appConfig: ApplicationConfig = {\n * providers: [\n * provideLoader([\n * {\n * url: 'assets',\n * method: 'GET',\n * },\n * ])\n * ]\n * }\n */\nexport function provideQuangLoaderExcludedUrls(excludedUrls: UrlData[]): EnvironmentProviders {\n return makeEnvironmentProviders([\n {\n provide: LOADER_EXCLUDED_URLS,\n useValue: excludedUrls,\n },\n ])\n}\n\nexport function withLoaderExcludedUrls(excludedUrls: UrlData[]): QuangFeature<QuangFeatureKind.LoaderFeature> {\n return quangFeature(QuangFeatureKind.LoaderFeature, [provideQuangLoaderExcludedUrls(excludedUrls)])\n}\n\n/**\n * @deprecated\n * @see {@link provideQuangLoaderExcludedUrls}\n */\nexport const provideLoader = provideQuangLoaderExcludedUrls\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import * as i1 from '@angular/cdk/overlay';
|
|
2
|
+
import { OverlayConfig } from '@angular/cdk/overlay';
|
|
3
|
+
import * as i2 from '@angular/cdk/portal';
|
|
4
|
+
import { PortalModule, CdkPortal } from '@angular/cdk/portal';
|
|
5
|
+
import { NgStyle } from '@angular/common';
|
|
6
|
+
import * as i0 from '@angular/core';
|
|
7
|
+
import { output, input, computed, inject, DestroyRef, ViewChild, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
8
|
+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Modal component that leverages Angular CDK's Overlay and Portal modules to create modals with flexible positioning and configurations.
|
|
12
|
+
*
|
|
13
|
+
* @usageNotes
|
|
14
|
+
* The component can be shown by using its selector `quang-modal` with a boolean binded to the Angular directive `*ngIf`.
|
|
15
|
+
*
|
|
16
|
+
* Its structure is divided in 3 `ng-content` to set the header, body and footer.
|
|
17
|
+
* Every section has its own selector and can be used to render custom content in a simple way.
|
|
18
|
+
*
|
|
19
|
+
* `header` section is placed on top, `footer` section is placed on bottom.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* <quang-modal
|
|
23
|
+
* (backdropClick)="closeModal()"
|
|
24
|
+
* *ngIf="showModal"
|
|
25
|
+
* position="right"
|
|
26
|
+
* >
|
|
27
|
+
* <ng-container header>
|
|
28
|
+
* <h2>Modal header</h2>
|
|
29
|
+
* </ng-container>
|
|
30
|
+
* <ng-container body>
|
|
31
|
+
* <h3>Modal body</h3>
|
|
32
|
+
* </ng-container>
|
|
33
|
+
* <ng-container footer>
|
|
34
|
+
* <h3>Modal footer</h3>
|
|
35
|
+
* </ng-container>
|
|
36
|
+
* </quang-modal>
|
|
37
|
+
*/
|
|
38
|
+
class QuangModalComponent {
|
|
39
|
+
constructor(overlay) {
|
|
40
|
+
this.overlay = overlay;
|
|
41
|
+
this.backdropClick = output();
|
|
42
|
+
this.position = input.required();
|
|
43
|
+
this.height = input('80vh');
|
|
44
|
+
this.width = input('80vw');
|
|
45
|
+
this.padding = input('0 1rem');
|
|
46
|
+
this.containerClass = input('');
|
|
47
|
+
this.animationMode = input();
|
|
48
|
+
this.backgroundColor = input();
|
|
49
|
+
this.showBackdrop = input(true);
|
|
50
|
+
this.positionStrategy = computed(() => {
|
|
51
|
+
switch (this.position()) {
|
|
52
|
+
case 'right':
|
|
53
|
+
return this.overlay.position().global().right().top();
|
|
54
|
+
case 'left':
|
|
55
|
+
return this.overlay.position().global().left().top();
|
|
56
|
+
case 'center':
|
|
57
|
+
default:
|
|
58
|
+
return this.overlay.position().global().centerHorizontally().centerVertically();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
this.animationClassEnter = computed(() => {
|
|
62
|
+
switch (this.animationMode()) {
|
|
63
|
+
case 'SLIDE_FROM_LEFT_TO_RIGHT':
|
|
64
|
+
return 'left-to-right-enter-active';
|
|
65
|
+
case 'SLIDE_FROM_RIGHT_TO_LEFT':
|
|
66
|
+
return 'right-to-left-enter-active';
|
|
67
|
+
case 'SLIDE_TOP_TO_BOTTOM':
|
|
68
|
+
return 'top-to-bottom-enter-active';
|
|
69
|
+
case 'SLIDE_BOTTOM_TO_TOP':
|
|
70
|
+
return 'top-to-bottom-enter-active';
|
|
71
|
+
case 'FADE':
|
|
72
|
+
return 'fade-enter-active';
|
|
73
|
+
default:
|
|
74
|
+
return '';
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
this.destroyRef = inject(DestroyRef);
|
|
78
|
+
}
|
|
79
|
+
ngAfterViewInit() {
|
|
80
|
+
this.overlayConfig = new OverlayConfig({
|
|
81
|
+
hasBackdrop: true,
|
|
82
|
+
positionStrategy: this.positionStrategy(),
|
|
83
|
+
scrollStrategy: this.overlay.scrollStrategies.block(),
|
|
84
|
+
backdropClass: this.showBackdrop() ? undefined : '',
|
|
85
|
+
});
|
|
86
|
+
this.overlayRef = this.overlay.create(this.overlayConfig);
|
|
87
|
+
this.overlayRef
|
|
88
|
+
.backdropClick()
|
|
89
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
90
|
+
.subscribe(() => {
|
|
91
|
+
this.backdropClick.emit();
|
|
92
|
+
});
|
|
93
|
+
this.overlayRef?.attach(this.portal);
|
|
94
|
+
}
|
|
95
|
+
ngOnDestroy() {
|
|
96
|
+
this.closeModal();
|
|
97
|
+
}
|
|
98
|
+
closeModal() {
|
|
99
|
+
this.overlayRef?.detach();
|
|
100
|
+
this.overlayRef?.dispose();
|
|
101
|
+
}
|
|
102
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangModalComponent, deps: [{ token: i1.Overlay }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
103
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.5", type: QuangModalComponent, isStandalone: true, selector: "quang-modal", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: true, transformFunction: null }, height: { classPropertyName: "height", publicName: "height", isSignal: true, isRequired: false, transformFunction: null }, width: { classPropertyName: "width", publicName: "width", isSignal: true, isRequired: false, transformFunction: null }, padding: { classPropertyName: "padding", publicName: "padding", isSignal: true, isRequired: false, transformFunction: null }, containerClass: { classPropertyName: "containerClass", publicName: "containerClass", isSignal: true, isRequired: false, transformFunction: null }, animationMode: { classPropertyName: "animationMode", publicName: "animationMode", isSignal: true, isRequired: false, transformFunction: null }, backgroundColor: { classPropertyName: "backgroundColor", publicName: "backgroundColor", isSignal: true, isRequired: false, transformFunction: null }, showBackdrop: { classPropertyName: "showBackdrop", publicName: "showBackdrop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { backdropClick: "backdropClick" }, viewQueries: [{ propertyName: "portal", first: true, predicate: CdkPortal, descendants: true }], ngImport: i0, template: "<ng-template cdkPortal>\n <div\n [ngStyle]=\"{\n '--quang-modal-panel-width': width(),\n '--quang-modal-panel-height': height(),\n '--quang-modal-panel-background': backgroundColor(),\n '--quang-modal-panel-padding': padding(),\n }\"\n class=\"dialog {{ containerClass() }} {{ animationClassEnter() }}\"\n >\n <div class=\"dialog__header\">\n <ng-content select=\"[header]\"></ng-content>\n </div>\n <div class=\"dialog__body\">\n <ng-content select=\"[body]\"></ng-content>\n </div>\n <div class=\"dialog__footer\">\n <ng-content select=\"[footer]\"></ng-content>\n </div>\n </div>\n</ng-template>\n", styles: [".dialog{background-color:var(--quang-modal-panel-background, var(--bs-body-bg, initial));position:relative;display:flex;flex-direction:column;width:var(--quang-modal-panel-width);height:var(--quang-modal-panel-height);padding:var(--quang-modal-panel-padding)}.dialog__header{display:flex;flex-direction:column;width:100%}.dialog__body{flex:1;overflow:auto}.dialog__footer{display:flex;justify-content:flex-end}::ng-deep .cdk-global-scrollblock{overflow-y:auto}@keyframes left-to-right_enter{0%{transform:translate(-100%)}to{transform:translate(0)}}.left-to-right-enter-active{animation:left-to-right_enter .5s ease-in-out forwards}@keyframes right-to-left_enter{0%{transform:translate(100%)}to{transform:translate(0)}}.right-to-left-enter-active{animation:right-to-left_enter .5s ease-in-out forwards}@keyframes top-to-bottom_enter{0%{transform:translateY(-100%)}to{transform:translateY(0)}}.top-to-bottom-enter-active{animation:top-to-bottom_enter .5s ease-in-out forwards}@keyframes bottom-to-top_enter{0%{transform:translateY(100%)}to{transform:translateY(0)}}.top-to-bottom-enter-active{animation:bottom-to-top_enter .5s ease-in-out forwards}@keyframes fade_enter{0%{opacity:0}to{opacity:1}}.fade-enter-active{animation:fade_enter .5s ease-in-out forwards}\n"], dependencies: [{ kind: "ngmodule", type: PortalModule }, { kind: "directive", type: i2.CdkPortal, selector: "[cdkPortal]", exportAs: ["cdkPortal"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
104
|
+
}
|
|
105
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangModalComponent, decorators: [{
|
|
106
|
+
type: Component,
|
|
107
|
+
args: [{ selector: 'quang-modal', imports: [PortalModule, NgStyle], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template cdkPortal>\n <div\n [ngStyle]=\"{\n '--quang-modal-panel-width': width(),\n '--quang-modal-panel-height': height(),\n '--quang-modal-panel-background': backgroundColor(),\n '--quang-modal-panel-padding': padding(),\n }\"\n class=\"dialog {{ containerClass() }} {{ animationClassEnter() }}\"\n >\n <div class=\"dialog__header\">\n <ng-content select=\"[header]\"></ng-content>\n </div>\n <div class=\"dialog__body\">\n <ng-content select=\"[body]\"></ng-content>\n </div>\n <div class=\"dialog__footer\">\n <ng-content select=\"[footer]\"></ng-content>\n </div>\n </div>\n</ng-template>\n", styles: [".dialog{background-color:var(--quang-modal-panel-background, var(--bs-body-bg, initial));position:relative;display:flex;flex-direction:column;width:var(--quang-modal-panel-width);height:var(--quang-modal-panel-height);padding:var(--quang-modal-panel-padding)}.dialog__header{display:flex;flex-direction:column;width:100%}.dialog__body{flex:1;overflow:auto}.dialog__footer{display:flex;justify-content:flex-end}::ng-deep .cdk-global-scrollblock{overflow-y:auto}@keyframes left-to-right_enter{0%{transform:translate(-100%)}to{transform:translate(0)}}.left-to-right-enter-active{animation:left-to-right_enter .5s ease-in-out forwards}@keyframes right-to-left_enter{0%{transform:translate(100%)}to{transform:translate(0)}}.right-to-left-enter-active{animation:right-to-left_enter .5s ease-in-out forwards}@keyframes top-to-bottom_enter{0%{transform:translateY(-100%)}to{transform:translateY(0)}}.top-to-bottom-enter-active{animation:top-to-bottom_enter .5s ease-in-out forwards}@keyframes bottom-to-top_enter{0%{transform:translateY(100%)}to{transform:translateY(0)}}.top-to-bottom-enter-active{animation:bottom-to-top_enter .5s ease-in-out forwards}@keyframes fade_enter{0%{opacity:0}to{opacity:1}}.fade-enter-active{animation:fade_enter .5s ease-in-out forwards}\n"] }]
|
|
108
|
+
}], ctorParameters: () => [{ type: i1.Overlay }], propDecorators: { portal: [{
|
|
109
|
+
type: ViewChild,
|
|
110
|
+
args: [CdkPortal]
|
|
111
|
+
}] } });
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Generated bundle index. Do not edit.
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
export { QuangModalComponent };
|
|
118
|
+
//# sourceMappingURL=quang-overlay-modal.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quang-overlay-modal.mjs","sources":["../../../projects/quang/overlay/modal/modal.component.ts","../../../projects/quang/overlay/modal/modal.component.html","../../../projects/quang/overlay/modal/quang-overlay-modal.ts"],"sourcesContent":["import { Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay'\nimport { CdkPortal, PortalModule } from '@angular/cdk/portal'\nimport { NgStyle } from '@angular/common'\nimport {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n OnDestroy,\n ViewChild,\n computed,\n inject,\n input,\n output,\n} from '@angular/core'\nimport { takeUntilDestroyed } from '@angular/core/rxjs-interop'\n\nexport type ModalAnimationMode =\n | 'SLIDE_FROM_LEFT_TO_RIGHT'\n | 'SLIDE_FROM_RIGHT_TO_LEFT'\n | 'SLIDE_TOP_TO_BOTTOM'\n | 'SLIDE_BOTTOM_TO_TOP'\n | 'FADE'\n\n@Component({\n selector: 'quang-modal',\n imports: [PortalModule, NgStyle],\n templateUrl: './modal.component.html',\n styleUrl: './modal.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Modal component that leverages Angular CDK's Overlay and Portal modules to create modals with flexible positioning and configurations.\n *\n * @usageNotes\n * The component can be shown by using its selector `quang-modal` with a boolean binded to the Angular directive `*ngIf`.\n *\n * Its structure is divided in 3 `ng-content` to set the header, body and footer.\n * Every section has its own selector and can be used to render custom content in a simple way.\n *\n * `header` section is placed on top, `footer` section is placed on bottom.\n *\n * @example\n * <quang-modal\n * (backdropClick)=\"closeModal()\"\n * *ngIf=\"showModal\"\n * position=\"right\"\n * >\n * <ng-container header>\n * <h2>Modal header</h2>\n * </ng-container>\n * <ng-container body>\n * <h3>Modal body</h3>\n * </ng-container>\n * <ng-container footer>\n * <h3>Modal footer</h3>\n * </ng-container>\n * </quang-modal>\n */\nexport class QuangModalComponent implements AfterViewInit, OnDestroy {\n @ViewChild(CdkPortal) public readonly portal?: CdkPortal\n\n backdropClick = output<void>()\n\n position = input.required<'right' | 'left' | 'center'>()\n\n height = input<string>('80vh')\n\n width = input<string>('80vw')\n\n padding = input<string>('0 1rem')\n\n containerClass = input<string>('')\n\n animationMode = input<ModalAnimationMode>()\n\n backgroundColor = input<string>()\n\n showBackdrop = input<boolean>(true)\n\n positionStrategy = computed(() => {\n switch (this.position()) {\n case 'right':\n return this.overlay.position().global().right().top()\n case 'left':\n return this.overlay.position().global().left().top()\n case 'center':\n default:\n return this.overlay.position().global().centerHorizontally().centerVertically()\n }\n })\n\n animationClassEnter = computed(() => {\n switch (this.animationMode()) {\n case 'SLIDE_FROM_LEFT_TO_RIGHT':\n return 'left-to-right-enter-active'\n case 'SLIDE_FROM_RIGHT_TO_LEFT':\n return 'right-to-left-enter-active'\n case 'SLIDE_TOP_TO_BOTTOM':\n return 'top-to-bottom-enter-active'\n case 'SLIDE_BOTTOM_TO_TOP':\n return 'top-to-bottom-enter-active'\n case 'FADE':\n return 'fade-enter-active'\n default:\n return ''\n }\n })\n\n private readonly destroyRef = inject(DestroyRef)\n\n private overlayConfig?: OverlayConfig\n\n private overlayRef?: OverlayRef\n\n constructor(private readonly overlay: Overlay) {}\n\n ngAfterViewInit(): void {\n this.overlayConfig = new OverlayConfig({\n hasBackdrop: true,\n positionStrategy: this.positionStrategy(),\n scrollStrategy: this.overlay.scrollStrategies.block(),\n backdropClass: this.showBackdrop() ? undefined : '',\n })\n this.overlayRef = this.overlay.create(this.overlayConfig)\n this.overlayRef\n .backdropClick()\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe(() => {\n this.backdropClick.emit()\n })\n this.overlayRef?.attach(this.portal)\n }\n\n ngOnDestroy(): void {\n this.closeModal()\n }\n\n closeModal(): void {\n this.overlayRef?.detach()\n this.overlayRef?.dispose()\n }\n}\n","<ng-template cdkPortal>\n <div\n [ngStyle]=\"{\n '--quang-modal-panel-width': width(),\n '--quang-modal-panel-height': height(),\n '--quang-modal-panel-background': backgroundColor(),\n '--quang-modal-panel-padding': padding(),\n }\"\n class=\"dialog {{ containerClass() }} {{ animationClassEnter() }}\"\n >\n <div class=\"dialog__header\">\n <ng-content select=\"[header]\"></ng-content>\n </div>\n <div class=\"dialog__body\">\n <ng-content select=\"[body]\"></ng-content>\n </div>\n <div class=\"dialog__footer\">\n <ng-content select=\"[footer]\"></ng-content>\n </div>\n </div>\n</ng-template>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, signal, ChangeDetectionStrategy, Component, Directive } from '@angular/core';
|
|
3
|
+
import { QuangBaseOverlayDirective } from 'quang/overlay/shared';
|
|
4
|
+
import { NgTemplateOutlet, NgClass, NgIf } from '@angular/common';
|
|
5
|
+
import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Popover component that can render custom content, passed from the outside as a `TemplateRef`
|
|
9
|
+
* @example
|
|
10
|
+
* <button
|
|
11
|
+
[quangPopover]="popoverTest"
|
|
12
|
+
[scrollCloseThreshold]="undefined"
|
|
13
|
+
class="btn popover-test-button"
|
|
14
|
+
overlayPosition="top"
|
|
15
|
+
showMethod="click"
|
|
16
|
+
>
|
|
17
|
+
{{ 'buttons.popover' | transloco }}
|
|
18
|
+
<span>CLICK</span>
|
|
19
|
+
</button>
|
|
20
|
+
<ng-template #popoverTest> <span>test works!</span> <button type="button">click!</button> </ng-template>
|
|
21
|
+
*/
|
|
22
|
+
class QuangPopoverComponent {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.content = input(null);
|
|
25
|
+
this.positionPair = signal(null);
|
|
26
|
+
this.payload = input();
|
|
27
|
+
this.getPopoverPosition = signal('');
|
|
28
|
+
this.onChangePositionPair$ = toObservable(this.positionPair)
|
|
29
|
+
.pipe(takeUntilDestroyed())
|
|
30
|
+
.subscribe((positionPair) => {
|
|
31
|
+
const originX = positionPair?.originX;
|
|
32
|
+
const originY = positionPair?.originY;
|
|
33
|
+
if (originX && originY) {
|
|
34
|
+
this.getPopoverPosition.set(`${originX}-${originY}`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
this.getPopoverPosition.set('');
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
42
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.5", type: QuangPopoverComponent, isStandalone: true, selector: "quang-popover", inputs: { content: { classPropertyName: "content", publicName: "content", isSignal: true, isRequired: false, transformFunction: null }, payload: { classPropertyName: "payload", publicName: "payload", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n [ngClass]=\"getPopoverPosition()\"\n *ngIf=\"content()\"\n class=\"popover-container\"\n>\n <ng-container\n [ngTemplateOutlet]=\"content()\"\n [ngTemplateOutletContext]=\"{\n $implicit: payload(),\n }\"\n ></ng-container>\n</div>\n", styles: [":host{--bs-popover-border-width: 1px;--bs-popover-arrow-width: .5rem;--bs-popover-arrow-border: var(--bs-border-color, #000);--box-shadow-bg: rgba(0, 0, 0, .16)}.popover-container{box-shadow:var(--box-shadow-bg);background:var(--bs-body-bg, #fff);border:var(--bs-popover-border-width) solid var(--bs-border-color, #000);pointer-events:none;position:relative;padding:1rem;pointer-events:all}.popover-container.center-bottom:after,.popover-container.center-bottom:before{bottom:100%;left:50%;transform:translate(-50%)}.popover-container.start-bottom:after,.popover-container.start-bottom:before{bottom:100%;left:85%;transform:translate(-50%)}.popover-container.end-bottom:after,.popover-container.end-bottom:before{bottom:100%;left:15%;transform:translate(-50%)}.popover-container.center-top:after,.popover-container.center-top:before{top:100%;left:50%;transform:translate(-50%) rotate(180deg)}.popover-container.start-top:after,.popover-container.start-top:before{top:100%;left:85%;transform:translate(-50%) rotate(180deg)}.popover-container.end-top:after,.popover-container.end-top:before{top:100%;left:15%;transform:translate(-50%) rotate(180deg)}.popover-container.end-center:after,.popover-container.end-center:before{right:100%;top:50%;transform:translateY(-50%) rotate(270deg)}.popover-container.start-center:after,.popover-container.start-center:before{left:100%;top:50%;transform:translateY(-50%) rotate(90deg)}.popover-container:after,.popover-container:before{content:\"\";display:block;position:absolute;width:0;height:0;border-style:solid}.popover-container:after{border-color:transparent transparent var(--bs-body-bg, #fff) transparent;border-width:var(--bs-popover-arrow-width)}.popover-container:before{border-color:transparent transparent var(--bs-border-color, #000) transparent;border-width:calc(var(--bs-popover-arrow-width) + 1px)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
43
|
+
}
|
|
44
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangPopoverComponent, decorators: [{
|
|
45
|
+
type: Component,
|
|
46
|
+
args: [{ selector: 'quang-popover', imports: [NgTemplateOutlet, NgClass, NgIf], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n [ngClass]=\"getPopoverPosition()\"\n *ngIf=\"content()\"\n class=\"popover-container\"\n>\n <ng-container\n [ngTemplateOutlet]=\"content()\"\n [ngTemplateOutletContext]=\"{\n $implicit: payload(),\n }\"\n ></ng-container>\n</div>\n", styles: [":host{--bs-popover-border-width: 1px;--bs-popover-arrow-width: .5rem;--bs-popover-arrow-border: var(--bs-border-color, #000);--box-shadow-bg: rgba(0, 0, 0, .16)}.popover-container{box-shadow:var(--box-shadow-bg);background:var(--bs-body-bg, #fff);border:var(--bs-popover-border-width) solid var(--bs-border-color, #000);pointer-events:none;position:relative;padding:1rem;pointer-events:all}.popover-container.center-bottom:after,.popover-container.center-bottom:before{bottom:100%;left:50%;transform:translate(-50%)}.popover-container.start-bottom:after,.popover-container.start-bottom:before{bottom:100%;left:85%;transform:translate(-50%)}.popover-container.end-bottom:after,.popover-container.end-bottom:before{bottom:100%;left:15%;transform:translate(-50%)}.popover-container.center-top:after,.popover-container.center-top:before{top:100%;left:50%;transform:translate(-50%) rotate(180deg)}.popover-container.start-top:after,.popover-container.start-top:before{top:100%;left:85%;transform:translate(-50%) rotate(180deg)}.popover-container.end-top:after,.popover-container.end-top:before{top:100%;left:15%;transform:translate(-50%) rotate(180deg)}.popover-container.end-center:after,.popover-container.end-center:before{right:100%;top:50%;transform:translateY(-50%) rotate(270deg)}.popover-container.start-center:after,.popover-container.start-center:before{left:100%;top:50%;transform:translateY(-50%) rotate(90deg)}.popover-container:after,.popover-container:before{content:\"\";display:block;position:absolute;width:0;height:0;border-style:solid}.popover-container:after{border-color:transparent transparent var(--bs-body-bg, #fff) transparent;border-width:var(--bs-popover-arrow-width)}.popover-container:before{border-color:transparent transparent var(--bs-border-color, #000) transparent;border-width:calc(var(--bs-popover-arrow-width) + 1px)}\n"] }]
|
|
47
|
+
}] });
|
|
48
|
+
|
|
49
|
+
class QuangPopoverDirective extends QuangBaseOverlayDirective {
|
|
50
|
+
constructor() {
|
|
51
|
+
super(...arguments);
|
|
52
|
+
this.targetComponentType = signal(QuangPopoverComponent);
|
|
53
|
+
this.content = input.required({ alias: 'quangPopover' });
|
|
54
|
+
}
|
|
55
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangPopoverDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
|
|
56
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.2.5", type: QuangPopoverDirective, isStandalone: true, selector: "[quangPopover]", inputs: { content: { classPropertyName: "content", publicName: "quangPopover", isSignal: true, isRequired: true, transformFunction: null } }, usesInheritance: true, ngImport: i0 }); }
|
|
57
|
+
}
|
|
58
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.5", ngImport: i0, type: QuangPopoverDirective, decorators: [{
|
|
59
|
+
type: Directive,
|
|
60
|
+
args: [{
|
|
61
|
+
selector: '[quangPopover]',
|
|
62
|
+
}]
|
|
63
|
+
}] });
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Generated bundle index. Do not edit.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
export { QuangPopoverDirective };
|
|
70
|
+
//# sourceMappingURL=quang-overlay-popover.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quang-overlay-popover.mjs","sources":["../../../projects/quang/overlay/popover/popover.component.ts","../../../projects/quang/overlay/popover/popover.component.html","../../../projects/quang/overlay/popover/popover.directive.ts","../../../projects/quang/overlay/popover/quang-overlay-popover.ts"],"sourcesContent":["import { ConnectionPositionPair } from '@angular/cdk/overlay'\nimport { NgClass, NgIf, NgTemplateOutlet } from '@angular/common'\nimport { ChangeDetectionStrategy, Component, TemplateRef, input, signal } from '@angular/core'\nimport { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop'\n\nimport { QuangBaseOverlayComponent } from 'quang/overlay/shared'\n\n@Component({\n selector: 'quang-popover',\n imports: [NgTemplateOutlet, NgClass, NgIf],\n templateUrl: './popover.component.html',\n styleUrl: './popover.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Popover component that can render custom content, passed from the outside as a `TemplateRef`\n * @example\n * <button\n [quangPopover]=\"popoverTest\"\n [scrollCloseThreshold]=\"undefined\"\n class=\"btn popover-test-button\"\n overlayPosition=\"top\"\n showMethod=\"click\"\n >\n {{ 'buttons.popover' | transloco }}\n <span>CLICK</span>\n </button>\n <ng-template #popoverTest> <span>test works!</span> <button type=\"button\">click!</button> </ng-template>\n */\nexport class QuangPopoverComponent implements QuangBaseOverlayComponent {\n content = input<TemplateRef<any> | null>(null)\n\n positionPair = signal<ConnectionPositionPair | null>(null)\n\n payload = input<any>()\n\n getPopoverPosition = signal<string>('')\n\n onChangePositionPair$ = toObservable(this.positionPair)\n .pipe(takeUntilDestroyed())\n .subscribe((positionPair) => {\n const originX = positionPair?.originX\n const originY = positionPair?.originY\n if (originX && originY) {\n this.getPopoverPosition.set(`${originX}-${originY}`)\n } else {\n this.getPopoverPosition.set('')\n }\n })\n}\n","<div\n [ngClass]=\"getPopoverPosition()\"\n *ngIf=\"content()\"\n class=\"popover-container\"\n>\n <ng-container\n [ngTemplateOutlet]=\"content()\"\n [ngTemplateOutletContext]=\"{\n $implicit: payload(),\n }\"\n ></ng-container>\n</div>\n","import { ComponentType } from '@angular/cdk/portal'\nimport { Directive, TemplateRef, input, signal } from '@angular/core'\n\nimport { QuangBaseOverlayDirective } from 'quang/overlay/shared'\n\nimport { QuangPopoverComponent } from './popover.component'\n\n@Directive({\n selector: '[quangPopover]',\n})\nexport class QuangPopoverDirective extends QuangBaseOverlayDirective<QuangPopoverComponent> {\n override targetComponentType = signal<ComponentType<QuangPopoverComponent> | undefined>(QuangPopoverComponent)\n\n override content = input.required<TemplateRef<any> | null>({ alias: 'quangPopover' })\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|