iss-ctrl 0.0.21 → 0.0.22

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 (141) hide show
  1. package/README.md +33 -0
  2. package/fesm2022/iss-ctrl-attachment.viewer-DVUL39xd.mjs +110 -0
  3. package/fesm2022/iss-ctrl-attachment.viewer-DVUL39xd.mjs.map +1 -0
  4. package/fesm2022/iss-ctrl-base.mjs +663 -0
  5. package/fesm2022/iss-ctrl-base.mjs.map +1 -0
  6. package/fesm2022/iss-ctrl-checkbox.field-Dj5EGLUr.mjs +92 -0
  7. package/fesm2022/iss-ctrl-checkbox.field-Dj5EGLUr.mjs.map +1 -0
  8. package/fesm2022/iss-ctrl-checkbox.mjs +143 -0
  9. package/fesm2022/iss-ctrl-checkbox.mjs.map +1 -0
  10. package/fesm2022/iss-ctrl-checkbox.viewer-C3SEUszR.mjs +31 -0
  11. package/fesm2022/iss-ctrl-checkbox.viewer-C3SEUszR.mjs.map +1 -0
  12. package/fesm2022/iss-ctrl-chips.field-BLLAjBbP.mjs +76 -0
  13. package/fesm2022/iss-ctrl-chips.field-BLLAjBbP.mjs.map +1 -0
  14. package/fesm2022/iss-ctrl-chips.mjs +168 -0
  15. package/fesm2022/iss-ctrl-chips.mjs.map +1 -0
  16. package/fesm2022/iss-ctrl-chips.viewer-BcKT2hcq.mjs +38 -0
  17. package/fesm2022/iss-ctrl-chips.viewer-BcKT2hcq.mjs.map +1 -0
  18. package/fesm2022/iss-ctrl-date-picker.field-BSpXukpO.mjs +98 -0
  19. package/fesm2022/iss-ctrl-date-picker.field-BSpXukpO.mjs.map +1 -0
  20. package/fesm2022/iss-ctrl-date-picker.mjs +200 -0
  21. package/fesm2022/iss-ctrl-date-picker.mjs.map +1 -0
  22. package/fesm2022/iss-ctrl-date-picker.viewer-Dsmsf91t.mjs +40 -0
  23. package/fesm2022/iss-ctrl-date-picker.viewer-Dsmsf91t.mjs.map +1 -0
  24. package/fesm2022/iss-ctrl-date-range-picker.field-CjNHU1RW.mjs +97 -0
  25. package/fesm2022/iss-ctrl-date-range-picker.field-CjNHU1RW.mjs.map +1 -0
  26. package/fesm2022/iss-ctrl-date-range-picker.mjs +307 -0
  27. package/fesm2022/iss-ctrl-date-range-picker.mjs.map +1 -0
  28. package/fesm2022/iss-ctrl-date-range-picker.viewer-tmTQGPFh.mjs +41 -0
  29. package/fesm2022/iss-ctrl-date-range-picker.viewer-tmTQGPFh.mjs.map +1 -0
  30. package/fesm2022/iss-ctrl-datetime-picker.field-DGMY9PaU.mjs +98 -0
  31. package/fesm2022/iss-ctrl-datetime-picker.field-DGMY9PaU.mjs.map +1 -0
  32. package/fesm2022/iss-ctrl-datetime-picker.mjs +226 -0
  33. package/fesm2022/iss-ctrl-datetime-picker.mjs.map +1 -0
  34. package/fesm2022/iss-ctrl-datetime-picker.viewer-BeUyEBKo.mjs +42 -0
  35. package/fesm2022/iss-ctrl-datetime-picker.viewer-BeUyEBKo.mjs.map +1 -0
  36. package/fesm2022/iss-ctrl-file-picker.field-CbepZaX6.mjs +210 -0
  37. package/fesm2022/iss-ctrl-file-picker.field-CbepZaX6.mjs.map +1 -0
  38. package/fesm2022/iss-ctrl-file-picker.mjs +272 -0
  39. package/fesm2022/iss-ctrl-file-picker.mjs.map +1 -0
  40. package/fesm2022/iss-ctrl-input.field-Ctlf3OCN.mjs +104 -0
  41. package/fesm2022/iss-ctrl-input.field-Ctlf3OCN.mjs.map +1 -0
  42. package/fesm2022/iss-ctrl-input.mjs +204 -0
  43. package/fesm2022/iss-ctrl-input.mjs.map +1 -0
  44. package/fesm2022/iss-ctrl-input.viewer-BOZnW0_e.mjs +22 -0
  45. package/fesm2022/iss-ctrl-input.viewer-BOZnW0_e.mjs.map +1 -0
  46. package/fesm2022/iss-ctrl-iss-ctrl-DvnkwSMG.mjs +1789 -0
  47. package/fesm2022/iss-ctrl-iss-ctrl-DvnkwSMG.mjs.map +1 -0
  48. package/fesm2022/{iss-ctrl-load-event-bOt6IlIo.mjs → iss-ctrl-load-event-CuZ7pMjk.mjs} +4 -3
  49. package/fesm2022/iss-ctrl-load-event-CuZ7pMjk.mjs.map +1 -0
  50. package/fesm2022/{iss-ctrl-load-options-event-CxyAyNMe.mjs → iss-ctrl-load-options-event-B10rhdqh.mjs} +3 -3
  51. package/fesm2022/{iss-ctrl-load-options-event-CxyAyNMe.mjs.map → iss-ctrl-load-options-event-B10rhdqh.mjs.map} +1 -1
  52. package/fesm2022/{iss-ctrl-load-value-event-DJKJ5S3h.mjs → iss-ctrl-load-value-event-C-aRgKLx.mjs} +3 -3
  53. package/fesm2022/{iss-ctrl-load-value-event-DJKJ5S3h.mjs.map → iss-ctrl-load-value-event-C-aRgKLx.mjs.map} +1 -1
  54. package/fesm2022/iss-ctrl-mobile.field-DXVYT3q-.mjs +77 -0
  55. package/fesm2022/iss-ctrl-mobile.field-DXVYT3q-.mjs.map +1 -0
  56. package/fesm2022/iss-ctrl-mobile.mjs +2465 -0
  57. package/fesm2022/iss-ctrl-mobile.mjs.map +1 -0
  58. package/fesm2022/iss-ctrl-mobile.viewer-DQgxAcR-.mjs +22 -0
  59. package/fesm2022/iss-ctrl-mobile.viewer-DQgxAcR-.mjs.map +1 -0
  60. package/fesm2022/{iss-ctrl-note.field-B_Lbp28X.mjs → iss-ctrl-note.field-C8X9-mgD.mjs} +2 -2
  61. package/fesm2022/{iss-ctrl-note.field-B_Lbp28X.mjs.map → iss-ctrl-note.field-C8X9-mgD.mjs.map} +1 -1
  62. package/fesm2022/iss-ctrl-plate.field-aI81tAOV.mjs +92 -0
  63. package/fesm2022/iss-ctrl-plate.field-aI81tAOV.mjs.map +1 -0
  64. package/fesm2022/iss-ctrl-plate.mjs +491 -0
  65. package/fesm2022/iss-ctrl-plate.mjs.map +1 -0
  66. package/fesm2022/iss-ctrl-plate.viewer-B8PUBLH8.mjs +179 -0
  67. package/fesm2022/iss-ctrl-plate.viewer-B8PUBLH8.mjs.map +1 -0
  68. package/fesm2022/iss-ctrl-radio.field-B_JjPIlb.mjs +96 -0
  69. package/fesm2022/iss-ctrl-radio.field-B_JjPIlb.mjs.map +1 -0
  70. package/fesm2022/iss-ctrl-radio.mjs +101 -0
  71. package/fesm2022/iss-ctrl-radio.mjs.map +1 -0
  72. package/fesm2022/iss-ctrl-radio.viewer-EiDliZro.mjs +30 -0
  73. package/fesm2022/iss-ctrl-radio.viewer-EiDliZro.mjs.map +1 -0
  74. package/fesm2022/{iss-ctrl-replace-api-keys-C0XYQW4i.mjs → iss-ctrl-replace-api-keys-DLnagkOr.mjs} +2 -2
  75. package/fesm2022/{iss-ctrl-replace-api-keys-C0XYQW4i.mjs.map → iss-ctrl-replace-api-keys-DLnagkOr.mjs.map} +1 -1
  76. package/fesm2022/iss-ctrl-select.field-DoU4G_8t.mjs +87 -0
  77. package/fesm2022/iss-ctrl-select.field-DoU4G_8t.mjs.map +1 -0
  78. package/fesm2022/iss-ctrl-select.mjs +387 -0
  79. package/fesm2022/iss-ctrl-select.mjs.map +1 -0
  80. package/fesm2022/iss-ctrl-select.viewer-Dv9M-lG-.mjs +30 -0
  81. package/fesm2022/iss-ctrl-select.viewer-Dv9M-lG-.mjs.map +1 -0
  82. package/fesm2022/{iss-ctrl-set-value-event-CgXhi0Bv.mjs → iss-ctrl-set-value-event-Dhw0Vj5J.mjs} +2 -2
  83. package/fesm2022/{iss-ctrl-set-value-event-CgXhi0Bv.mjs.map → iss-ctrl-set-value-event-Dhw0Vj5J.mjs.map} +1 -1
  84. package/fesm2022/iss-ctrl-slide-toggle.field-TVVbAr6p.mjs +85 -0
  85. package/fesm2022/iss-ctrl-slide-toggle.field-TVVbAr6p.mjs.map +1 -0
  86. package/fesm2022/iss-ctrl-slide-toggle.mjs +72 -0
  87. package/fesm2022/iss-ctrl-slide-toggle.mjs.map +1 -0
  88. package/fesm2022/iss-ctrl-slide-toggle.viewer-hsIHwDj3.mjs +34 -0
  89. package/fesm2022/iss-ctrl-slide-toggle.viewer-hsIHwDj3.mjs.map +1 -0
  90. package/fesm2022/{iss-ctrl-table.field-B5FxF6hn.mjs → iss-ctrl-table.field-E0r9w0os.mjs} +142 -140
  91. package/fesm2022/iss-ctrl-table.field-E0r9w0os.mjs.map +1 -0
  92. package/fesm2022/iss-ctrl-textarea.field-CmHPDpk-.mjs +82 -0
  93. package/fesm2022/iss-ctrl-textarea.field-CmHPDpk-.mjs.map +1 -0
  94. package/fesm2022/iss-ctrl-textarea.mjs +115 -0
  95. package/fesm2022/iss-ctrl-textarea.mjs.map +1 -0
  96. package/fesm2022/iss-ctrl-textarea.viewer-CpmLauik.mjs +22 -0
  97. package/fesm2022/iss-ctrl-textarea.viewer-CpmLauik.mjs.map +1 -0
  98. package/fesm2022/iss-ctrl-time-picker.field-Cb0I5Ut1.mjs +77 -0
  99. package/fesm2022/iss-ctrl-time-picker.field-Cb0I5Ut1.mjs.map +1 -0
  100. package/fesm2022/iss-ctrl-time-picker.mjs +170 -0
  101. package/fesm2022/iss-ctrl-time-picker.mjs.map +1 -0
  102. package/fesm2022/iss-ctrl-time-picker.viewer-CJeFLrdI.mjs +22 -0
  103. package/fesm2022/iss-ctrl-time-picker.viewer-CJeFLrdI.mjs.map +1 -0
  104. package/fesm2022/iss-ctrl-toggle-button.field-Bj8WrkB-.mjs +105 -0
  105. package/fesm2022/iss-ctrl-toggle-button.field-Bj8WrkB-.mjs.map +1 -0
  106. package/fesm2022/iss-ctrl-toggle-button.mjs +156 -0
  107. package/fesm2022/iss-ctrl-toggle-button.mjs.map +1 -0
  108. package/fesm2022/iss-ctrl-toggle-button.viewer-CC-8_Dy4.mjs +30 -0
  109. package/fesm2022/iss-ctrl-toggle-button.viewer-CC-8_Dy4.mjs.map +1 -0
  110. package/fesm2022/iss-ctrl-tokens.mjs +25 -0
  111. package/fesm2022/iss-ctrl-tokens.mjs.map +1 -0
  112. package/fesm2022/{iss-ctrl-trigger-based-on-json-value-2v1kLVHZ.mjs → iss-ctrl-trigger-based-on-json-value-D9rTXVD1.mjs} +2 -2
  113. package/fesm2022/{iss-ctrl-trigger-based-on-json-value-2v1kLVHZ.mjs.map → iss-ctrl-trigger-based-on-json-value-D9rTXVD1.mjs.map} +1 -1
  114. package/fesm2022/{iss-ctrl-user-picker.field-BH63sZ-X.mjs → iss-ctrl-user-picker.field-BIzB5ZX6.mjs} +151 -150
  115. package/fesm2022/iss-ctrl-user-picker.field-BIzB5ZX6.mjs.map +1 -0
  116. package/fesm2022/iss-ctrl.mjs +3 -1
  117. package/fesm2022/iss-ctrl.mjs.map +1 -1
  118. package/package.json +69 -1
  119. package/types/iss-ctrl-base.d.ts +306 -0
  120. package/types/iss-ctrl-checkbox.d.ts +45 -0
  121. package/types/iss-ctrl-chips.d.ts +41 -0
  122. package/types/iss-ctrl-date-picker.d.ts +75 -0
  123. package/types/iss-ctrl-date-range-picker.d.ts +95 -0
  124. package/types/iss-ctrl-datetime-picker.d.ts +77 -0
  125. package/types/iss-ctrl-file-picker.d.ts +95 -0
  126. package/types/iss-ctrl-input.d.ts +76 -0
  127. package/types/iss-ctrl-mobile.d.ts +91 -0
  128. package/types/iss-ctrl-plate.d.ts +54 -0
  129. package/types/iss-ctrl-radio.d.ts +34 -0
  130. package/types/iss-ctrl-select.d.ts +75 -0
  131. package/types/iss-ctrl-slide-toggle.d.ts +26 -0
  132. package/types/iss-ctrl-textarea.d.ts +30 -0
  133. package/types/iss-ctrl-time-picker.d.ts +48 -0
  134. package/types/iss-ctrl-toggle-button.d.ts +41 -0
  135. package/types/iss-ctrl-tokens.d.ts +21 -0
  136. package/types/iss-ctrl.d.ts +120 -1810
  137. package/fesm2022/iss-ctrl-iss-ctrl-BKu6a5HF.mjs +0 -9683
  138. package/fesm2022/iss-ctrl-iss-ctrl-BKu6a5HF.mjs.map +0 -1
  139. package/fesm2022/iss-ctrl-load-event-bOt6IlIo.mjs.map +0 -1
  140. package/fesm2022/iss-ctrl-table.field-B5FxF6hn.mjs.map +0 -1
  141. package/fesm2022/iss-ctrl-user-picker.field-BH63sZ-X.mjs.map +0 -1
