ng-hub-ui-forms 22.13.0 → 22.15.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 CHANGED
@@ -92,7 +92,7 @@ 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`; 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, client-side search via `searchable` **and** server-side async typeahead via a `typeahead` Subject, tag creation with `addTag`, 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).
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, client-side search via `searchable` **and** server-side async typeahead via a `typeahead` Subject, tag creation with `addTag`, custom templates, `prepend` / `append` group addons and an attached action via `hubSelectSuffix`; the `buttons` / `checkbox` / `radio` formats are **deprecated** → use `hub-segmented`), `hub-datepicker` (single & range at any granularity from a year to a second, time picking, min/max down to the minute, 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
98
  - **Configurable** — `provideHubForms({ … })` sets the invalid-feedback templates, datepicker locale/labels, file-input labels and more, app-wide or per instance.
@@ -232,6 +232,35 @@ provideHubForms({
232
232
  <hub-select formControlName="city" label="City" [items]="cities" bindLabel="name" bindValue="id" groupBy="country" />
233
233
  ```
234
234
 
235
+ #### Addons and attached actions
236
+
237
+ `prepend` / `append` are the same group addons `hub-input` has: a string is one addon, an array
238
+ a run of them. They share the field's border and are not focusable.
239
+
240
+ ```html
241
+ <hub-select formControlName="budget" label="Budget" prepend="€" append="/ month" [items]="tiers" />
242
+ <hub-select formControlName="endpoint" [prepend]="['https://', 'api.']" [items]="regions" />
243
+ ```
244
+
245
+ For an **interactive** control attached to the edge — a button acting on whatever is selected —
246
+ project a `hubSelectSuffix` template. It is a template rather than plain content because the
247
+ select's catch-all `<ng-content>` carries `<ng-option>` through to the engine and would swallow
248
+ it; rendering from a template also keeps the action after the control in the DOM, so tabbing
249
+ reaches the field before the button acting on it.
250
+
251
+ ```html
252
+ <hub-select formControlName="product" label="Product" [items]="products" bindLabel="name">
253
+ <ng-template hubSelectSuffix>
254
+ <button type="button" aria-label="Configure the selected product" (click)="configure()">
255
+ <hub-icon name="fa:solid:gear" />
256
+ </button>
257
+ </ng-template>
258
+ </hub-select>
259
+ ```
260
+
261
+ > Import `HubSelectSuffixDirective` from `ng-hub-ui-forms`. Both mechanisms compose; with an
262
+ > append addon and an action present, the action is the outermost element.
263
+
235
264
  Custom option/label templates are projected straight through to the engine:
236
265
 
237
266
  ```html
@@ -296,6 +325,51 @@ A projected `hubSegmentedOption` template replaces each segment's content (icons
296
325
  <hub-datepicker formControlName="range" mode="range" label="Stay" />
297
326
  ```
298
327
 
328
+ `granularity` sets how precise each picked point is, and selects the panel with it. It is
329
+ orthogonal to `mode`: `mode` says how many points are picked, `granularity` how precise each
330
+ one is.
331
+
332
+ ```html
333
+ <!-- a validity window: each endpoint carries its own time -->
334
+ <hub-datepicker formControlName="window" mode="range" granularity="minute" [minuteStep]="15" />
335
+
336
+ <!-- coarse units get a 12-cell period grid instead of the calendar -->
337
+ <hub-datepicker formControlName="billingPeriod" granularity="month" />
338
+ ```
339
+
340
+ | `granularity` | Panel | Value (default `valueFormat`) |
341
+ | --- | --- | --- |
342
+ | `year` | Decade grid | `"2026"` |
343
+ | `month` | 12-month grid | `"2026-09"` |
344
+ | `day` *(default)* | Calendar | `"2026-09-01"` |
345
+ | `hour` / `minute` / `second` | Calendar + time strip | `"2026-09-01T09:30:00+02:00"` |
346
+
347
+ **The value's timezone.** At `day` and coarser it is a bare calendar date with no zone attached,
348
+ exactly as before. From `hour` onwards it is a full ISO 8601 timestamp carrying **the reader's
349
+ local wall clock and the offset of that very date** — `+02:00` in Madrid in September, `+01:00`
350
+ for the same clock in January. It denotes an unambiguous instant; convert with
351
+ `new Date(value).toISOString()` if you need UTC.
352
+
353
+ `min` and `max` honour the time too: a day is disabled only when no instant of it is allowed, so
354
+ `min="2026-09-01T14:00"` leaves 1 September clickable and the time controls refuse the earlier
355
+ hours.
356
+
357
+ Three independent axes control the formats:
358
+
359
+ ```html
360
+ <!-- what the control holds: 'iso' (default) | 'date' | 'timestamp' | (date) => unknown -->
361
+ <hub-datepicker formControlName="due" valueFormat="date" />
362
+
363
+ <!-- what the user reads: Intl options | an Angular pattern | (date) => string -->
364
+ <hub-datepicker formControlName="due" displayFormat="dd/MM/yyyy HH:mm" />
365
+
366
+ <!-- how an incoming value is read; also applies to min/max -->
367
+ <hub-datepicker formControlName="due" [parse]="parseLegacyDate" />
368
+ ```
369
+
370
+ ISO strings of any width, `Date` instances and epoch milliseconds are detected automatically, so
371
+ `parse` is only needed for dialects outside that set.
372
+
299
373
  ### File input
300
374
 
301
375
  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`.