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,272 @@
1
+ import * as i0 from '@angular/core';
2
+ import { output, HostListener, Directive, input, computed, signal, effect, CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { ReactiveFormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
5
+ import { ControlBase, Hints } from 'iss-ctrl/base';
6
+
7
+ class Droppable {
8
+ onDrop = output();
9
+ onDragOver(evt) {
10
+ evt.preventDefault();
11
+ evt.stopPropagation();
12
+ }
13
+ onDragLeave(evt) {
14
+ evt.preventDefault();
15
+ evt.stopPropagation();
16
+ }
17
+ onDropped(evt) {
18
+ evt.preventDefault();
19
+ evt.stopPropagation();
20
+ this.onDrop.emit(evt.dataTransfer.files);
21
+ }
22
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: Droppable, deps: [], target: i0.ɵɵFactoryTarget.Directive });
23
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: Droppable, isStandalone: true, selector: "[droppable]", outputs: { onDrop: "onDrop" }, host: { listeners: { "dragover": "onDragOver($event)", "dragleave": "onDragLeave($event)", "drop": "onDropped($event)" } }, ngImport: i0 });
24
+ }
25
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: Droppable, decorators: [{
26
+ type: Directive,
27
+ args: [{ selector: "[droppable]" }]
28
+ }], propDecorators: { onDrop: [{ type: i0.Output, args: ["onDrop"] }], onDragOver: [{
29
+ type: HostListener,
30
+ args: ["dragover", ["$event"]]
31
+ }], onDragLeave: [{
32
+ type: HostListener,
33
+ args: ["dragleave", ["$event"]]
34
+ }], onDropped: [{
35
+ type: HostListener,
36
+ args: ["drop", ["$event"]]
37
+ }] } });
38
+
39
+ /**
40
+ * `<iss-ctrl-file-picker>` — attachment upload with a per-file progress and error state.
41
+ *
42
+ * Uploading is done by the host: the control emits the picked files and renders whatever is
43
+ * fed back through `uploadedFiles`, `uploading` and `uploadingError`.
44
+ *
45
+ * @example
46
+ * ```html
47
+ * <iss-ctrl-file-picker
48
+ * formControlName="attachments"
49
+ * [multiple]="true"
50
+ * accept=".pdf,.png"
51
+ * [uploading]="uploading()"
52
+ * [uploadedFiles]="uploaded()"
53
+ * />
54
+ * ```
55
+ *
56
+ * ### Own inputs
57
+ * | Property | Type | Default | Description |
58
+ * | --- | --- | --- | --- |
59
+ * | `accept` | `string \| undefined` | `undefined` | Accepted extensions or MIME types for the native picker. |
60
+ * | `showDownloadButton` | `boolean` | `true` | Shows the download action on each attachment. |
61
+ * | `showDeleteButton` | `boolean` | `true` | Shows the remove action on each attachment. |
62
+ * | `uploading` | `boolean` | `false` | Renders the in-progress state. |
63
+ * | `uploadedFiles` | `IssAttachment[]` | `[]` | Files already stored on the server. |
64
+ * | `uploadingError` | `string \| undefined` | `undefined` | Error message attached to the failed upload. |
65
+ *
66
+ * ### Inherited from {@link ControlBase}
67
+ * `formControlName` · `readonly` · `className` · `(onChange)` · `multiple` · `hints`
68
+ *
69
+ * Does not project a label — the field label is rendered by the wrapping `iss-field-*`.
70
+ */
71
+ class FilePickerControl extends ControlBase {
72
+ /**
73
+ * Accepted extensions or MIME types, passed straight to the native file input.
74
+ */
75
+ accept = input(...(ngDevMode ? [undefined, { debugName: "accept" }] : /* istanbul ignore next */ []));
76
+ /**
77
+ * Shows the download action on each listed attachment.
78
+ */
79
+ showDownloadButton = input(true, ...(ngDevMode ? [{ debugName: "showDownloadButton" }] : /* istanbul ignore next */ []));
80
+ /**
81
+ * Shows the remove action on each listed attachment.
82
+ */
83
+ showDeleteButton = input(true, ...(ngDevMode ? [{ debugName: "showDeleteButton" }] : /* istanbul ignore next */ []));
84
+ /**
85
+ * Renders the upload-in-progress state; set by the host that performs the upload.
86
+ */
87
+ uploading = input(false, ...(ngDevMode ? [{ debugName: "uploading" }] : /* istanbul ignore next */ []));
88
+ /**
89
+ * Attachments already stored on the server, merged into the rendered list.
90
+ */
91
+ uploadedFiles = input([], ...(ngDevMode ? [{ debugName: "uploadedFiles" }] : /* istanbul ignore next */ []));
92
+ /**
93
+ * Error message shown on the attachment whose upload failed.
94
+ */
95
+ uploadingError = input(undefined, ...(ngDevMode ? [{ debugName: "uploadingError" }] : /* istanbul ignore next */ []));
96
+ filesValue = computed(() => this.#returnAttachmentViewObject(), ...(ngDevMode ? [{ debugName: "filesValue" }] : /* istanbul ignore next */ []));
97
+ attachments = signal([], ...(ngDevMode ? [{ debugName: "attachments" }] : /* istanbul ignore next */ []));
98
+ #uploadedFilesEffectRef = effect(() => {
99
+ this.#markUploadedFiles();
100
+ }, ...(ngDevMode ? [{ debugName: "#uploadedFilesEffectRef" }] : /* istanbul ignore next */ []));
101
+ /*todo needs review and refactor*/
102
+ ngOnDestroy() {
103
+ this.#uploadedFilesEffectRef.destroy();
104
+ }
105
+ writeValue(val) {
106
+ if (typeof val === "string") {
107
+ return;
108
+ }
109
+ this.#reset();
110
+ if (val) {
111
+ this.attachments.set([...this.attachments(), ...this.#convertFormDataToFiles(val)]);
112
+ }
113
+ }
114
+ onDelete(files) {
115
+ this.attachments.set(files);
116
+ this.emitValue(this.#formDataFactory(this.attachments()));
117
+ }
118
+ captureFile($event) {
119
+ if (this.readonly() || this.disabled()) {
120
+ return;
121
+ }
122
+ if (!$event) {
123
+ return;
124
+ }
125
+ if (!$event.length) {
126
+ return;
127
+ }
128
+ this.markAsTouched();
129
+ const files = Array.from($event);
130
+ const issFiles = files.map((file) => {
131
+ return {
132
+ name: file.name,
133
+ size: file.size,
134
+ type: file.type,
135
+ selected: Date.now(),
136
+ file: file,
137
+ };
138
+ });
139
+ this.#updateAttachments(issFiles);
140
+ // The field component uploads this output. Emit only the files selected in
141
+ // this interaction: `attachments` also contains files selected earlier, so
142
+ // serialising it would upload those files again whenever more are added.
143
+ this.emitValue(this.#formDataFactory(issFiles));
144
+ }
145
+ openFilePicker(input) {
146
+ if (this.readonly() || this.disabled()) {
147
+ return;
148
+ }
149
+ input.click();
150
+ this.markAsTouched();
151
+ }
152
+ #updateAttachments(selectedFiles) {
153
+ if (!this.multiple()) {
154
+ this.attachments.set([selectedFiles[0]]);
155
+ return;
156
+ }
157
+ this.attachments.update((files) => {
158
+ files = [...files, ...selectedFiles];
159
+ return files;
160
+ });
161
+ }
162
+ #formDataFactory(files) {
163
+ if (files.length === 0) {
164
+ return null;
165
+ }
166
+ const fd = new FormData();
167
+ let formDataKey = "file";
168
+ if (this.multiple()) {
169
+ formDataKey = "files";
170
+ }
171
+ for (let i = 0; i < files.length; i++) {
172
+ fd.append(formDataKey, files[i].file);
173
+ }
174
+ return fd;
175
+ }
176
+ #reset() {
177
+ this.attachments.set([]);
178
+ }
179
+ #convertFormDataToFiles(val) {
180
+ if (!val || !(val instanceof FormData)) {
181
+ return [];
182
+ }
183
+ const files = [];
184
+ for (const pair of val.entries()) {
185
+ if (pair[1] instanceof File) {
186
+ files.push(pair[1]);
187
+ }
188
+ }
189
+ return files;
190
+ }
191
+ #markUploadedFiles() {
192
+ this.attachments.update((attachments) => {
193
+ return attachments.map((attachment) => {
194
+ // const uploadedFile = this.uploadedFiles().find((f) => f.selected === attachment.selected && f.name === attachment.name);
195
+ if (this.uploadingError()) {
196
+ attachment.errorMsg = this.uploadingError();
197
+ }
198
+ // if (uploadedFile) {
199
+ // attachment.id = uploadedFile.id;
200
+ // }
201
+ return attachment;
202
+ });
203
+ });
204
+ }
205
+ #returnAttachmentViewObject() {
206
+ return {
207
+ config: {
208
+ showDownloadButton: this.showDownloadButton(),
209
+ showDeleteButton: this.showDeleteButton()
210
+ },
211
+ ctrlJsonValue: signal(this.attachments())
212
+ };
213
+ }
214
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FilePickerControl, deps: null, target: i0.ɵɵFactoryTarget.Component });
215
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.2.9", type: FilePickerControl, isStandalone: true, selector: "iss-ctrl-file-picker", inputs: { accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, showDownloadButton: { classPropertyName: "showDownloadButton", publicName: "showDownloadButton", isSignal: true, isRequired: false, transformFunction: null }, showDeleteButton: { classPropertyName: "showDeleteButton", publicName: "showDeleteButton", isSignal: true, isRequired: false, transformFunction: null }, uploading: { classPropertyName: "uploading", publicName: "uploading", isSignal: true, isRequired: false, transformFunction: null }, uploadedFiles: { classPropertyName: "uploadedFiles", publicName: "uploadedFiles", isSignal: true, isRequired: false, transformFunction: null }, uploadingError: { classPropertyName: "uploadingError", publicName: "uploadingError", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
216
+ { provide: NG_VALUE_ACCESSOR, useExisting: FilePickerControl, multi: true }
217
+ ], usesInheritance: true, ngImport: i0, template: `
218
+ <ds-file-picker (click)="openFilePicker(inputFile)" (onDrop)="captureFile($event)" droppable>
219
+ <input
220
+ #inputFile
221
+ (change)="captureFile($any($event.target).files)"
222
+ (click)="$event.stopPropagation()"
223
+ [accept]="accept()"
224
+ [formControl]="ctrl"
225
+ [multiple]="multiple()"
226
+ [disabled]="readonly()"
227
+ [style.display]="'none'"
228
+ type="file"
229
+ />
230
+ </ds-file-picker>
231
+
232
+ <iss-ctrl-hints [hints]="hints()" [touched]="touched()"/>
233
+ <!--<iss-viewer-attachment (deleteOut)="onDelete($event)" [field]="filesValue()" [uploading]="uploading()"/>-->
234
+ `, isInline: true, styles: [".file-uploader{--uploader-height: 150px;--uploader-width: 100%;--uploader-bg: var(--off-white);--uploader-border: 1px dashed var(--dark-gray);--uploader-radius: var(--box-radius);--uploader-padding: 1rem;height:var(--uploader-height);background-color:var(--uploader-bg);border:var(--uploader-border);border-radius:var(--uploader-radius);padding:var(--uploader-padding);text-align:center;cursor:pointer}.file-uploader --input{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:.75rem}\n"], 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: Droppable, selector: "[droppable]", outputs: ["onDrop"] }, { kind: "component", type: Hints, selector: "iss-ctrl-hints", inputs: ["hints", "touched"] }] });
235
+ }
236
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: FilePickerControl, decorators: [{
237
+ type: Component,
238
+ args: [{ selector: "iss-ctrl-file-picker", schemas: [CUSTOM_ELEMENTS_SCHEMA], imports: [
239
+ ReactiveFormsModule,
240
+ Droppable,
241
+ Hints,
242
+ ], providers: [
243
+ { provide: NG_VALUE_ACCESSOR, useExisting: FilePickerControl, multi: true }
244
+ ], template: `
245
+ <ds-file-picker (click)="openFilePicker(inputFile)" (onDrop)="captureFile($event)" droppable>
246
+ <input
247
+ #inputFile
248
+ (change)="captureFile($any($event.target).files)"
249
+ (click)="$event.stopPropagation()"
250
+ [accept]="accept()"
251
+ [formControl]="ctrl"
252
+ [multiple]="multiple()"
253
+ [disabled]="readonly()"
254
+ [style.display]="'none'"
255
+ type="file"
256
+ />
257
+ </ds-file-picker>
258
+
259
+ <iss-ctrl-hints [hints]="hints()" [touched]="touched()"/>
260
+ <!--<iss-viewer-attachment (deleteOut)="onDelete($event)" [field]="filesValue()" [uploading]="uploading()"/>-->
261
+ `, styles: [".file-uploader{--uploader-height: 150px;--uploader-width: 100%;--uploader-bg: var(--off-white);--uploader-border: 1px dashed var(--dark-gray);--uploader-radius: var(--box-radius);--uploader-padding: 1rem;height:var(--uploader-height);background-color:var(--uploader-bg);border:var(--uploader-border);border-radius:var(--uploader-radius);padding:var(--uploader-padding);text-align:center;cursor:pointer}.file-uploader --input{display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;gap:.75rem}\n"] }]
262
+ }], propDecorators: { accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], showDownloadButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDownloadButton", required: false }] }], showDeleteButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDeleteButton", required: false }] }], uploading: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploading", required: false }] }], uploadedFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadedFiles", required: false }] }], uploadingError: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadingError", required: false }] }] } });
263
+
264
+ // The file-picker control. Its field and viewer stay in the primary entry point and reach it
265
+ // from there, so the control ships only to an app that renders it or imports it directly.
266
+
267
+ /**
268
+ * Generated bundle index. Do not edit.
269
+ */
270
+
271
+ export { Droppable, FilePickerControl };
272
+ //# sourceMappingURL=iss-ctrl-file-picker.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iss-ctrl-file-picker.mjs","sources":["../../../projects/iss/file-picker/src/droppable.ts","../../../projects/iss/file-picker/src/file-picker.control.ts","../../../projects/iss/file-picker/src/public-api.ts","../../../projects/iss/file-picker/src/iss-ctrl-file-picker.ts"],"sourcesContent":["import { Directive, HostListener, output, OutputEmitterRef } from \"@angular/core\";\r\n\r\n@Directive({selector: \"[droppable]\"})\r\nexport class Droppable {\r\n onDrop: OutputEmitterRef<FileList> = output();\r\n\r\n @HostListener(\"dragover\", [\"$event\"])\r\n onDragOver(evt: any) {\r\n evt.preventDefault();\r\n evt.stopPropagation();\r\n }\r\n\r\n @HostListener(\"dragleave\", [\"$event\"])\r\n onDragLeave(evt: any) {\r\n evt.preventDefault();\r\n evt.stopPropagation();\r\n }\r\n\r\n @HostListener(\"drop\", [\"$event\"])\r\n onDropped(evt: any) {\r\n evt.preventDefault();\r\n evt.stopPropagation();\r\n this.onDrop.emit(evt.dataTransfer.files);\r\n }\r\n}\r\n","import { Component, computed, CUSTOM_ELEMENTS_SCHEMA, effect, input, InputSignal, OnDestroy, Signal, signal, WritableSignal } from \"@angular/core\";\nimport { NG_VALUE_ACCESSOR, ReactiveFormsModule } from \"@angular/forms\";\nimport { Hints } from \"iss-ctrl/base\";\nimport { ControlBase } from \"iss-ctrl/base\";\nimport { IssAttachment } from \"iss-ctrl/tokens\";\nimport { Droppable } from \"./droppable\";\nimport { IssFile } from \"./file\";\n\n/**\n * `<iss-ctrl-file-picker>` — attachment upload with a per-file progress and error state.\n *\n * Uploading is done by the host: the control emits the picked files and renders whatever is\n * fed back through `uploadedFiles`, `uploading` and `uploadingError`.\n *\n * @example\n * ```html\n * <iss-ctrl-file-picker\n * formControlName=\"attachments\"\n * [multiple]=\"true\"\n * accept=\".pdf,.png\"\n * [uploading]=\"uploading()\"\n * [uploadedFiles]=\"uploaded()\"\n * />\n * ```\n *\n * ### Own inputs\n * | Property | Type | Default | Description |\n * | --- | --- | --- | --- |\n * | `accept` | `string \\| undefined` | `undefined` | Accepted extensions or MIME types for the native picker. |\n * | `showDownloadButton` | `boolean` | `true` | Shows the download action on each attachment. |\n * | `showDeleteButton` | `boolean` | `true` | Shows the remove action on each attachment. |\n * | `uploading` | `boolean` | `false` | Renders the in-progress state. |\n * | `uploadedFiles` | `IssAttachment[]` | `[]` | Files already stored on the server. |\n * | `uploadingError` | `string \\| undefined` | `undefined` | Error message attached to the failed upload. |\n *\n * ### Inherited from {@link ControlBase}\n * `formControlName` · `readonly` · `className` · `(onChange)` · `multiple` · `hints`\n *\n * Does not project a label — the field label is rendered by the wrapping `iss-field-*`.\n */\n@Component({\n selector: \"iss-ctrl-file-picker\",\n schemas: [CUSTOM_ELEMENTS_SCHEMA],\n imports: [\n ReactiveFormsModule,\n Droppable,\n Hints,\n ],\n providers: [\n { provide: NG_VALUE_ACCESSOR, useExisting: FilePickerControl, multi: true }\n ],\n template: `\n <ds-file-picker (click)=\"openFilePicker(inputFile)\" (onDrop)=\"captureFile($event)\" droppable>\n <input\n #inputFile\n (change)=\"captureFile($any($event.target).files)\"\n (click)=\"$event.stopPropagation()\"\n [accept]=\"accept()\"\n [formControl]=\"ctrl\"\n [multiple]=\"multiple()\"\n [disabled]=\"readonly()\"\n [style.display]=\"'none'\"\n type=\"file\"\n />\n </ds-file-picker>\n\n <iss-ctrl-hints [hints]=\"hints()\" [touched]=\"touched()\"/>\n <!--<iss-viewer-attachment (deleteOut)=\"onDelete($event)\" [field]=\"filesValue()\" [uploading]=\"uploading()\"/>-->\n `,\n styles: `\n .file-uploader {\n --uploader-height: 150px;\n --uploader-width: 100%;\n --uploader-bg: var(--off-white);\n --uploader-border: 1px dashed var(--dark-gray);\n --uploader-radius: var(--box-radius);\n --uploader-padding: 1rem;\n\n height: var(--uploader-height);\n background-color: var(--uploader-bg);\n border: var(--uploader-border);\n border-radius: var(--uploader-radius);\n padding: var(--uploader-padding);\n text-align: center;\n cursor: pointer;\n\n & --input {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n gap: 0.75rem;\n }\n }`\n})\nexport class FilePickerControl extends ControlBase implements OnDestroy {\n /**\n * Accepted extensions or MIME types, passed straight to the native file input.\n */\n accept: InputSignal<string | undefined> = input();\n /**\n * Shows the download action on each listed attachment.\n */\n showDownloadButton: InputSignal<boolean> = input(true);\n /**\n * Shows the remove action on each listed attachment.\n */\n showDeleteButton: InputSignal<boolean> = input(true);\n /**\n * Renders the upload-in-progress state; set by the host that performs the upload.\n */\n uploading: InputSignal<boolean> = input(false);\n /**\n * Attachments already stored on the server, merged into the rendered list.\n */\n uploadedFiles: InputSignal<IssAttachment[]> = input<IssAttachment[]>([]);\n /**\n * Error message shown on the attachment whose upload failed.\n */\n uploadingError: InputSignal<string | undefined> = input<string | undefined>(undefined);\n readonly filesValue: Signal<any> = computed(() => this.#returnAttachmentViewObject());\n protected attachments: WritableSignal<IssFile[]> = signal([]);\n #uploadedFilesEffectRef = effect(() => {\n this.#markUploadedFiles();\n });\n\n /*todo needs review and refactor*/\n\n ngOnDestroy(): void {\n this.#uploadedFilesEffectRef.destroy();\n }\n\n override writeValue(val: FormData | string | null): void {\n if (typeof val === \"string\") {\n return;\n }\n this.#reset();\n if (val) {\n this.attachments.set([...this.attachments(), ...this.#convertFormDataToFiles(val)]);\n }\n }\n\n protected onDelete(files: IssFile[]): void {\n this.attachments.set(files);\n this.emitValue(this.#formDataFactory(this.attachments()));\n }\n\n protected captureFile($event: FileList) {\n if (this.readonly() || this.disabled()) {\n return;\n }\n if (!$event) {\n return;\n }\n if (!$event.length) {\n return;\n }\n this.markAsTouched();\n const files: File[] = Array.from($event);\n const issFiles: IssFile[] = files.map((file: File): IssFile => {\n return {\n name: file.name,\n size: file.size,\n type: file.type,\n selected: Date.now(),\n file: file,\n };\n });\n this.#updateAttachments(issFiles);\n // The field component uploads this output. Emit only the files selected in\n // this interaction: `attachments` also contains files selected earlier, so\n // serialising it would upload those files again whenever more are added.\n this.emitValue(this.#formDataFactory(issFiles));\n }\n\n protected openFilePicker(input: HTMLInputElement): void {\n if (this.readonly() || this.disabled()) {\n return;\n }\n input.click();\n this.markAsTouched();\n }\n\n #updateAttachments(selectedFiles: IssFile[]) {\n if (!this.multiple()) {\n this.attachments.set([selectedFiles[0]]);\n return;\n }\n this.attachments.update((files: IssFile[]) => {\n files = [...files, ...selectedFiles];\n return files;\n });\n }\n\n #formDataFactory(files: IssFile[]): FormData | null {\n if (files.length === 0) {\n return null;\n }\n const fd: FormData = new FormData();\n let formDataKey = \"file\";\n if (this.multiple()) {\n formDataKey = \"files\";\n }\n for (let i = 0; i < files.length; i++) {\n fd.append(formDataKey, (files[i].file as File));\n }\n return fd;\n }\n\n #reset() {\n this.attachments.set([]);\n }\n\n #convertFormDataToFiles(val: FormData): IssFile[] {\n if (!val || !(val instanceof FormData)) {\n return [];\n }\n const files: File[] = [];\n for (const pair of val.entries()) {\n if (pair[1] instanceof File) {\n files.push(pair[1]);\n }\n }\n return files;\n }\n\n #markUploadedFiles() {\n this.attachments.update((attachments: IssFile[]) => {\n return attachments.map((attachment: IssFile) => {\n // const uploadedFile = this.uploadedFiles().find((f) => f.selected === attachment.selected && f.name === attachment.name);\n if (this.uploadingError()) {\n attachment.errorMsg = this.uploadingError();\n }\n // if (uploadedFile) {\n // attachment.id = uploadedFile.id;\n // }\n return attachment;\n });\n });\n }\n\n #returnAttachmentViewObject() {\n return {\n config: {\n showDownloadButton: this.showDownloadButton(),\n showDeleteButton: this.showDeleteButton()\n },\n ctrlJsonValue: signal(this.attachments())\n };\n }\n}\n","// The file-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 \"./droppable\";\nexport * from \"./file-picker.control\";\nexport * from \"./file\";\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Component } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { ReactiveFormsModule } from '@angular/forms';
5
+ import { F as FieldBase, V as VIEW_PROVIDER, a as ValidationMessage, b as FieldViewer } from './iss-ctrl-iss-ctrl-DvnkwSMG.mjs';
6
+ import { InputControl } from 'iss-ctrl/input';
7
+ import { InputViewer } from './iss-ctrl-input.viewer-BOZnW0_e.mjs';
8
+
9
+ /**
10
+ * `<iss-field-input>` — single line text, number, email or password entry.
11
+ *
12
+ * Rendered by the outlet for fields of type `text_input`. In `edit` mode it renders
13
+ * {@link InputControl} plus the validation message; in `view` mode the matching viewer.
14
+ *
15
+ * ### Supported `config` keys
16
+ * | Key | Type | Description |
17
+ * | --- | --- | --- |
18
+ * | `type` | `string` | Native input type — `text`, `number`, `email`, `password`, … |
19
+ * | `placeholder` | `string` | Placeholder shown while empty. |
20
+ * | `min` | `number` | Minimum numeric value. |
21
+ * | `max` | `number` | Maximum numeric value. |
22
+ * | `minLength` | `number` | Minimum number of characters. |
23
+ * | `maxLength` | `number` | Maximum number of characters. |
24
+ * | `readonly` | `boolean` | Shows the value but blocks interaction. |
25
+ *
26
+ * ### Other field members used
27
+ * `label()`
28
+ *
29
+ * Every field also honours `visible`, `mode`, `validation`, `asyncValidation` and
30
+ * `events` — see {@link IssField} for the full model and {@link FieldConfig} for all keys.
31
+ *
32
+ * @example
33
+ * ```json
34
+ * { "name": "email", "type": "text_input", "label": "Email", "config": { "type": "email", "maxLength": 120 } }
35
+ * ```
36
+ */
37
+ class InputField extends FieldBase {
38
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: InputField, deps: null, target: i0.ɵɵFactoryTarget.Component });
39
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: InputField, isStandalone: true, selector: "iss-field-input", usesInheritance: true, ngImport: i0, template: `
40
+ @if (field.visible()) {
41
+ @if (field.mode() === "edit") {
42
+ <iss-ctrl-input
43
+ [formControlName]="field.name"
44
+ [type]="field.config.type() ?? ''"
45
+ [placeholder]="field.config.placeholder() ?? ''"
46
+ [min]="field.config.min() ?? null"
47
+ [max]="field.config.max() ?? null"
48
+ [readonly]="field.config.readonly() ?? false"
49
+ [minLength]="field.config.minLength() ?? null"
50
+ [maxLength]="field.config.maxLength() ?? null"
51
+ >
52
+ <label>{{ field.label() }}</label>
53
+ </iss-ctrl-input>
54
+ <iss-validation-message-viewer [errors]="ctrl.errors" [showMessage]="!ctrl.untouched"/>
55
+ } @else {
56
+ <iss-field-viewer>
57
+ <label>{{ field.label() }}</label>
58
+ <iss-viewer-input [field]="field"/>
59
+ </iss-field-viewer>
60
+ }
61
+ }
62
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: InputControl, selector: "iss-ctrl-input", inputs: ["type", "prefixIcon", "prefixText", "suffixIcon", "suffixText"], outputs: ["onPrefixClick", "onSuffixClick"] }, { kind: "component", type: ValidationMessage, selector: "iss-validation-message-viewer", inputs: ["errors", "showMessage"] }, { kind: "component", type: InputViewer, selector: "iss-viewer-input" }, { kind: "component", type: FieldViewer, selector: "iss-field-viewer" }], viewProviders: [VIEW_PROVIDER] });
63
+ }
64
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: InputField, decorators: [{
65
+ type: Component,
66
+ args: [{
67
+ selector: "iss-field-input",
68
+ viewProviders: [VIEW_PROVIDER],
69
+ imports: [
70
+ ReactiveFormsModule,
71
+ InputControl,
72
+ ValidationMessage,
73
+ InputViewer,
74
+ FieldViewer
75
+ ],
76
+ template: `
77
+ @if (field.visible()) {
78
+ @if (field.mode() === "edit") {
79
+ <iss-ctrl-input
80
+ [formControlName]="field.name"
81
+ [type]="field.config.type() ?? ''"
82
+ [placeholder]="field.config.placeholder() ?? ''"
83
+ [min]="field.config.min() ?? null"
84
+ [max]="field.config.max() ?? null"
85
+ [readonly]="field.config.readonly() ?? false"
86
+ [minLength]="field.config.minLength() ?? null"
87
+ [maxLength]="field.config.maxLength() ?? null"
88
+ >
89
+ <label>{{ field.label() }}</label>
90
+ </iss-ctrl-input>
91
+ <iss-validation-message-viewer [errors]="ctrl.errors" [showMessage]="!ctrl.untouched"/>
92
+ } @else {
93
+ <iss-field-viewer>
94
+ <label>{{ field.label() }}</label>
95
+ <iss-viewer-input [field]="field"/>
96
+ </iss-field-viewer>
97
+ }
98
+ }
99
+ `
100
+ }]
101
+ }] });
102
+
103
+ export { InputField };
104
+ //# sourceMappingURL=iss-ctrl-input.field-Ctlf3OCN.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iss-ctrl-input.field-Ctlf3OCN.mjs","sources":["../../../projects/iss/src/components/controls/input/input.field.ts"],"sourcesContent":["import { Component } from \"@angular/core\";\nimport { ReactiveFormsModule } from \"@angular/forms\";\nimport { VIEW_PROVIDER } from \"../../../shared/constants/view-provider.const\";\nimport { ValidationMessage } from \"../../shared/validation-message\";\nimport { FieldBase } from \"../base/field-base\";\nimport { InputControl } from \"iss-ctrl/input\";\nimport { InputViewer } from \"./input.viewer\";\nimport { FieldViewer } from \"../../shared/field-viewer\";\n\n/**\n * `<iss-field-input>` — single line text, number, email or password entry.\n *\n * Rendered by the outlet for fields of type `text_input`. In `edit` mode it renders\n * {@link InputControl} plus the validation message; in `view` mode the matching viewer.\n *\n * ### Supported `config` keys\n * | Key | Type | Description |\n * | --- | --- | --- |\n * | `type` | `string` | Native input type — `text`, `number`, `email`, `password`, … |\n * | `placeholder` | `string` | Placeholder shown while empty. |\n * | `min` | `number` | Minimum numeric value. |\n * | `max` | `number` | Maximum numeric value. |\n * | `minLength` | `number` | Minimum number of characters. |\n * | `maxLength` | `number` | Maximum number of characters. |\n * | `readonly` | `boolean` | Shows the value but blocks interaction. |\n *\n * ### Other field members used\n * `label()`\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 * @example\n * ```json\n * { \"name\": \"email\", \"type\": \"text_input\", \"label\": \"Email\", \"config\": { \"type\": \"email\", \"maxLength\": 120 } }\n * ```\n */\n@Component({\n selector: \"iss-field-input\",\n viewProviders: [VIEW_PROVIDER],\n imports: [\n ReactiveFormsModule,\n InputControl,\n ValidationMessage,\n InputViewer,\n FieldViewer\n ],\n template: `\n @if (field.visible()) {\n @if (field.mode() === \"edit\") {\n <iss-ctrl-input\n [formControlName]=\"field.name\"\n [type]=\"field.config.type() ?? ''\"\n [placeholder]=\"field.config.placeholder() ?? ''\"\n [min]=\"field.config.min() ?? null\"\n [max]=\"field.config.max() ?? null\"\n [readonly]=\"field.config.readonly() ?? false\"\n [minLength]=\"field.config.minLength() ?? null\"\n [maxLength]=\"field.config.maxLength() ?? null\"\n >\n <label>{{ field.label() }}</label>\n </iss-ctrl-input>\n <iss-validation-message-viewer [errors]=\"ctrl.errors\" [showMessage]=\"!ctrl.untouched\"/>\n } @else {\n <iss-field-viewer>\n <label>{{ field.label() }}</label>\n <iss-viewer-input [field]=\"field\"/>\n </iss-field-viewer>\n }\n }\n `\n})\nexport class InputField extends FieldBase {}\n"],"names":[],"mappings":";;;;;;;;AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;AAoCG,MAAO,UAAW,SAAQ,SAAS,CAAA;uGAA5B,UAAU,EAAA,IAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAV,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAU,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAzBX;;;;;;;;;;;;;;;;;;;;;;;AAuBT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EA7BC,mBAAmB,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,iBAAA,EAAA,UAAA,EAAA,SAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACnB,YAAY,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,EAAA,YAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACZ,iBAAiB,EAAA,QAAA,EAAA,+BAAA,EAAA,MAAA,EAAA,CAAA,QAAA,EAAA,aAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACjB,WAAW,EAAA,QAAA,EAAA,kBAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EACX,WAAW,EAAA,QAAA,EAAA,kBAAA,EAAA,CAAA,EAAA,aAAA,EANE,CAAC,aAAa,CAAC,EAAA,CAAA;;2FAiCnB,UAAU,EAAA,UAAA,EAAA,CAAA;kBAnCtB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,iBAAiB;oBAC3B,aAAa,EAAE,CAAC,aAAa,CAAC;AAC9B,oBAAA,OAAO,EAAE;wBACP,mBAAmB;wBACnB,YAAY;wBACZ,iBAAiB;wBACjB,WAAW;wBACX;AACD,qBAAA;AACD,oBAAA,QAAQ,EAAE;;;;;;;;;;;;;;;;;;;;;;;AAuBT,EAAA;AACF,iBAAA;;;;;"}
@@ -0,0 +1,204 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, output, effect, ChangeDetectionStrategy, CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core';
3
+ import * as i1 from '@angular/forms';
4
+ import { ReactiveFormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
5
+ import * as i2 from '@angular/material/form-field';
6
+ import { MatFormFieldModule } from '@angular/material/form-field';
7
+ import { MatInput, MatInputModule } from '@angular/material/input';
8
+ import { ControlBase, Hints } from 'iss-ctrl/base';
9
+
10
+ /**
11
+ * `<iss-ctrl-input>` — single line text input, the base for every scalar text field.
12
+ *
13
+ * `type` is forwarded to the native input, so `number`, `email` and `password` variants all
14
+ * come from this one control.
15
+ *
16
+ * @example
17
+ * ```html
18
+ * <iss-ctrl-input formControlName="amount" type="number" [min]="0" suffixText="SAR">
19
+ * <label>Amount</label>
20
+ * </iss-ctrl-input>
21
+ * ```
22
+ *
23
+ * ### Own inputs
24
+ * | Property | Type | Default | Description |
25
+ * | --- | --- | --- | --- |
26
+ * | `type` | `string` | `"text"` | Native input type: `text`, `number`, `email`, `password`, … |
27
+ * | `prefixIcon` | `string` | `""` | Icon rendered before the value. |
28
+ * | `prefixText` | `string` | `""` | Text rendered before the value. |
29
+ * | `suffixIcon` | `string` | `""` | Icon rendered after the value. |
30
+ * | `suffixText` | `string` | `""` | Text rendered after the value. |
31
+ *
32
+ * ### Inherited from {@link ControlBase}
33
+ * `formControlName` · `readonly` · `className` · `(onChange)` · `placeholder` · `min` · `max` · `minLength` · `maxLength` · `hints`
34
+ *
35
+ * ### Outputs
36
+ * - `(onPrefixClick)` — `string`, the prefix affix was clicked.
37
+ * - `(onSuffixClick)` — `string`, the suffix affix was clicked.
38
+ *
39
+ * Projects `<label>` into the floating label; omit it to render the control without one.
40
+ *
41
+ * Also projects `[issPrefix]` and `[issSuffix]` for fully custom affixes.
42
+ */
43
+ class InputControl extends ControlBase {
44
+ /**
45
+ * Native input type — `text`, `number`, `email`, `password`, and so on.
46
+ */
47
+ type = input("text", ...(ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []));
48
+ /**
49
+ * Icon name rendered before the value.
50
+ */
51
+ prefixIcon = input("", ...(ngDevMode ? [{ debugName: "prefixIcon" }] : /* istanbul ignore next */ []));
52
+ /**
53
+ * Static text rendered before the value.
54
+ */
55
+ prefixText = input("", ...(ngDevMode ? [{ debugName: "prefixText" }] : /* istanbul ignore next */ []));
56
+ /**
57
+ * Icon name rendered after the value.
58
+ */
59
+ suffixIcon = input("", ...(ngDevMode ? [{ debugName: "suffixIcon" }] : /* istanbul ignore next */ []));
60
+ /**
61
+ * Static text rendered after the value, a unit or currency for example.
62
+ */
63
+ suffixText = input("", ...(ngDevMode ? [{ debugName: "suffixText" }] : /* istanbul ignore next */ []));
64
+ /**
65
+ * Emits when the prefix affix is clicked.
66
+ */
67
+ onPrefixClick = output();
68
+ /**
69
+ * Emits when the suffix affix is clicked.
70
+ */
71
+ onSuffixClick = output();
72
+ #disabledEffect = effect(() => {
73
+ if (this.disabled()) {
74
+ this.ctrl.disable();
75
+ }
76
+ else {
77
+ this.ctrl.enable();
78
+ }
79
+ }, ...(ngDevMode ? [{ debugName: "#disabledEffect" }] : /* istanbul ignore next */ []));
80
+ emitSuffixClick() {
81
+ this.onSuffixClick.emit(this.ctrl.getRawValue());
82
+ }
83
+ emitPrefixClick() {
84
+ this.onPrefixClick.emit(this.ctrl.getRawValue());
85
+ }
86
+ ngOnDestroy() {
87
+ this.#disabledEffect.destroy();
88
+ }
89
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: InputControl, deps: null, target: i0.ɵɵFactoryTarget.Component });
90
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: InputControl, isStandalone: true, selector: "iss-ctrl-input", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, prefixIcon: { classPropertyName: "prefixIcon", publicName: "prefixIcon", isSignal: true, isRequired: false, transformFunction: null }, prefixText: { classPropertyName: "prefixText", publicName: "prefixText", isSignal: true, isRequired: false, transformFunction: null }, suffixIcon: { classPropertyName: "suffixIcon", publicName: "suffixIcon", isSignal: true, isRequired: false, transformFunction: null }, suffixText: { classPropertyName: "suffixText", publicName: "suffixText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onPrefixClick: "onPrefixClick", onSuffixClick: "onSuffixClick" }, providers: [
91
+ { provide: NG_VALUE_ACCESSOR, useExisting: InputControl, multi: true },
92
+ { provide: NG_VALIDATORS, useExisting: InputControl, multi: true }
93
+ ], usesInheritance: true, ngImport: i0, template: `
94
+ <mat-form-field floatLabel="auto" class="">
95
+ <!-- Always rendered: upgrade.scss shows the floating label only while the projected <label> carries text, so an omitted or empty one collapses on its own. -->
96
+ <mat-label class="fs-16 fc-dark-gray">
97
+ <ng-content select="label"></ng-content>
98
+ </mat-label>
99
+ <ng-content select="[issPrefix]"></ng-content>
100
+ <div (click)="emitPrefixClick()" class="cursor-pointer">
101
+ @if (prefixText()) {
102
+ <span matTextPrefix>{{ prefixText() }}</span>
103
+ }
104
+ @if (prefixIcon()) {
105
+ <ds-icon matPrefix icon="{{prefixIcon()}}"></ds-icon>
106
+ }
107
+ </div>
108
+ <input
109
+ matInput
110
+ [errorStateMatcher]="errorStateMatcher"
111
+ (blur)="markAsTouched()"
112
+ (input)="emitValue()"
113
+ [formControl]="ctrl"
114
+ [attr.maxlength]="maxLength()"
115
+ [attr.minlength]="minLength()"
116
+ [attr.max]="max()"
117
+ [attr.min]="min()"
118
+ [placeholder]="placeholder()"
119
+ [readonly]="readonly()"
120
+ [type]="type()"
121
+ />
122
+ <ng-content select="[issSuffix]"></ng-content>
123
+ <div (click)="emitSuffixClick()" class="cursor-pointer">
124
+ @if (suffixText()) {
125
+ <span matTextSuffix>{{ suffixText() }}</span>
126
+ }
127
+ @if (suffixIcon()) {
128
+ <ds-icon matSuffix icon="{{suffixIcon()}}"></ds-icon>
129
+ }
130
+ </div>
131
+ <iss-ctrl-hints [hints]="hints()" [touched]="touched()"/>
132
+ </mat-form-field>
133
+ `, 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: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "directive", type: i2.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: Hints, selector: "iss-ctrl-hints", inputs: ["hints", "touched"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatInputModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
134
+ }
135
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: InputControl, decorators: [{
136
+ type: Component,
137
+ args: [{
138
+ selector: "iss-ctrl-input",
139
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
140
+ changeDetection: ChangeDetectionStrategy.OnPush,
141
+ imports: [
142
+ ReactiveFormsModule,
143
+ MatFormFieldModule,
144
+ Hints,
145
+ MatInput,
146
+ MatInputModule,
147
+ ],
148
+ providers: [
149
+ { provide: NG_VALUE_ACCESSOR, useExisting: InputControl, multi: true },
150
+ { provide: NG_VALIDATORS, useExisting: InputControl, multi: true }
151
+ ],
152
+ template: `
153
+ <mat-form-field floatLabel="auto" class="">
154
+ <!-- Always rendered: upgrade.scss shows the floating label only while the projected <label> carries text, so an omitted or empty one collapses on its own. -->
155
+ <mat-label class="fs-16 fc-dark-gray">
156
+ <ng-content select="label"></ng-content>
157
+ </mat-label>
158
+ <ng-content select="[issPrefix]"></ng-content>
159
+ <div (click)="emitPrefixClick()" class="cursor-pointer">
160
+ @if (prefixText()) {
161
+ <span matTextPrefix>{{ prefixText() }}</span>
162
+ }
163
+ @if (prefixIcon()) {
164
+ <ds-icon matPrefix icon="{{prefixIcon()}}"></ds-icon>
165
+ }
166
+ </div>
167
+ <input
168
+ matInput
169
+ [errorStateMatcher]="errorStateMatcher"
170
+ (blur)="markAsTouched()"
171
+ (input)="emitValue()"
172
+ [formControl]="ctrl"
173
+ [attr.maxlength]="maxLength()"
174
+ [attr.minlength]="minLength()"
175
+ [attr.max]="max()"
176
+ [attr.min]="min()"
177
+ [placeholder]="placeholder()"
178
+ [readonly]="readonly()"
179
+ [type]="type()"
180
+ />
181
+ <ng-content select="[issSuffix]"></ng-content>
182
+ <div (click)="emitSuffixClick()" class="cursor-pointer">
183
+ @if (suffixText()) {
184
+ <span matTextSuffix>{{ suffixText() }}</span>
185
+ }
186
+ @if (suffixIcon()) {
187
+ <ds-icon matSuffix icon="{{suffixIcon()}}"></ds-icon>
188
+ }
189
+ </div>
190
+ <iss-ctrl-hints [hints]="hints()" [touched]="touched()"/>
191
+ </mat-form-field>
192
+ `
193
+ }]
194
+ }], propDecorators: { type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], prefixIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixIcon", required: false }] }], prefixText: [{ type: i0.Input, args: [{ isSignal: true, alias: "prefixText", required: false }] }], suffixIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixIcon", required: false }] }], suffixText: [{ type: i0.Input, args: [{ isSignal: true, alias: "suffixText", required: false }] }], onPrefixClick: [{ type: i0.Output, args: ["onPrefixClick"] }], onSuffixClick: [{ type: i0.Output, args: ["onSuffixClick"] }] } });
195
+
196
+ // The input control. Its field and viewer stay in the primary entry point and reach it
197
+ // from there, so the control ships only to an app that renders it or imports it directly.
198
+
199
+ /**
200
+ * Generated bundle index. Do not edit.
201
+ */
202
+
203
+ export { InputControl };
204
+ //# sourceMappingURL=iss-ctrl-input.mjs.map