ng-hub-ui-forms 22.4.0 → 22.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -3
- package/fesm2022/ng-hub-ui-forms.mjs +1157 -45
- package/fesm2022/ng-hub-ui-forms.mjs.map +1 -1
- package/ng-hub-ui-forms-22.6.0.tgz +0 -0
- package/package.json +6 -2
- package/{src/lib/styles → styles}/_tokens.scss +89 -5
- package/{src/lib/styles → styles}/index.scss +3 -0
- package/styles/mixins/_file-input-theme.scss +199 -0
- package/styles/mixins/_forms-theme.scss +67 -0
- package/{src/lib/styles → styles}/mixins/_segmented-theme.scss +1 -1
- package/types/ng-hub-ui-forms.d.ts +668 -16
- package/ng-hub-ui-forms-22.4.0.tgz +0 -0
- /package/{src/lib/styles → styles}/_field.scss +0 -0
package/README.md
CHANGED
|
@@ -92,11 +92,11 @@ mode — no Bootstrap dependency.
|
|
|
92
92
|
|
|
93
93
|
## 🎯 Features
|
|
94
94
|
|
|
95
|
-
- **Fields** — `hub-input` (text/number/email/password/color/switch/checkbox/counter, with input-group addons & masks, projected in-field affixes, a built-in `clearable` button and debounced typeahead `search`), `hub-otp-input`, `hub-textarea` (+ `hubAutoresize`), `hub-slider` (single / dual thumb, gradient fill), `hub-segmented` (segmented control field — single & multiple selection, horizontal & vertical, with label + validation), `hub-select` (dropdown format, grouping, typeahead, custom templates; the `buttons` / `checkbox` / `radio` formats are **deprecated** → use `hub-segmented`), `hub-datepicker` (single & range, keyboard nav, i18n).
|
|
95
|
+
- **Fields** — `hub-input` (text/number/email/password/color/switch/checkbox/counter, with input-group addons & masks, projected in-field affixes, a built-in `clearable` button and debounced typeahead `search`; the `file` format is **deprecated** → use `hub-file-input`), `hub-otp-input`, `hub-textarea` (+ `hubAutoresize`), `hub-slider` (single / dual thumb, gradient fill), `hub-segmented` (segmented control field — single & multiple selection, horizontal & vertical, with label + validation), `hub-select` (dropdown format, grouping, typeahead, custom templates; the `buttons` / `checkbox` / `radio` formats are **deprecated** → use `hub-segmented`), `hub-datepicker` (single & range, keyboard nav, i18n), `hub-file-input` (drag & drop, clipboard paste, type/size limits, previews, optional upload progress).
|
|
96
96
|
- **Automatic error display** — bind a field and its control errors render below it; `hub-fieldset`, `form[hubForm]` and `hub-legend` surface group- and form-level (cross-field) errors the same way, with zero wiring.
|
|
97
97
|
- **Containers** — `hub-fieldset` / `form[hubForm]` group fields and show their group errors; `hub-legend` renders an accessible legend.
|
|
98
|
-
- **Configurable** — `provideHubForms({ … })` sets the invalid-feedback templates, datepicker locale/labels and more, app-wide or per instance.
|
|
99
|
-
- **Validators & helpers** — `hubAreEqual` cross-field validator, `hubValidationError` / `hubFormText` projection directives, and a set of utility pipes.
|
|
98
|
+
- **Configurable** — `provideHubForms({ … })` sets the invalid-feedback templates, datepicker locale/labels, file-input labels and more, app-wide or per instance.
|
|
99
|
+
- **Validators & helpers** — `hubAreEqual` cross-field validator, the file validators (`hubAcceptedFiles`, `hubMaxFileSize`, `hubMinFileSize`, `hubMaxTotalSize`, `hubMaxFiles`, `hubMinFiles`), `hubValidationError` / `hubFormText` projection directives, and a set of utility pipes.
|
|
100
100
|
- **Signal Forms ready** — an opt-in [`ng-hub-ui-forms/signals`](#-signal-forms-opt-in) secondary entry point integrates Angular Signal Forms; the core stays Reactive-Forms-based and Angular-21-safe.
|
|
101
101
|
- **Theming** — every colour, border, radius and spacing is a `--hub-*` CSS custom property; ships shared SCSS tokens for consumers.
|
|
102
102
|
- **Cross-library adapter** — `hubFormControlAdapter` lets other libraries render `hub-input` / `hub-select` on demand without hard-depending on this package (see below).
|
|
@@ -215,6 +215,74 @@ Custom option/label templates are projected straight through to the engine:
|
|
|
215
215
|
<hub-datepicker formControlName="range" mode="range" label="Stay" />
|
|
216
216
|
```
|
|
217
217
|
|
|
218
|
+
### File input
|
|
219
|
+
|
|
220
|
+
Drag & drop, clipboard paste, constraints and previews. The control value stays native — a `File`, a `File[]`, or `null` — so it goes straight into a `FormData`.
|
|
221
|
+
|
|
222
|
+
```html
|
|
223
|
+
<hub-file-input
|
|
224
|
+
formControlName="attachments"
|
|
225
|
+
label="Attachments"
|
|
226
|
+
[multiple]="true"
|
|
227
|
+
accept="image/*,.pdf"
|
|
228
|
+
[maxSize]="5 * 1024 * 1024"
|
|
229
|
+
[maxFiles]="3"
|
|
230
|
+
preview="grid"
|
|
231
|
+
(rejected)="notify($event)"
|
|
232
|
+
/>
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
`accept`, `maxSize`, `maxFiles` and friends **filter**: an offending file never reaches the value and surfaces through `(rejected)` with a typed reason. They are enforced by hand, because the native `accept` attribute only filters the operating-system dialog — a drop or a paste bypasses it. To make the *control* invalid as well (worth doing when a value can also be patched in programmatically), add the matching validators:
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
new FormControl<File[]>([], [hubMaxFiles(3), hubMaxFileSize(5 * 1024 * 1024), hubAcceptedFiles('image/*,.pdf')]);
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Uploading is opt-in and transport-agnostic. Implement the contract in your application — the library never ships an endpoint — and the field renders per-file progress, cancel and retry:
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
@Injectable({ providedIn: 'root' })
|
|
245
|
+
export class ApiFileUploader implements HubFileUploader {
|
|
246
|
+
readonly #http = inject(HttpClient);
|
|
247
|
+
|
|
248
|
+
upload(file: File): Observable<HubFileUploadEvent> {
|
|
249
|
+
const body = new FormData();
|
|
250
|
+
body.append('file', file);
|
|
251
|
+
|
|
252
|
+
return this.#http.post('/api/files', body, { reportProgress: true, observe: 'events' }).pipe(
|
|
253
|
+
map((event) => {
|
|
254
|
+
if (event.type === HttpEventType.UploadProgress) {
|
|
255
|
+
// `total` is undefined when the size is unknown — pass null, not 0, so the bar
|
|
256
|
+
// renders indeterminate instead of looking stalled.
|
|
257
|
+
return { status: 'progress', loaded: event.loaded, total: event.total ?? null } as const;
|
|
258
|
+
}
|
|
259
|
+
if (event.type === HttpEventType.Response) {
|
|
260
|
+
return { status: 'done', response: event.body } as const;
|
|
261
|
+
}
|
|
262
|
+
return null;
|
|
263
|
+
}),
|
|
264
|
+
filter((event) => event !== null),
|
|
265
|
+
catchError((error) => of({ status: 'error', error } as const))
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
bootstrapApplication(App, { providers: [provideHttpClient(), provideHubFileUploader(ApiFileUploader)] });
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
> The observable **must be cold**: one subscription is one request. `cancel()` unsubscribes, which is what aborts the underlying `XMLHttpRequest`. A shared or hot observable silently breaks cancellation.
|
|
274
|
+
> Bind a submit button to `uploading()` if you need to wait for the uploads: the control stays valid while they run, by design.
|
|
275
|
+
|
|
276
|
+
Customize it without forking the template: 66 `--hub-file-input-*` tokens (every icon is a swappable CSS mask), the `hub-file-input-theme(...)` mixin, and two projection slots.
|
|
277
|
+
|
|
278
|
+
```html
|
|
279
|
+
<hub-file-input formControlName="attachments" [multiple]="true">
|
|
280
|
+
<ng-template hubFileIcon let-item>
|
|
281
|
+
<hub-icon [name]="item.file.type === 'application/pdf' ? 'fa:solid:file-pdf' : 'fa:solid:file'" />
|
|
282
|
+
</ng-template>
|
|
283
|
+
</hub-file-input>
|
|
284
|
+
```
|
|
285
|
+
|
|
218
286
|
### Automatic errors at every level
|
|
219
287
|
|
|
220
288
|
```html
|