@@ -0,0 +1,226 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, Component } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { FormGroup, FormControl, ReactiveFormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
5
+ import { MatDatepickerModule } from '@angular/material/datepicker';
6
+ import { MatFormFieldModule } from '@angular/material/form-field';
7
+ import { MatInputModule } from '@angular/material/input';
8
+ import { MatTimepickerModule } from '@angular/material/timepicker';
9
+ import { format } from 'date-fns';
10
+ import { ControlBase } from 'iss-ctrl/base';
11
+ import { DatePickerControl } from 'iss-ctrl/date-picker';
12
+ import { TimePickerControl } from 'iss-ctrl/time-picker';
13
+
14
+ /**
15
+ * `<iss-ctrl-datetime-picker>` — a date and a time in a single field.
16
+ *
17
+ * Combines the calendar of the date picker with the time list of the time picker; both parts
18
+ * must be set before a value is emitted.
19
+ *
20
+ * @example
21
+ * ```html
22
+ * <iss-ctrl-datetime-picker formControlName="scheduledAt" [minDate]="today" minTime="08:00" maxTime="17:00">
23
+ * <label>Scheduled at</label>
24
+ * </iss-ctrl-datetime-picker>
25
+ * ```
26
+ *
27
+ * ### Own inputs
28
+ * | Property | Type | Default | Description |
29
+ * | --- | --- | --- | --- |
30
+ * | `minDate` | `Date \| null` | `null` | Earliest selectable date. |
31
+ * | `maxDate` | `Date \| null` | `null` | Latest selectable date. |
32
+ * | `minTime` | `string \| null` | `null` | Earliest selectable time, `HH:mm`. |
33
+ * | `maxTime` | `string \| null` | `null` | Latest selectable time, `HH:mm`. |
34
+ * | `disabledDays` | `number[]` | `[]` | Week days to block, `0` = Sunday … `6` = Saturday. |
35
+ * | `hijriCalendar` | `boolean` | `false` | Shows an Umm al-Qura Hijri calendar; the value stays Gregorian. |
36
+ * | `emitHijri` | `boolean` | `false` | Emits the date half as a Hijri date. Implies `hijriCalendar`. |
37
+ *
38
+ * ### Hijri dates
39
+ * Both flags are handed straight to the inner date picker; the time half is untouched, so a
40
+ * Hijri value reads `1447-03-15T09:30:00`.
41
+ *
42
+ * ### Inherited from {@link ControlBase}
43
+ * `formControlName` · `readonly` · `className` · `(onChange)`
44
+ *
45
+ * Projects `<label>` into the floating label; omit it to render the control without one.
46
+ */
47
+ class DatetimePickerControl extends ControlBase {
48
+ datetimeForm = new FormGroup({
49
+ date: new FormControl(null),
50
+ time: new FormControl(null),
51
+ });
52
+ /**
53
+ * Week days that cannot be selected — `0` is Sunday through `6` for Saturday.
54
+ */
55
+ disabledDays = input([], ...(ngDevMode ? [{ debugName: "disabledDays" }] : /* istanbul ignore next */ []));
56
+ /**
57
+ * Earliest selectable date.
58
+ */
59
+ minDate = input(null, ...(ngDevMode ? [{ debugName: "minDate" }] : /* istanbul ignore next */ []));
60
+ /**
61
+ * Latest selectable date.
62
+ */
63
+ maxDate = input(null, ...(ngDevMode ? [{ debugName: "maxDate" }] : /* istanbul ignore next */ []));
64
+ /**
65
+ * Earliest selectable time of day, as `HH:mm`.
66
+ */
67
+ minTime = input(null, ...(ngDevMode ? [{ debugName: "minTime" }] : /* istanbul ignore next */ []));
68
+ /**
69
+ * Latest selectable time of day, as `HH:mm`.
70
+ */
71
+ maxTime = input(null, ...(ngDevMode ? [{ debugName: "maxTime" }] : /* istanbul ignore next */ []));
72
+ /**
73
+ * Renders the calendar as an Umm al-Qura Hijri calendar, leaving the emitted date Gregorian.
74
+ */
75
+ hijriCalendar = input(false, ...(ngDevMode ? [{ debugName: "hijriCalendar" }] : /* istanbul ignore next */ []));
76
+ /**
77
+ * Emits the date half of the value as a Hijri date. Implies {@link hijriCalendar}.
78
+ */
79
+ emitHijri = input(false, ...(ngDevMode ? [{ debugName: "emitHijri" }] : /* istanbul ignore next */ []));
80
+ setDisabledState(isDisabled) {
81
+ super.setDisabledState(isDisabled);
82
+ // the template binds `datetimeForm`, disabling ctrl alone leaves the pickers live
83
+ if (isDisabled) {
84
+ this.datetimeForm.disable({ emitEvent: false });
85
+ }
86
+ else {
87
+ this.datetimeForm.enable({ emitEvent: false });
88
+ }
89
+ }
90
+ emit() {
91
+ if (this.readonly()) {
92
+ return;
93
+ }
94
+ const datetimeStr = this.#stringifyDateTime(this.datetimeForm.getRawValue());
95
+ this.propagateValue(datetimeStr);
96
+ this.emitOnChangeEvent(datetimeStr);
97
+ }
98
+ writeValue(value) {
99
+ this.datetimeForm.patchValue({
100
+ date: this.#stringifyDate(value),
101
+ time: this.#stringifyTime(value),
102
+ });
103
+ }
104
+ #stringifyDateTime(datetime) {
105
+ if (!datetime) {
106
+ return undefined;
107
+ }
108
+ if (this.#stringifyDate(datetime) && this.#stringifyTime(datetime)) {
109
+ return `${this.#stringifyDate(datetime)}T${this.#stringifyTime(datetime)}`;
110
+ }
111
+ return undefined;
112
+ }
113
+ #stringifyDate(datetime) {
114
+ if (!datetime) {
115
+ return undefined;
116
+ }
117
+ if (datetime.date && typeof datetime.date === "string") {
118
+ return `${datetime.date.split("T")[0]}`;
119
+ }
120
+ const date = new Date(datetime);
121
+ if (!Number.isNaN(date.getTime())) {
122
+ return format(datetime, "yyyy-MM-dd");
123
+ }
124
+ return undefined;
125
+ }
126
+ #stringifyTime(datetime) {
127
+ if (!datetime) {
128
+ return undefined;
129
+ }
130
+ if (datetime.time && typeof datetime.time === "string") {
131
+ return `${datetime.time}`;
132
+ }
133
+ const date = new Date(datetime);
134
+ if (!Number.isNaN(date.getTime())) {
135
+ return format(datetime, "HH:mm:ss");
136
+ }
137
+ return undefined;
138
+ }
139
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DatetimePickerControl, deps: null, target: i0.ɵɵFactoryTarget.Component });
140
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: DatetimePickerControl, isStandalone: true, selector: "iss-ctrl-datetime-picker", inputs: { disabledDays: { classPropertyName: "disabledDays", publicName: "disabledDays", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, minTime: { classPropertyName: "minTime", publicName: "minTime", isSignal: true, isRequired: false, transformFunction: null }, maxTime: { classPropertyName: "maxTime", publicName: "maxTime", isSignal: true, isRequired: false, transformFunction: null }, hijriCalendar: { classPropertyName: "hijriCalendar", publicName: "hijriCalendar", isSignal: true, isRequired: false, transformFunction: null }, emitHijri: { classPropertyName: "emitHijri", publicName: "emitHijri", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
141
+ { provide: NG_VALUE_ACCESSOR, useExisting: DatetimePickerControl, multi: true },
142
+ { provide: NG_VALIDATORS, useExisting: DatetimePickerControl, multi: true },
143
+ ], usesInheritance: true, ngImport: i0, template: `
144
+ <form [formGroup]="datetimeForm" class="d-flex flex-row gap-1">
145
+ <iss-ctrl-date-picker
146
+ (focusout)="markAsTouched()"
147
+ [disabledDays]="disabledDays()"
148
+ [maxDate]="maxDate()"
149
+ [minDate]="minDate()"
150
+ [readonly]="readonly()"
151
+ [hijriCalendar]="hijriCalendar()"
152
+ [emitHijri]="emitHijri()"
153
+ formControlName="date"
154
+ (onChange)="emit()"
155
+ >
156
+ <!-- Re-projected with ngProjectAs so it still matches the date picker's own select="label";
157
+ wrapping it in a second <label> instead would nest one inside the other and defeat the label rule in upgrade.scss. -->
158
+ <ng-content select="label" ngProjectAs="label"></ng-content>
159
+ </iss-ctrl-date-picker>
160
+ <iss-ctrl-time-picker
161
+ (focusout)="markAsTouched()"
162
+ [maxTime]="maxTime()"
163
+ [minTime]="minTime()"
164
+ [readonly]="readonly()"
165
+ formControlName="time"
166
+ (onChange)="emit()"
167
+ />
168
+ </form>
169
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatTimepickerModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: DatePickerControl, selector: "iss-ctrl-date-picker", inputs: ["disabledDays", "minDate", "maxDate", "hijriCalendar", "emitHijri"] }, { kind: "component", type: TimePickerControl, selector: "iss-ctrl-time-picker", inputs: ["interval", "minTime", "maxTime"] }] });
170
+ }
171
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DatetimePickerControl, decorators: [{
172
+ type: Component,
173
+ args: [{
174
+ selector: "iss-ctrl-datetime-picker",
175
+ imports: [
176
+ MatFormFieldModule,
177
+ MatInputModule,
178
+ MatTimepickerModule,
179
+ MatDatepickerModule,
180
+ ReactiveFormsModule,
181
+ DatePickerControl,
182
+ TimePickerControl,
183
+ ],
184
+ providers: [
185
+ { provide: NG_VALUE_ACCESSOR, useExisting: DatetimePickerControl, multi: true },
186
+ { provide: NG_VALIDATORS, useExisting: DatetimePickerControl, multi: true },
187
+ ],
188
+ template: `
189
+ <form [formGroup]="datetimeForm" class="d-flex flex-row gap-1">
190
+ <iss-ctrl-date-picker
191
+ (focusout)="markAsTouched()"
192
+ [disabledDays]="disabledDays()"
193
+ [maxDate]="maxDate()"
194
+ [minDate]="minDate()"
195
+ [readonly]="readonly()"
196
+ [hijriCalendar]="hijriCalendar()"
197
+ [emitHijri]="emitHijri()"
198
+ formControlName="date"
199
+ (onChange)="emit()"
200
+ >
201
+ <!-- Re-projected with ngProjectAs so it still matches the date picker's own select="label";
202
+ wrapping it in a second <label> instead would nest one inside the other and defeat the label rule in upgrade.scss. -->
203
+ <ng-content select="label" ngProjectAs="label"></ng-content>
204
+ </iss-ctrl-date-picker>
205
+ <iss-ctrl-time-picker
206
+ (focusout)="markAsTouched()"
207
+ [maxTime]="maxTime()"
208
+ [minTime]="minTime()"
209
+ [readonly]="readonly()"
210
+ formControlName="time"
211
+ (onChange)="emit()"
212
+ />
213
+ </form>
214
+ `
215
+ }]
216
+ }], propDecorators: { disabledDays: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabledDays", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], minTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "minTime", required: false }] }], maxTime: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxTime", required: false }] }], hijriCalendar: [{ type: i0.Input, args: [{ isSignal: true, alias: "hijriCalendar", required: false }] }], emitHijri: [{ type: i0.Input, args: [{ isSignal: true, alias: "emitHijri", required: false }] }] } });
217
+
218
+ // The datetime-picker control. Its field and viewer stay in the primary entry point and reach it
219
+ // from there, so the control ships only to an app that renders it or imports it directly.
220
+
221
+ /**
222
+ * Generated bundle index. Do not edit.
223
+ */
224
+
225
+ export { DatetimePickerControl };
226
+ //# sourceMappingURL=iss-ctrl-datetime-picker.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iss-ctrl-datetime-picker.mjs","sources":["../../../projects/iss/datetime-picker/src/datetime-picker.control.ts","../../../projects/iss/datetime-picker/src/public-api.ts","../../../projects/iss/datetime-picker/src/iss-ctrl-datetime-picker.ts"],"sourcesContent":["import { Component, input, InputSignal } from \"@angular/core\";\nimport { FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, ReactiveFormsModule } from \"@angular/forms\";\nimport { MatDatepickerModule } from \"@angular/material/datepicker\";\nimport { MatFormFieldModule } from \"@angular/material/form-field\";\nimport { MatInputModule } from \"@angular/material/input\";\nimport { MatTimepickerModule } from \"@angular/material/timepicker\";\nimport { format } from \"date-fns\";\nimport { ControlBase } from \"iss-ctrl/base\";\nimport { DatePickerControl } from \"iss-ctrl/date-picker\";\nimport { TimePickerControl } from \"iss-ctrl/time-picker\";\n\n/**\n * `<iss-ctrl-datetime-picker>` — a date and a time in a single field.\n *\n * Combines the calendar of the date picker with the time list of the time picker; both parts\n * must be set before a value is emitted.\n *\n * @example\n * ```html\n * <iss-ctrl-datetime-picker formControlName=\"scheduledAt\" [minDate]=\"today\" minTime=\"08:00\" maxTime=\"17:00\">\n * <label>Scheduled at</label>\n * </iss-ctrl-datetime-picker>\n * ```\n *\n * ### Own inputs\n * | Property | Type | Default | Description |\n * | --- | --- | --- | --- |\n * | `minDate` | `Date \\| null` | `null` | Earliest selectable date. |\n * | `maxDate` | `Date \\| null` | `null` | Latest selectable date. |\n * | `minTime` | `string \\| null` | `null` | Earliest selectable time, `HH:mm`. |\n * | `maxTime` | `string \\| null` | `null` | Latest selectable time, `HH:mm`. |\n * | `disabledDays` | `number[]` | `[]` | Week days to block, `0` = Sunday … `6` = Saturday. |\n * | `hijriCalendar` | `boolean` | `false` | Shows an Umm al-Qura Hijri calendar; the value stays Gregorian. |\n * | `emitHijri` | `boolean` | `false` | Emits the date half as a Hijri date. Implies `hijriCalendar`. |\n *\n * ### Hijri dates\n * Both flags are handed straight to the inner date picker; the time half is untouched, so a\n * Hijri value reads `1447-03-15T09:30:00`.\n *\n * ### Inherited from {@link ControlBase}\n * `formControlName` · `readonly` · `className` · `(onChange)`\n *\n * Projects `<label>` into the floating label; omit it to render the control without one.\n */\n@Component({\n selector: \"iss-ctrl-datetime-picker\",\n imports: [\n MatFormFieldModule,\n MatInputModule,\n MatTimepickerModule,\n MatDatepickerModule,\n ReactiveFormsModule,\n DatePickerControl,\n TimePickerControl,\n ],\n providers: [\n { provide: NG_VALUE_ACCESSOR, useExisting: DatetimePickerControl, multi: true },\n { provide: NG_VALIDATORS, useExisting: DatetimePickerControl, multi: true },\n ],\n template: `\n <form [formGroup]=\"datetimeForm\" class=\"d-flex flex-row gap-1\">\n <iss-ctrl-date-picker\n (focusout)=\"markAsTouched()\"\n [disabledDays]=\"disabledDays()\"\n [maxDate]=\"maxDate()\"\n [minDate]=\"minDate()\"\n [readonly]=\"readonly()\"\n [hijriCalendar]=\"hijriCalendar()\"\n [emitHijri]=\"emitHijri()\"\n formControlName=\"date\"\n (onChange)=\"emit()\"\n >\n <!-- Re-projected with ngProjectAs so it still matches the date picker's own select=\"label\";\n wrapping it in a second <label> instead would nest one inside the other and defeat the label rule in upgrade.scss. -->\n <ng-content select=\"label\" ngProjectAs=\"label\"></ng-content>\n </iss-ctrl-date-picker>\n <iss-ctrl-time-picker\n (focusout)=\"markAsTouched()\"\n [maxTime]=\"maxTime()\"\n [minTime]=\"minTime()\"\n [readonly]=\"readonly()\"\n formControlName=\"time\"\n (onChange)=\"emit()\"\n />\n </form>\n `\n})\nexport class DatetimePickerControl extends ControlBase {\n datetimeForm: FormGroup = new FormGroup({\n date: new FormControl(null),\n time: new FormControl(null),\n });\n /**\n * Week days that cannot be selected — `0` is Sunday through `6` for Saturday.\n */\n disabledDays: InputSignal<number[]> = input<number[]>([]);\n /**\n * Earliest selectable date.\n */\n minDate: InputSignal<Date | null> = input<Date | null>(null);\n /**\n * Latest selectable date.\n */\n maxDate: InputSignal<Date | null> = input<Date | null>(null);\n /**\n * Earliest selectable time of day, as `HH:mm`.\n */\n minTime: InputSignal<string | null> = input<string | null>(null);\n /**\n * Latest selectable time of day, as `HH:mm`.\n */\n maxTime: InputSignal<string | null> = input<string | null>(null);\n /**\n * Renders the calendar as an Umm al-Qura Hijri calendar, leaving the emitted date Gregorian.\n */\n hijriCalendar: InputSignal<boolean> = input(false);\n /**\n * Emits the date half of the value as a Hijri date. Implies {@link hijriCalendar}.\n */\n emitHijri: InputSignal<boolean> = input(false);\n\n override setDisabledState(isDisabled: boolean): void {\n super.setDisabledState(isDisabled);\n // the template binds `datetimeForm`, disabling ctrl alone leaves the pickers live\n if (isDisabled) {\n this.datetimeForm.disable({ emitEvent: false });\n } else {\n this.datetimeForm.enable({ emitEvent: false });\n }\n }\n\n emit() {\n if (this.readonly()) {\n return;\n }\n const datetimeStr = this.#stringifyDateTime(this.datetimeForm.getRawValue());\n this.propagateValue(datetimeStr);\n this.emitOnChangeEvent(datetimeStr);\n }\n\n override writeValue(value: string | Date | null) {\n this.datetimeForm.patchValue({\n date: this.#stringifyDate(value),\n time: this.#stringifyTime(value),\n });\n }\n\n #stringifyDateTime(datetime: any): string | undefined {\n if (!datetime) {\n return undefined;\n }\n if (this.#stringifyDate(datetime) && this.#stringifyTime(datetime)) {\n return `${this.#stringifyDate(datetime)}T${this.#stringifyTime(datetime)}`;\n }\n return undefined;\n }\n\n #stringifyDate(datetime: any) {\n if (!datetime) {\n return undefined;\n }\n\n if (datetime.date && typeof datetime.date === \"string\") {\n return `${datetime.date.split(\"T\")[0]}`;\n }\n\n const date = new Date(datetime);\n if (!Number.isNaN(date.getTime())) {\n return format(datetime, \"yyyy-MM-dd\");\n }\n return undefined;\n }\n\n #stringifyTime(datetime: any) {\n if (!datetime) {\n return undefined;\n }\n\n if (datetime.time && typeof datetime.time === \"string\") {\n return `${datetime.time}`;\n }\n\n const date = new Date(datetime);\n if (!Number.isNaN(date.getTime())) {\n return format(datetime, \"HH:mm:ss\");\n }\n return undefined;\n }\n}\n","// The datetime-picker control. Its field and viewer stay in the primary entry point and reach it\n// from there, so the control ships only to an app that renders it or imports it directly.\n\nexport * from \"./datetime-picker.control\";\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { DatePipe } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { computed, Component } from '@angular/core';
4
+ import { ViewerBase, DATETIME_FORMAT, toHijriDisplay } from 'iss-ctrl/base';
5
+
6
+ class DatePickerTimeViewer extends ViewerBase {
7
+ DATETIME_FORMAT = DATETIME_FORMAT;
8
+ // a field picked on the Hijri calendar reads back as a Hijri date, whichever calendar its
9
+ // stored value is in
10
+ hijriDatetime = computed(() => toHijriDisplay(this.field().ctrlValue(), {
11
+ hijriCalendar: this.field().config?.hijriCalendar(),
12
+ emitHijri: this.field().config?.emitHijri(),
13
+ withTime: true,
14
+ }), ...(ngDevMode ? [{ debugName: "hijriDatetime" }] : /* istanbul ignore next */ []));
15
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DatePickerTimeViewer, deps: null, target: i0.ɵɵFactoryTarget.Component });
16
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: DatePickerTimeViewer, isStandalone: true, selector: "iss-viewer-datetime-picker", usesInheritance: true, ngImport: i0, template: `
17
+ @if (hijriDatetime(); as hijri) {
18
+ {{ hijri }}
19
+ } @else {
20
+ {{ field().ctrlValue() | date: DATETIME_FORMAT }}
21
+ }
22
+ `, isInline: true, dependencies: [{ kind: "pipe", type: DatePipe, name: "date" }] });
23
+ }
24
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: DatePickerTimeViewer, decorators: [{
25
+ type: Component,
26
+ args: [{
27
+ selector: "iss-viewer-datetime-picker",
28
+ imports: [
29
+ DatePipe
30
+ ],
31
+ template: `
32
+ @if (hijriDatetime(); as hijri) {
33
+ {{ hijri }}
34
+ } @else {
35
+ {{ field().ctrlValue() | date: DATETIME_FORMAT }}
36
+ }
37
+ `
38
+ }]
39
+ }] });
40
+
41
+ export { DatePickerTimeViewer };
42
+ //# sourceMappingURL=iss-ctrl-datetime-picker.viewer-BeUyEBKo.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iss-ctrl-datetime-picker.viewer-BeUyEBKo.mjs","sources":["../../../projects/iss/src/components/controls/datetime-picker/datetime-picker.viewer.ts"],"sourcesContent":["import { DatePipe } from \"@angular/common\";\nimport { Component, computed, Signal } from \"@angular/core\";\nimport { DATETIME_FORMAT } from \"iss-ctrl/base\";\nimport { toHijriDisplay } from \"iss-ctrl/base\";\nimport { ViewerBase } from \"iss-ctrl/base\";\n\n@Component({\n selector: \"iss-viewer-datetime-picker\",\n imports: [\n DatePipe\n ],\n template: `\n @if (hijriDatetime(); as hijri) {\n {{ hijri }}\n } @else {\n {{ field().ctrlValue() | date: DATETIME_FORMAT }}\n }\n `\n})\nexport class DatePickerTimeViewer extends ViewerBase {\n protected readonly DATETIME_FORMAT = DATETIME_FORMAT;\n // a field picked on the Hijri calendar reads back as a Hijri date, whichever calendar its\n // stored value is in\n protected hijriDatetime: Signal<string | null> = computed(() => toHijriDisplay(this.field().ctrlValue(), {\n hijriCalendar: this.field().config?.hijriCalendar(),\n emitHijri: this.field().config?.emitHijri(),\n withTime: true,\n }));\n}\n"],"names":[],"mappings":";;;;;AAmBM,MAAO,oBAAqB,SAAQ,UAAU,CAAA;IAC/B,eAAe,GAAG,eAAe;;;AAG1C,IAAA,aAAa,GAA0B,QAAQ,CAAC,MAAM,cAAc,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,EAAE;QACvG,aAAa,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE;QACnD,SAAS,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE;AAC3C,QAAA,QAAQ,EAAE,IAAI;AACf,KAAA,CAAC,oFAAC;uGARQ,oBAAoB,EAAA,IAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAApB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,oBAAoB,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,4BAAA,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EARrB;;;;;;AAMT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EARC,QAAQ,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,EAAA,CAAA;;2FAUC,oBAAoB,EAAA,UAAA,EAAA,CAAA;kBAbhC,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,4BAA4B;AACtC,oBAAA,OAAO,EAAE;wBACP;AACD,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;AAMT,EAAA;AACF,iBAAA;;;;;"}
@@ -0,0 +1,210 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, signal, computed, effect, Component } from '@angular/core';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
+ import * as i1 from '@angular/forms';
5
+ import { FormControl, ReactiveFormsModule } from '@angular/forms';
6
+ import { MatLabel } from '@angular/material/input';
7
+ import { catchError, EMPTY } from 'rxjs';
8
+ import { F as FieldBase, c as FileHandler, V as VIEW_PROVIDER, a as ValidationMessage, b as FieldViewer } from './iss-ctrl-iss-ctrl-DvnkwSMG.mjs';
9
+ import { AttachmentViewer } from './iss-ctrl-attachment.viewer-DVUL39xd.mjs';
10
+ import { FilePickerControl } from 'iss-ctrl/file-picker';
11
+
12
+ /**
13
+ * `<iss-field-file-picker>` — attachment upload.
14
+ *
15
+ * Rendered by the outlet for fields of type `attachment`. In `edit` mode it renders
16
+ * {@link FilePickerControl} plus the validation message; in `view` mode the matching viewer.
17
+ *
18
+ * ### Supported `config` keys
19
+ * | Key | Type | Description |
20
+ * | --- | --- | --- |
21
+ * | `multiple` | `boolean` | Allows attaching more than one file. |
22
+ * | `readonly` | `boolean` | Shows the value but blocks interaction. |
23
+ *
24
+ * ### Other field members used
25
+ * `label()` · `value` · `validation` · `ctrlJsonValue()`
26
+ *
27
+ * Every field also honours `visible`, `mode`, `validation`, `asyncValidation` and
28
+ * `events` — see {@link IssField} for the full model and {@link FieldConfig} for all keys.
29
+ *
30
+ * The field uploads the picked files itself, stores the returned ids as the control value
31
+ * and keeps the resolved attachments in `field.ctrlJsonValue`.
32
+ *
33
+ * Accepted extensions come from the `fileType` **validation** rule, not from `config`; the
34
+ * `allowedFileSize`, `allowedFileTypes`, `minFilesCount`, `maxFilesCount`, `templateId` and
35
+ * `templateUrl` config keys exist on {@link FieldConfig} but are not read here yet.
36
+ *
37
+ * @example
38
+ * ```json
39
+ * { "name": "attachments", "type": "attachment", "label": "Attachments", "config": { "multiple": true }, "validation": { "fileType": ["pdf", "png"] } }
40
+ * ```
41
+ */
42
+ class FilePickerField extends FieldBase {
43
+ picker = new FormControl();
44
+ fileHandlerService = inject(FileHandler);
45
+ uploading = signal(false, ...(ngDevMode ? [{ debugName: "uploading" }] : /* istanbul ignore next */ []));
46
+ viewField = computed(() => this.#generateViewField(this.field.ctrlJsonValue()), ...(ngDevMode ? [{ debugName: "viewField" }] : /* istanbul ignore next */ []));
47
+ attachments = signal([], ...(ngDevMode ? [{ debugName: "attachments" }] : /* istanbul ignore next */ []));
48
+ uploadingError = signal(undefined, ...(ngDevMode ? [{ debugName: "uploadingError" }] : /* istanbul ignore next */ []));
49
+ accept = this.#acceptFactory();
50
+ // the ids the picker already holds files for; without it the effect would re-download
51
+ // the very files captureFile just uploaded, since it writes them back into ctrl
52
+ #hydratedValue = null;
53
+ #valueEffect = effect(() => {
54
+ const value = this.ctrlValueChange();
55
+ if (!value || !this.field.value || value === this.#hydratedValue) {
56
+ return;
57
+ }
58
+ this.#hydratedValue = value;
59
+ this.fileHandlerService.fetchFiles(value)
60
+ .pipe(takeUntilDestroyed(this.destroyRef))
61
+ .subscribe((res) => {
62
+ const filesOnly = res.map((attachment) => attachment.file);
63
+ const formDataValue = this.fileHandlerService.formDataFactory(filesOnly, !!this.field.config.multiple());
64
+ this.attachments.set(res);
65
+ this.picker.setValue(formDataValue);
66
+ this.field.ctrlJsonValue.set(res);
67
+ });
68
+ }, ...(ngDevMode ? [{ debugName: "#valueEffect" }] : /* istanbul ignore next */ []));
69
+ captureFile(formData) {
70
+ if (!formData) {
71
+ return;
72
+ }
73
+ this.uploading.set(true);
74
+ const notUploadedFiles = this.#getNotUploadedFiles(formData);
75
+ if (this.fileHandlerService.formDataHasValue(notUploadedFiles)) {
76
+ this.fileHandlerService.upload(notUploadedFiles).pipe(catchError((err) => {
77
+ this.uploading.set(false);
78
+ this.uploadingError.set(err?.message ?? "Uploading Failed!");
79
+ console.error(err);
80
+ return EMPTY;
81
+ })).subscribe((res) => {
82
+ this.attachments.update((attachments) => {
83
+ if (!this.field.config.multiple()) {
84
+ return res;
85
+ }
86
+ return [...attachments, ...res];
87
+ });
88
+ const stringifiedValue = this.stringifyIssAttachment(this.attachments());
89
+ this.#hydratedValue = stringifiedValue;
90
+ this.ctrl.setValue(stringifiedValue);
91
+ this.field.ctrlJsonValue.set(this.attachments());
92
+ this.uploading.set(false);
93
+ });
94
+ }
95
+ else {
96
+ this.uploading.set(false);
97
+ }
98
+ }
99
+ stringifyIssAttachment(attachments) {
100
+ return attachments.map((attachment) => attachment.id).join(",");
101
+ }
102
+ ngOnDestroy() {
103
+ super.ngOnDestroy();
104
+ this.#valueEffect.destroy();
105
+ }
106
+ // The accepted extensions are the `fileType` rule's own value, the same one its validator is
107
+ // built from — a list, or the comma-separated string an older definition wrote it as.
108
+ #acceptFactory() {
109
+ const extensions = this.field.validation?.["fileType"];
110
+ if (!extensions) {
111
+ return "";
112
+ }
113
+ const list = Array.isArray(extensions) ? extensions : String(extensions).split(",");
114
+ return list
115
+ .map((extension) => extension.trim())
116
+ .filter((extension) => !!extension)
117
+ .map((extension) => extension.startsWith(".") ? extension : `.${extension}`)
118
+ .join(",");
119
+ }
120
+ #generateViewField(value) {
121
+ return {
122
+ config: {
123
+ showDownloadButton: true,
124
+ showDeleteButton: false
125
+ },
126
+ ctrlJsonValue: signal(value ?? [])
127
+ };
128
+ }
129
+ #getNotUploadedFiles(formData) {
130
+ const fd = new FormData();
131
+ if (formData) {
132
+ for (const pair of formData.entries()) {
133
+ const file = pair[1];
134
+ if (!file.id) {
135
+ fd.append(pair[0], pair[1]);
136
+ }
137
+ }
138
+ }
139
+ return fd;
140
+ }
141
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FilePickerField, deps: null, target: i0.ɵɵFactoryTarget.Component });
142
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: FilePickerField, isStandalone: true, selector: "iss-field-file-picker", usesInheritance: true, ngImport: i0, template: `
143
+ @if (field.visible()) {
144
+ @if (field.mode() === "edit") {
145
+ <mat-label>{{ field.label() }}</mat-label>
146
+ <input type="hidden" [formControlName]="field.name">
147
+ <!-- [showDeleteButton]="field.config.showDeleteButton" [showDownloadButton]="field.config.showDownloadButton"-->
148
+ <iss-ctrl-file-picker
149
+ [formControl]="picker"
150
+ [accept]="accept"
151
+ (onChange)="captureFile($event)"
152
+ [multiple]="field.config.multiple()"
153
+ [readonly]="field.config.readonly() ?? false"
154
+ [uploading]="uploading()"
155
+ [uploadedFiles]="attachments()"
156
+ [uploadingError]="uploadingError()"
157
+ />
158
+ <iss-validation-message-viewer [errors]="ctrl.errors" [showMessage]="ctrl.touched"/>
159
+ } @else {
160
+ <iss-field-viewer>
161
+ <label>{{ field.label() }}</label>
162
+ <iss-viewer-attachment [uploading]="uploading()" [field]="viewField()"/>
163
+ </iss-field-viewer>
164
+ }
165
+ }
166
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: FilePickerControl, selector: "iss-ctrl-file-picker", inputs: ["accept", "showDownloadButton", "showDeleteButton", "uploading", "uploadedFiles", "uploadingError"] }, { kind: "component", type: ValidationMessage, selector: "iss-validation-message-viewer", inputs: ["errors", "showMessage"] }, { kind: "component", type: AttachmentViewer, selector: "iss-viewer-attachment", inputs: ["uploading", "uploadingError"], outputs: ["deleteOut"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "component", type: FieldViewer, selector: "iss-field-viewer" }], viewProviders: [VIEW_PROVIDER] });
167
+ }
168
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FilePickerField, decorators: [{
169
+ type: Component,
170
+ args: [{
171
+ selector: "iss-field-file-picker",
172
+ viewProviders: [VIEW_PROVIDER],
173
+ imports: [
174
+ ReactiveFormsModule,
175
+ FilePickerControl,
176
+ ValidationMessage,
177
+ AttachmentViewer,
178
+ MatLabel,
179
+ FieldViewer
180
+ ],
181
+ template: `
182
+ @if (field.visible()) {
183
+ @if (field.mode() === "edit") {
184
+ <mat-label>{{ field.label() }}</mat-label>
185
+ <input type="hidden" [formControlName]="field.name">
186
+ <!-- [showDeleteButton]="field.config.showDeleteButton" [showDownloadButton]="field.config.showDownloadButton"-->
187
+ <iss-ctrl-file-picker
188
+ [formControl]="picker"
189
+ [accept]="accept"
190
+ (onChange)="captureFile($event)"
191
+ [multiple]="field.config.multiple()"
192
+ [readonly]="field.config.readonly() ?? false"
193
+ [uploading]="uploading()"
194
+ [uploadedFiles]="attachments()"
195
+ [uploadingError]="uploadingError()"
196
+ />
197
+ <iss-validation-message-viewer [errors]="ctrl.errors" [showMessage]="ctrl.touched"/>
198
+ } @else {
199
+ <iss-field-viewer>
200
+ <label>{{ field.label() }}</label>
201
+ <iss-viewer-attachment [uploading]="uploading()" [field]="viewField()"/>
202
+ </iss-field-viewer>
203
+ }
204
+ }
205
+ `
206
+ }]
207
+ }] });
208
+
209
+ export { FilePickerField };
210
+ //# sourceMappingURL=iss-ctrl-file-picker.field-CbepZaX6.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iss-ctrl-file-picker.field-CbepZaX6.mjs","sources":["../../../projects/iss/src/components/controls/file-picker/file-picker.field.ts"],"sourcesContent":["import { Component, computed, effect, inject, OnDestroy, Signal, signal, WritableSignal, } from \"@angular/core\";\nimport { takeUntilDestroyed } from \"@angular/core/rxjs-interop\";\nimport { FormControl, ReactiveFormsModule } from \"@angular/forms\";\nimport { MatLabel } from \"@angular/material/input\";\nimport { catchError, EMPTY } from \"rxjs\";\nimport { VIEW_PROVIDER } from \"../../../shared/constants/view-provider.const\";\nimport { FieldViewer } from \"../../shared/field-viewer\";\nimport { ValidationMessage } from \"../../shared/validation-message\";\nimport { FieldBase } from \"../base/field-base\";\nimport { IssAttachment } from \"iss-ctrl/tokens\";\nimport { AttachmentViewer } from \"./attachment.viewer\";\nimport { IssFile } from \"iss-ctrl/file-picker\";\nimport { FileHandler } from \"./file-handler\";\nimport { FilePickerControl } from \"iss-ctrl/file-picker\";\n\n/**\n * `<iss-field-file-picker>` — attachment upload.\n *\n * Rendered by the outlet for fields of type `attachment`. In `edit` mode it renders\n * {@link FilePickerControl} plus the validation message; in `view` mode the matching viewer.\n *\n * ### Supported `config` keys\n * | Key | Type | Description |\n * | --- | --- | --- |\n * | `multiple` | `boolean` | Allows attaching more than one file. |\n * | `readonly` | `boolean` | Shows the value but blocks interaction. |\n *\n * ### Other field members used\n * `label()` · `value` · `validation` · `ctrlJsonValue()`\n *\n * Every field also honours `visible`, `mode`, `validation`, `asyncValidation` and\n * `events` — see {@link IssField} for the full model and {@link FieldConfig} for all keys.\n *\n * The field uploads the picked files itself, stores the returned ids as the control value\n * and keeps the resolved attachments in `field.ctrlJsonValue`.\n *\n * Accepted extensions come from the `fileType` **validation** rule, not from `config`; the\n * `allowedFileSize`, `allowedFileTypes`, `minFilesCount`, `maxFilesCount`, `templateId` and\n * `templateUrl` config keys exist on {@link FieldConfig} but are not read here yet.\n *\n * @example\n * ```json\n * { \"name\": \"attachments\", \"type\": \"attachment\", \"label\": \"Attachments\", \"config\": { \"multiple\": true }, \"validation\": { \"fileType\": [\"pdf\", \"png\"] } }\n * ```\n */\n@Component({\n selector: \"iss-field-file-picker\",\n viewProviders: [VIEW_PROVIDER],\n imports: [\n ReactiveFormsModule,\n FilePickerControl,\n ValidationMessage,\n AttachmentViewer,\n MatLabel,\n FieldViewer\n ],\n template: `\n @if (field.visible()) {\n @if (field.mode() === \"edit\") {\n <mat-label>{{ field.label() }}</mat-label>\n <input type=\"hidden\" [formControlName]=\"field.name\">\n <!-- [showDeleteButton]=\"field.config.showDeleteButton\" [showDownloadButton]=\"field.config.showDownloadButton\"-->\n <iss-ctrl-file-picker\n [formControl]=\"picker\"\n [accept]=\"accept\"\n (onChange)=\"captureFile($event)\"\n [multiple]=\"field.config.multiple()\"\n [readonly]=\"field.config.readonly() ?? false\"\n [uploading]=\"uploading()\"\n [uploadedFiles]=\"attachments()\"\n [uploadingError]=\"uploadingError()\"\n />\n <iss-validation-message-viewer [errors]=\"ctrl.errors\" [showMessage]=\"ctrl.touched\"/>\n } @else {\n <iss-field-viewer>\n <label>{{ field.label() }}</label>\n <iss-viewer-attachment [uploading]=\"uploading()\" [field]=\"viewField()\"/>\n </iss-field-viewer>\n }\n }\n `\n})\nexport class FilePickerField extends FieldBase implements OnDestroy {\n picker = new FormControl();\n fileHandlerService = inject(FileHandler);\n uploading: WritableSignal<boolean> = signal(false);\n viewField: Signal<any> = computed(() => this.#generateViewField(this.field.ctrlJsonValue()));\n attachments: WritableSignal<IssAttachment[]> = signal([]);\n uploadingError = signal<string | undefined>(undefined);\n accept: string = this.#acceptFactory();\n // the ids the picker already holds files for; without it the effect would re-download\n // the very files captureFile just uploaded, since it writes them back into ctrl\n #hydratedValue: string | null = null;\n #valueEffect = effect(() => {\n const value = this.ctrlValueChange();\n if (!value || !this.field.value || value === this.#hydratedValue) {\n return;\n }\n\n this.#hydratedValue = value;\n this.fileHandlerService.fetchFiles(value)\n .pipe(takeUntilDestroyed(this.destroyRef))\n .subscribe((res: any) => {\n const filesOnly = res.map((attachment: any) => attachment.file);\n const formDataValue: FormData | null = this.fileHandlerService.formDataFactory(filesOnly, !!this.field.config.multiple());\n this.attachments.set(res);\n this.picker.setValue(formDataValue);\n this.field.ctrlJsonValue.set(res);\n });\n });\n\n captureFile(formData: FormData | null) {\n if (!formData) {\n return;\n }\n\n this.uploading.set(true);\n const notUploadedFiles: FormData = this.#getNotUploadedFiles(formData);\n if (this.fileHandlerService.formDataHasValue(notUploadedFiles)) {\n this.fileHandlerService.upload(notUploadedFiles).pipe(\n catchError((err) => {\n this.uploading.set(false);\n this.uploadingError.set(err?.message ?? \"Uploading Failed!\");\n console.error(err);\n return EMPTY;\n }),\n ).subscribe((res: any) => {\n this.attachments.update((attachments: IssAttachment[]): IssAttachment[] => {\n if (!this.field.config.multiple()) {\n return res;\n }\n return [...attachments, ...res];\n });\n const stringifiedValue = this.stringifyIssAttachment(this.attachments());\n this.#hydratedValue = stringifiedValue;\n this.ctrl.setValue(stringifiedValue);\n this.field.ctrlJsonValue.set(this.attachments());\n this.uploading.set(false);\n });\n } else {\n this.uploading.set(false);\n }\n }\n\n stringifyIssAttachment(attachments: IssAttachment[]): string {\n return attachments.map((attachment: IssAttachment) => attachment.id).join(\",\");\n }\n\n override ngOnDestroy() {\n super.ngOnDestroy();\n this.#valueEffect.destroy();\n }\n\n // The accepted extensions are the `fileType` rule's own value, the same one its validator is\n // built from — a list, or the comma-separated string an older definition wrote it as.\n #acceptFactory(): string {\n const extensions: any = this.field.validation?.[\"fileType\"];\n if (!extensions) {\n return \"\";\n }\n const list: string[] = Array.isArray(extensions) ? extensions : String(extensions).split(\",\");\n return list\n .map((extension: string) => extension.trim())\n .filter((extension: string) => !!extension)\n .map((extension: string) => extension.startsWith(\".\") ? extension : `.${extension}`)\n .join(\",\");\n }\n\n #generateViewField(value: IssFile[]) {\n return {\n config: {\n showDownloadButton: true,\n showDeleteButton: false\n },\n ctrlJsonValue: signal(value ?? [])\n };\n }\n\n #getNotUploadedFiles(formData: FormData): FormData {\n const fd: FormData = new FormData();\n if (formData) {\n for (const pair of formData.entries()) {\n const file: IssFile = pair[1] as unknown as IssFile;\n if (!file.id) {\n fd.append(pair[0], pair[1]);\n }\n }\n }\n return fd;\n }\n}\n"],"names":[],"mappings":"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"}