@wemake4u/form-controls 2.0.2 → 2.0.3

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.
@@ -1,6 +1,6 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import { AfterContentInit, ComponentRef, DoCheck, EnvironmentProviders, InjectionToken, Injector, OnDestroy, Provider, Signal, TemplateRef, Type } from "@angular/core";
3
- import { AbstractControl, ControlValueAccessor, FormArray, FormGroup, ValidationErrors, Validator } from "@angular/forms";
3
+ import { AbstractControl, ControlValueAccessor, FormArray, FormControl, FormGroup, ValidationErrors, Validator } from "@angular/forms";
4
4
  import { Options, Splide } from "@splidejs/splide";
5
5
  import { Observable } from "rxjs";
6
6
  import { Row } from "@tanstack/angular-table";
@@ -165,7 +165,17 @@ export declare class SirioInfoButton {
165
165
  readonly title: import("@angular/core").InputSignal<string>;
166
166
  /** Accessible name of the button (e.g. "Informazioni su Codice fiscale"). */
167
167
  readonly label: import("@angular/core").InputSignal<string>;
168
+ /**
169
+ * Id(s) of the element(s) whose text completes the accessible name after `label`
170
+ * (e.g. the label of the control). Use it when the label text is not available as a string,
171
+ * for instance when it is projected content: the name becomes "`label` <text of the element>".
172
+ */
173
+ readonly labelledBy: import("@angular/core").InputSignal<string | null>;
168
174
  readonly placement: import("@angular/core").InputSignal<SirioTooltipPlacement>;
175
+ /** Id of the button: referenced by its own aria-labelledby to prepend `label` to the name. */
176
+ protected readonly buttonId: string;
177
+ /** Self-reference first, so the name is "<aria-label> <referenced text>". */
178
+ protected readonly ariaLabelledBy: import("@angular/core").Signal<string | null>;
169
179
  protected readonly template: import("@angular/core").Signal<TemplateRef<unknown> | null>;
170
180
  static ɵfac: i0.ɵɵFactoryDeclaration<SirioInfoButton, never>;
171
181
  static ɵcmp: i0.ɵɵComponentDeclaration<SirioInfoButton, "wm-sirio-info-button", never, {
@@ -184,6 +194,11 @@ export declare class SirioInfoButton {
184
194
  "required": false;
185
195
  "isSignal": true;
186
196
  };
197
+ "labelledBy": {
198
+ "alias": "labelledBy";
199
+ "required": false;
200
+ "isSignal": true;
201
+ };
187
202
  "placement": {
188
203
  "alias": "placement";
189
204
  "required": false;
@@ -313,6 +328,12 @@ export declare abstract class SirioControlBase<T> implements ControlValueAccesso
313
328
  readonly readonlyAppearance: import("@angular/core").InputSignal<SirioReadonlyAppearance | null>;
314
329
  /** Visual "required" marker. It is also inferred from Validators.required on the bound control. */
315
330
  readonly required: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
331
+ /**
332
+ * Required marker (asterisk, aria-required) without validation, for hosts that validate the control on their own
333
+ * (e.g. a form player with its own required validator). A `[required]` binding next to `formControlName` also
334
+ * matches the Angular RequiredValidator directive, which adds Validators.required to the control; this input does not.
335
+ */
336
+ readonly requiredIndicator: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
316
337
  /** Disabled state when the component is used without Angular forms. */
317
338
  readonly disabledInput: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
318
339
  /** Per-control error-message overrides (merged on top of SIRIO_ERROR_MESSAGES). */
@@ -361,8 +382,19 @@ export declare abstract class SirioControlBase<T> implements ControlValueAccesso
361
382
  readonly pendingLabel: import("@angular/core").InputSignal<string>;
362
383
  /** Milliseconds before the spinner appears (fast validations show nothing). */
363
384
  readonly pendingDelay: import("@angular/core").InputSignalWithTransform<number, unknown>;
385
+ /**
386
+ * Lets the user set the field to null: a reset button ("X", as in the kit autocomplete) inside the field,
387
+ * shown only while the field has a value and is editable and not required. Default false.
388
+ * Supported by textbox, number, date, time, datetime and single select; the radio group adds an option
389
+ * with value null instead, and a checkbox becomes a radio group yes / no / no answer.
390
+ */
391
+ readonly nullable: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
392
+ /** Accessible name of the reset button, followed by the label ("Nessun valore per Codice fiscale"). */
393
+ readonly nullLabel: import("@angular/core").InputSignal<string>;
364
394
  /** Accessible name of the info button. */
365
395
  readonly infoButtonLabel: import("@angular/core").Signal<string>;
396
+ /** Accessible name of the null reset button. */
397
+ readonly nullButtonLabel: import("@angular/core").Signal<string>;
366
398
  /** Id of the label text (without the info button), for aria-labelledby on fieldsets. */
367
399
  readonly labelTextId: import("@angular/core").Signal<string>;
368
400
  protected readonly value: import("@angular/core").WritableSignal<T | null>;
@@ -390,6 +422,8 @@ export declare abstract class SirioControlBase<T> implements ControlValueAccesso
390
422
  */
391
423
  readonly control: import("@angular/core").Signal<AbstractControl<any, any, any> | null>;
392
424
  readonly isRequired: import("@angular/core").Signal<boolean>;
425
+ /** The null reset button is shown: nullable, editable, not required and with a value. */
426
+ readonly showNullButton: import("@angular/core").Signal<boolean>;
393
427
  /** An async validator is running on the bound control (status PENDING). */
394
428
  readonly isPending: import("@angular/core").Signal<boolean>;
395
429
  /** The pending indicator is shown: PENDING for at least `pendingDelay` ms. */
@@ -468,6 +502,15 @@ export declare abstract class SirioControlBase<T> implements ControlValueAccesso
468
502
  protected sameValue(a: T | null, b: T | null): boolean;
469
503
  /** Equality of two values (or array items); controls with `compareWith` use it. */
470
504
  protected sameItem(a: unknown, b: unknown): boolean;
505
+ /** True when an internal value counts as "no value" for the null reset button. */
506
+ protected isNullValue(value: T | null): boolean;
507
+ /**
508
+ * Sets the field to null (reset button of `nullable`): clears what is shown, notifies the form
509
+ * and moves the focus back to the field (the button disappears).
510
+ */
511
+ setNull(): void;
512
+ /** Moves the focus to the main element of the control (the one with `inputId`). */
513
+ protected focusField(): void;
471
514
  /** Hook to convert the model value into the internal value (override when they differ). */
472
515
  protected fromModel(value: unknown): T | null;
473
516
  /** Hook to convert the internal value into the model value (override when they differ). */
@@ -519,6 +562,11 @@ export declare abstract class SirioControlBase<T> implements ControlValueAccesso
519
562
  "required": false;
520
563
  "isSignal": true;
521
564
  };
565
+ "requiredIndicator": {
566
+ "alias": "requiredIndicator";
567
+ "required": false;
568
+ "isSignal": true;
569
+ };
522
570
  "disabledInput": {
523
571
  "alias": "disabled";
524
572
  "required": false;
@@ -589,6 +637,16 @@ export declare abstract class SirioControlBase<T> implements ControlValueAccesso
589
637
  "required": false;
590
638
  "isSignal": true;
591
639
  };
640
+ "nullable": {
641
+ "alias": "nullable";
642
+ "required": false;
643
+ "isSignal": true;
644
+ };
645
+ "nullLabel": {
646
+ "alias": "nullLabel";
647
+ "required": false;
648
+ "isSignal": true;
649
+ };
592
650
  }, {}, never, never, true, never>;
593
651
  }
594
652
  /**
@@ -2857,10 +2915,20 @@ export declare function sirioCloneControl<C extends AbstractControl>(control: C)
2857
2915
  * @internal
2858
2916
  */
2859
2917
  export declare function sirioSyncControl(target: AbstractControl, source: AbstractControl): boolean;
2860
- /** Sizes of the kit dialog (`.sirio-dialog-wrapper` modifiers); default 600px. */
2861
- export type SirioDialogSize = 'sm' | 'default' | 'lg' | 'xl';
2918
+ /**
2919
+ * Sizes of the kit dialog (`.sirio-dialog-wrapper` modifiers); default 600px. `fullscreen` takes the whole window,
2920
+ * with the body between header and footer, for content that needs room such as an editor.
2921
+ */
2922
+ export type SirioDialogSize = 'sm' | 'default' | 'lg' | 'xl' | 'fullscreen';
2862
2923
  /** Color of the title icon (kit examples: default blue, "Avvertimento", "Pericolo"). */
2863
2924
  export type SirioDialogTone = 'default' | 'warning' | 'danger';
2925
+ /** Backdrop behind the dialog: `dark` = the kit one (dark blue; grey for the drawer), `light` = black at 50%. */
2926
+ export type SirioDialogBackdrop = 'dark' | 'light';
2927
+ /**
2928
+ * Header of the dialog: `kit` = the kit one (the icon is a block above the title), `compact` = the icon inline before
2929
+ * the title and less space around it, for dialogs with many fields.
2930
+ */
2931
+ export type SirioDialogHeader = 'kit' | 'compact';
2864
2932
  /**
2865
2933
  * Footer of a dialog (kit `.sirio-dialog-footer`), with the action buttons:
2866
2934
  * `<div wmSirioDialogFooter>...</div>`.
@@ -2890,7 +2958,7 @@ export declare class SirioDialogClose {
2890
2958
  }
2891
2959
  /**
2892
2960
  * Dialog of the Sirio web kit ("Dialog"): `.sirio-dialog` (backdrop) > `.sirio-dialog-wrapper`
2893
- * (size `sm` / `lg` / `xl`, `dialog-centered`) > `.sirio-dialog-content` with header
2961
+ * (size `sm` / `lg` / `xl` / `fullscreen`, `dialog-centered`) > `.sirio-dialog-content` with header
2894
2962
  * (`h2.sirio-dialog-title` with the icon, close button `.sirio-btn-close`), body and footer.
2895
2963
  *
2896
2964
  * Behaviour of the kit script (SirioDialog) reproduced in Angular: `aria-modal`, focus moved into
@@ -2901,6 +2969,12 @@ export declare class SirioDialogClose {
2901
2969
  * With `drawer` it is the kit drawer (`.sirio-drawer`): a panel opening from the right. Inside a component
2902
2970
  * opened by `SirioDialogService.open()` the dialog opens by itself and closes the `SirioDialogRef`.
2903
2971
  *
2972
+ * `backdrop="light"` puts the same black at 50% behind any dialog, drawer included, instead of the kit
2973
+ * backdrop (dark blue for the dialog, an almost transparent grey for the drawer).
2974
+ *
2975
+ * `header="compact"` puts the title icon inline instead of in a block above the title, with less space around the
2976
+ * header: the dialog is about 60px lower (for dialogs with many fields).
2977
+ *
2904
2978
  * ```html
2905
2979
  * <wm-sirio-dialog [(open)]="confirmOpen" title="Vuoi eliminare il tuo account?" tone="danger" alert
2906
2980
  * (closed)="onClosed($event)">
@@ -2935,6 +3009,10 @@ export declare class SirioDialog {
2935
3009
  readonly alert: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
2936
3010
  /** Kit drawer: panel opening from the right (`.sirio-drawer`). */
2937
3011
  readonly drawer: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
3012
+ /** Backdrop: `dark` (kit, default) or `light` (black at 50%, also for the drawer). */
3013
+ readonly backdrop: import("@angular/core").InputSignalWithTransform<SirioDialogBackdrop, "" | SirioDialogBackdrop | null | undefined>;
3014
+ /** Header: `kit` (default, the icon above the title) or `compact` (the icon inline, less space). */
3015
+ readonly header: import("@angular/core").InputSignalWithTransform<SirioDialogHeader, "" | SirioDialogHeader | null | undefined>;
2938
3016
  /** Extra classes of the `.sirio-dialog` element (e.g. kit drawer / side panel classes). */
2939
3017
  readonly panelClass: import("@angular/core").InputSignal<string>;
2940
3018
  /**
@@ -3045,6 +3123,16 @@ export declare class SirioDialog {
3045
3123
  "required": false;
3046
3124
  "isSignal": true;
3047
3125
  };
3126
+ "backdrop": {
3127
+ "alias": "backdrop";
3128
+ "required": false;
3129
+ "isSignal": true;
3130
+ };
3131
+ "header": {
3132
+ "alias": "header";
3133
+ "required": false;
3134
+ "isSignal": true;
3135
+ };
3048
3136
  "panelClass": {
3049
3137
  "alias": "panelClass";
3050
3138
  "required": false;
@@ -3273,6 +3361,11 @@ export declare class SirioDataGrid<T extends object = any> {
3273
3361
  readonly expanded: import("@angular/core").ModelSignal<SirioGridExpanded>;
3274
3362
  /** With `wmSirioGridDetail`: which rows have a detail (default every data row). */
3275
3363
  readonly rowExpandable: import("@angular/core").InputSignal<((row: T) => boolean) | null>;
3364
+ /**
3365
+ * Shows "Espandi tutto" / "Comprimi tutto" above a grid with detail rows, tree rows or groups. Off for short
3366
+ * grids that start expanded, where the buttons only add noise.
3367
+ */
3368
+ readonly expandAllTools: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
3276
3369
  /**
3277
3370
  * Row number column at the start (after selection and expand columns): continuous across pages,
3278
3371
  * in the current filter and sort order; group rows have no number, tree rows are numbered by
@@ -3454,6 +3547,14 @@ export declare class SirioDataGrid<T extends object = any> {
3454
3547
  readonly collapseRowLabel: import("@angular/core").InputSignal<string>;
3455
3548
  /** Accessible label of the resize handle: "<label> <header>". */
3456
3549
  readonly resizeColumnLabel: import("@angular/core").InputSignal<string>;
3550
+ /**
3551
+ * Keyboard instructions of the grid pattern (WCAG 2.1 SC 3.3.2): read when the focus enters the
3552
+ * table (aria-describedby), only with the keyboard navigation (role grid / treegrid). Users expect
3553
+ * Tab to move between the buttons of a row: the arrows do it, Tab leaves the grid. Empty = none.
3554
+ */
3555
+ readonly navigationHint: import("@angular/core").InputSignal<string>;
3556
+ /** aria-describedby of the table: the navigation hint with role grid / treegrid. */
3557
+ protected readonly tableDescribedBy: import("@angular/core").Signal<string | null>;
3457
3558
  /** Hint of the headers of a reorderable grid. */
3458
3559
  readonly reorderHint: import("@angular/core").InputSignal<string>;
3459
3560
  /** Hint of a resizable header (keyboard of ag-grid: Alt+arrows). */
@@ -4160,6 +4261,11 @@ export declare class SirioDataGrid<T extends object = any> {
4160
4261
  "required": false;
4161
4262
  "isSignal": true;
4162
4263
  };
4264
+ "expandAllTools": {
4265
+ "alias": "expandAllTools";
4266
+ "required": false;
4267
+ "isSignal": true;
4268
+ };
4163
4269
  "rowNumbers": {
4164
4270
  "alias": "rowNumbers";
4165
4271
  "required": false;
@@ -4480,6 +4586,11 @@ export declare class SirioDataGrid<T extends object = any> {
4480
4586
  "required": false;
4481
4587
  "isSignal": true;
4482
4588
  };
4589
+ "navigationHint": {
4590
+ "alias": "navigationHint";
4591
+ "required": false;
4592
+ "isSignal": true;
4593
+ };
4483
4594
  "reorderHint": {
4484
4595
  "alias": "reorderHint";
4485
4596
  "required": false;
@@ -4621,6 +4732,55 @@ interface InlineFilter {
4621
4732
  placeholder: string;
4622
4733
  summary?: string;
4623
4734
  }
4735
+ /** Sort criterion of a server-side query (same shape as remoting `OrderBy`). */
4736
+ export interface SirioRemoteSort {
4737
+ colId: string;
4738
+ sort: 'asc' | 'desc';
4739
+ }
4740
+ /** Ag-grid style filter model, by column key. */
4741
+ export type SirioRemoteFilterModel = Record<string, unknown>;
4742
+ /** Filter type by column key: the `filter` of the columns (default `text`). */
4743
+ export type SirioRemoteFilterTypes = Record<string, SirioGridFilterType>;
4744
+ /** Options of a server-side query (same shape as remoting `QueryOptions`). */
4745
+ export interface SirioRemoteQueryOptions {
4746
+ count?: boolean;
4747
+ top?: number;
4748
+ skip?: number;
4749
+ orderBy?: SirioRemoteSort[];
4750
+ filter?: SirioRemoteFilterModel;
4751
+ /**
4752
+ * Total row count, written by the loader into the options it receives (remoting copies `$count`
4753
+ * of the response here): it becomes the `total` of the grid result.
4754
+ */
4755
+ totalCount?: number;
4756
+ }
4757
+ export interface SirioRemoteGridSourceOptions {
4758
+ /** Filters that are not grid columns (e.g. states chosen with chips), read at every query. */
4759
+ extraFilter?: () => SirioRemoteFilterModel;
4760
+ /**
4761
+ * Filter type of the number, date, select and boolean columns: needed to translate the values and
4762
+ * the conditions with operators (`filterOperators`), which have the same shape for dates and texts.
4763
+ */
4764
+ filterTypes?: SirioRemoteFilterTypes;
4765
+ }
4766
+ /**
4767
+ * Data source of a grid with paging, sorting and filtering on the server: the grid query becomes
4768
+ * `SirioRemoteQueryOptions` and the loader returns the rows (it is the counterpart of remoting
4769
+ * `queryRows`, which does the same for ag-grid).
4770
+ *
4771
+ * ```ts
4772
+ * readonly source = sirioRemoteGridSource(options => this.service.getItems(options), {
4773
+ * filterTypes: { version: 'number', created: 'date' }
4774
+ * });
4775
+ * ```
4776
+ */
4777
+ export declare function sirioRemoteGridSource<T extends object>(load: (options: SirioRemoteQueryOptions) => Observable<T[] | null>, sourceOptions?: SirioRemoteGridSourceOptions): SirioGridDataSource<T>;
4778
+ /** Server-side query options of a grid query, with optional extra filters. */
4779
+ export declare function sirioToQueryOptions(query: SirioGridQuery, extraFilter?: SirioRemoteFilterModel, filterTypes?: SirioRemoteFilterTypes): SirioRemoteQueryOptions;
4780
+ /** Ag-grid style filter model of the active grid filters. */
4781
+ export declare function sirioToFilterModel(filters: SirioGridFilters, filterTypes?: SirioRemoteFilterTypes): SirioRemoteFilterModel;
4782
+ /** Any of the values (conditions in OR): for example the states chosen with chips. */
4783
+ export declare function sirioAnyOf(values: readonly (string | number)[]): SirioRemoteFilterModel;
4624
4784
  /** Duration of the kit collapse transition (`[data-sirio-visible=collapsing]`, .35s). */
4625
4785
  declare const SIRIO_COLLAPSE_MS = 350;
4626
4786
  /** Values of `data-sirio-visible` used by the kit collapsible elements. */
@@ -5144,6 +5304,8 @@ export declare const SIRIO_SIDENAV: readonly [typeof SirioSidenav, typeof SirioS
5144
5304
  * (`danger` = "Alert", `warning`, `info`, `success`).
5145
5305
  */
5146
5306
  export type SirioTagType = 'default' | 'danger' | 'warning' | 'info' | 'success';
5307
+ /** Size of the tag: `default` = the kit tag, `small` = compact (e.g. inside the rows of a grid). */
5308
+ export type SirioTagSize = 'default' | 'small';
5147
5309
  /**
5148
5310
  * Tag of the Sirio web kit ("Tag"), applied to a `<span>`: `span.sirio-tag` with the kit background
5149
5311
  * class of the type (`sirio-bg-danger`, `sirio-bg-warning`, `sirio-bg-info`, `sirio-bg-success`).
@@ -5151,10 +5313,14 @@ export type SirioTagType = 'default' | 'danger' | 'warning' | 'info' | 'success'
5151
5313
  * As the kit says, tags label the type of a content in one or two words (e.g. inside a Card) and
5152
5314
  * are **not interactive**: never use them instead of the input or selection chips.
5153
5315
  *
5316
+ * `outline` draws the lighter variant (border and text in the color of the type, no background),
5317
+ * for secondary information next to other tags; `size="small"` makes it compact.
5318
+ *
5154
5319
  * ```html
5155
5320
  * <span wmSirioTag>Default</span>
5156
5321
  * <span wmSirioTag="success">Completato</span>
5157
5322
  * <span wmSirioTag background="primary-light-40">Novità</span>
5323
+ * <span wmSirioTag="warning" outline size="small">Trace</span>
5158
5324
  * ```
5159
5325
  */
5160
5326
  export declare class SirioTag {
@@ -5162,9 +5328,13 @@ export declare class SirioTag {
5162
5328
  readonly type: import("@angular/core").InputSignalWithTransform<SirioTagType, "" | SirioTagType | null | undefined>;
5163
5329
  /**
5164
5330
  * Any other kit background (`sirio-bg-*` without the prefix, e.g. `warning-80`,
5165
- * `primary-light-40`); it replaces the color of the type.
5331
+ * `primary-light-40`); it replaces the color of the type (and the outline).
5166
5332
  */
5167
5333
  readonly background: import("@angular/core").InputSignal<string | null>;
5334
+ /** Outline variant: border and text in the color of the type, transparent background. */
5335
+ readonly outline: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
5336
+ /** Size: `default` (the kit tag) or `small` (compact). */
5337
+ readonly size: import("@angular/core").InputSignalWithTransform<SirioTagSize, "" | SirioTagSize | null | undefined>;
5168
5338
  protected readonly classes: import("@angular/core").Signal<string>;
5169
5339
  static ɵfac: i0.ɵɵFactoryDeclaration<SirioTag, never>;
5170
5340
  static ɵcmp: i0.ɵɵComponentDeclaration<SirioTag, "span[wmSirioTag]", never, {
@@ -5178,6 +5348,16 @@ export declare class SirioTag {
5178
5348
  "required": false;
5179
5349
  "isSignal": true;
5180
5350
  };
5351
+ "outline": {
5352
+ "alias": "outline";
5353
+ "required": false;
5354
+ "isSignal": true;
5355
+ };
5356
+ "size": {
5357
+ "alias": "size";
5358
+ "required": false;
5359
+ "isSignal": true;
5360
+ };
5181
5361
  }, {}, never, ["*"], true, never>;
5182
5362
  }
5183
5363
  /**
@@ -7009,7 +7189,7 @@ export declare class SirioTextbox extends SirioAdornedControlBase<string> {
7009
7189
  readonly type: import("@angular/core").InputSignal<SirioTextboxType>;
7010
7190
  readonly maxlength: import("@angular/core").InputSignalWithTransform<number | null, unknown>;
7011
7191
  readonly autocomplete: import("@angular/core").InputSignal<string | null>;
7012
- /** When true, '' is propagated to the model as null. */
7192
+ /** When true, '' is propagated to the model as null (always with `nullable`). */
7013
7193
  readonly emptyAsNull: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
7014
7194
  /** Casing applied to typed/pasted text. Values set from code (setValue/patchValue) are not changed. */
7015
7195
  readonly textCase: import("@angular/core").InputSignal<SirioTextCase>;
@@ -7056,6 +7236,8 @@ export declare class SirioTextarea extends SirioControlBase<string> {
7056
7236
  readonly rows: import("@angular/core").InputSignalWithTransform<number, unknown>;
7057
7237
  readonly maxlength: import("@angular/core").InputSignalWithTransform<number | null, unknown>;
7058
7238
  readonly showCounter: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
7239
+ /** When true, '' is propagated to the model as null. */
7240
+ readonly emptyAsNull: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
7059
7241
  /** Casing applied to typed/pasted text. Values set from code (setValue/patchValue) are not changed. */
7060
7242
  readonly textCase: import("@angular/core").InputSignal<SirioTextCase>;
7061
7243
  /** Text alignment (null = Sirio default). */
@@ -7081,6 +7263,11 @@ export declare class SirioTextarea extends SirioControlBase<string> {
7081
7263
  "required": false;
7082
7264
  "isSignal": true;
7083
7265
  };
7266
+ "emptyAsNull": {
7267
+ "alias": "emptyAsNull";
7268
+ "required": false;
7269
+ "isSignal": true;
7270
+ };
7084
7271
  "textCase": {
7085
7272
  "alias": "textCase";
7086
7273
  "required": false;
@@ -7410,6 +7597,13 @@ export declare abstract class SirioDateTimeBase extends SirioControlBase<string>
7410
7597
  };
7411
7598
  }, {}, never, never, true, never>;
7412
7599
  }
7600
+ /**
7601
+ * Keyboard instructions of the date picker: `hint` when given (null or '' = none), otherwise the
7602
+ * default text for the locale (Italian or English) and the pick level.
7603
+ */
7604
+ export declare function sirioDatePickerKeyboardHint(hint: string | null | undefined, locale: string, level?: SirioDatePickLevel): string | null;
7605
+ /** Space separated ids for aria-describedby, skipping the empty ones (null when none). */
7606
+ export declare function sirioJoinIds(...ids: (string | null | undefined)[]): string | null;
7413
7607
  /**
7414
7608
  * Attaches the date picker of the Sirio web kit guide — **VanillaJS Datepicker**, styled by the kit
7415
7609
  * CSS (`css/datepicker.min.css` + the `.datepicker*` rules of `webkit.min.css`) — to an input
@@ -7462,6 +7656,13 @@ export declare class SirioDatePickerDirective implements OnDestroy {
7462
7656
  /** Back in its place after the input when the picker closes. */
7463
7657
  protected unfloat(): void;
7464
7658
  private create;
7659
+ /**
7660
+ * Picker options changed without touching the text. VanillaJS Datepicker `setOptions` always
7661
+ * rewrites the field with its selected dates (`refreshUI(this, 3)`, bypassing the `refresh`
7662
+ * override), and this effect may run before the one on `date`: when a limit changes together with
7663
+ * the value, the field would show the previous date again (or lose the text being typed).
7664
+ */
7665
+ private setOptions;
7465
7666
  /** Aligns the picker selection with the component value, without touching the text. */
7466
7667
  private select;
7467
7668
  private isoOf;
@@ -7591,6 +7792,16 @@ export declare class SirioDate extends SirioDateTimeBase {
7591
7792
  readonly hideOnFocus: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
7592
7793
  /** What is picked: a full date, a month (mm/aaaa) or a year (aaaa). */
7593
7794
  readonly pickLevel: import("@angular/core").InputSignal<SirioDatePickLevel>;
7795
+ /**
7796
+ * Keyboard instructions of the picker, read after the label (aria-describedby).
7797
+ * Not set: default text for `LOCALE_ID` and the pick level; null or '' = none.
7798
+ */
7799
+ readonly keyboardHint: import("@angular/core").InputSignal<string | null | undefined>;
7800
+ /** Instructions shown to screen readers (none when the picker cannot open). */
7801
+ protected readonly keyboardHintText: import("@angular/core").Signal<string | null>;
7802
+ protected readonly keyboardHintId: import("@angular/core").Signal<string>;
7803
+ /** aria-describedby of the field: help and error first, then the keyboard instructions. */
7804
+ protected readonly fieldDescribedBy: import("@angular/core").Signal<string | null>;
7594
7805
  /** Layout of the field for the pick level. */
7595
7806
  protected readonly layout: import("@angular/core").Signal<import("@wemake4u/form-controls").SirioDateTimeLayout>;
7596
7807
  protected readonly maxLength: import("@angular/core").Signal<number>;
@@ -7629,6 +7840,11 @@ export declare class SirioDate extends SirioDateTimeBase {
7629
7840
  "required": false;
7630
7841
  "isSignal": true;
7631
7842
  };
7843
+ "keyboardHint": {
7844
+ "alias": "keyboardHint";
7845
+ "required": false;
7846
+ "isSignal": true;
7847
+ };
7632
7848
  }, {}, never, never, true, never>;
7633
7849
  }
7634
7850
  /**
@@ -7702,6 +7918,16 @@ export declare class SirioDateTime extends SirioDateTimeBase {
7702
7918
  readonly fieldLabels: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
7703
7919
  /** Completes a missing part when the component is left: time 00:00 or today's date. */
7704
7920
  readonly completeParts: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
7921
+ /**
7922
+ * Keyboard instructions of the date picker, read on the date field (aria-describedby).
7923
+ * Not set: default text for `LOCALE_ID`; null or '' = none.
7924
+ */
7925
+ readonly keyboardHint: import("@angular/core").InputSignal<string | null | undefined>;
7926
+ /** Instructions shown to screen readers (none when the picker cannot open). */
7927
+ protected readonly keyboardHintText: import("@angular/core").Signal<string | null>;
7928
+ protected readonly keyboardHintId: import("@angular/core").Signal<string>;
7929
+ /** aria-describedby of the date field: help and error first, then the keyboard instructions. */
7930
+ protected readonly dateDescribedBy: import("@angular/core").Signal<string | null>;
7705
7931
  private readonly host;
7706
7932
  private readonly dateFieldRef;
7707
7933
  protected readonly dateText: import("@angular/core").WritableSignal<string>;
@@ -7776,6 +8002,11 @@ export declare class SirioDateTime extends SirioDateTimeBase {
7776
8002
  "required": false;
7777
8003
  "isSignal": true;
7778
8004
  };
8005
+ "keyboardHint": {
8006
+ "alias": "keyboardHint";
8007
+ "required": false;
8008
+ "isSignal": true;
8009
+ };
7779
8010
  }, {}, never, never, true, never>;
7780
8011
  }
7781
8012
  /**
@@ -7785,6 +8016,10 @@ export declare class SirioDateTime extends SirioDateTimeBase {
7785
8016
  * The label can contain markup: projected content is rendered inside the `<label>`, after the
7786
8017
  * `label` text (use inline elements only, such as `<span>`, `<strong>`, `<em>`, `<a>`).
7787
8018
  *
8019
+ * With `nullable` the checkbox becomes a group of radio buttons (yes / no / no answer): the value is
8020
+ * `true`, `false` or `null`. The labels are `trueLabel`, `falseLabel` and `nullOptionLabel`; the null option
8021
+ * is not shown when the field is required. The label (text and projected content) names the group.
8022
+ *
7788
8023
  * ```html
7789
8024
  * <wm-sirio-checkbox label="Accetto i termini" formControlName="privacy" />
7790
8025
  * <wm-sirio-checkbox label="Notifiche" toggle formControlName="notify" />
@@ -7797,8 +8032,29 @@ export declare class SirioCheckbox extends SirioControlBase<boolean> {
7797
8032
  /** Toggle position relative to the label. */
7798
8033
  readonly togglePosition: import("@angular/core").InputSignal<"left" | "right">;
7799
8034
  readonly inline: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
8035
+ /** nullable: label of the option with value true. */
8036
+ readonly trueLabel: import("@angular/core").InputSignal<string>;
8037
+ /** nullable: label of the option with value false. */
8038
+ readonly falseLabel: import("@angular/core").InputSignal<string>;
8039
+ /** nullable: label of the option with value null (not shown when the field is required). */
8040
+ readonly nullOptionLabel: import("@angular/core").InputSignal<string>;
8041
+ /** nullable: the options of the radio group. */
8042
+ protected readonly nullableOptions: import("@angular/core").Signal<{
8043
+ value: boolean | null;
8044
+ label: string;
8045
+ isNull: boolean;
8046
+ }[]>;
8047
+ /** nullable: native radio "name" (the name input or a generated unique one). */
8048
+ protected get groupName(): string;
8049
+ private readonly fallbackName;
8050
+ /** nullable: a radio of the group was chosen. */
8051
+ protected onChoose(value: boolean | null): void;
7800
8052
  protected onToggle(event: Event): void;
7801
- protected fromModel(value: unknown): boolean;
8053
+ /**
8054
+ * The value is a boolean. With nullable, null stays null (the null option is checked) and
8055
+ * undefined checks no option (e.g. a property not passed, in wm-sirio-schema-form).
8056
+ */
8057
+ protected fromModel(value: unknown): boolean | null;
7802
8058
  static ɵfac: i0.ɵɵFactoryDeclaration<SirioCheckbox, never>;
7803
8059
  static ɵcmp: i0.ɵɵComponentDeclaration<SirioCheckbox, "wm-sirio-checkbox", never, {
7804
8060
  "toggle": {
@@ -7816,6 +8072,21 @@ export declare class SirioCheckbox extends SirioControlBase<boolean> {
7816
8072
  "required": false;
7817
8073
  "isSignal": true;
7818
8074
  };
8075
+ "trueLabel": {
8076
+ "alias": "trueLabel";
8077
+ "required": false;
8078
+ "isSignal": true;
8079
+ };
8080
+ "falseLabel": {
8081
+ "alias": "falseLabel";
8082
+ "required": false;
8083
+ "isSignal": true;
8084
+ };
8085
+ "nullOptionLabel": {
8086
+ "alias": "nullOptionLabel";
8087
+ "required": false;
8088
+ "isSignal": true;
8089
+ };
7819
8090
  }, {}, never, ["*"], true, never>;
7820
8091
  }
7821
8092
  /**
@@ -7897,6 +8168,9 @@ export declare class SirioChecklist<T = unknown> extends SirioControlBase<T[]> i
7897
8168
  * `chips` renders the options as Sirio selection chips ("Chips di selezione (Radio button)":
7898
8169
  * `.sirio-chip-selection` with the radio and its label), always on one row that wraps.
7899
8170
  *
8171
+ * `nullable` adds a last option with value null (text `nullOptionLabel`, default "Nessuna scelta"), so the user
8172
+ * can go back to no value; it is not shown when the field is required.
8173
+ *
7900
8174
  * ```html
7901
8175
  * <wm-sirio-radio-group label="Sesso" [options]="[{ value: 'M', label: 'Maschio' }, { value: 'F', label: 'Femmina' }]"
7902
8176
  * inline formControlName="gender" />
@@ -7911,13 +8185,19 @@ export declare class SirioRadioGroup<T = unknown> extends SirioControlBase<T> {
7911
8185
  /** Renders the options as Sirio selection chips (`sirio-chip-selection`), on one row. */
7912
8186
  readonly chips: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
7913
8187
  readonly compareWith: import("@angular/core").InputSignal<SirioCompareWith<T>>;
8188
+ /** nullable: label of the extra last option with value null. */
8189
+ readonly nullOptionLabel: import("@angular/core").InputSignal<string>;
8190
+ /** The extra option with value null, when `nullable` and the field is not required. */
8191
+ protected readonly nullOption: import("@angular/core").Signal<SirioOption<T | null> | null>;
8192
+ /** Options rendered: the bound options followed by the null option, if any. */
8193
+ protected readonly displayedOptions: import("@angular/core").Signal<SirioOption<T | null>[]>;
7914
8194
  /** valueSync compares values (and array items) with `compareWith`. */
7915
8195
  protected sameItem(a: unknown, b: unknown): boolean;
7916
8196
  /** Native radio "name": uses the name input or a generated unique one. */
7917
8197
  protected get groupName(): string;
7918
8198
  private readonly fallbackName;
7919
- protected isChecked(option: SirioOption<T>): boolean;
7920
- protected select(option: SirioOption<T>): void;
8199
+ protected isChecked(option: SirioOption<T | null>): boolean;
8200
+ protected select(option: SirioOption<T | null>): void;
7921
8201
  static ɵfac: i0.ɵɵFactoryDeclaration<SirioRadioGroup<any>, never>;
7922
8202
  static ɵcmp: i0.ɵɵComponentDeclaration<SirioRadioGroup<any>, "wm-sirio-radio-group", never, {
7923
8203
  "options": {
@@ -7940,6 +8220,11 @@ export declare class SirioRadioGroup<T = unknown> extends SirioControlBase<T> {
7940
8220
  "required": false;
7941
8221
  "isSignal": true;
7942
8222
  };
8223
+ "nullOptionLabel": {
8224
+ "alias": "nullOptionLabel";
8225
+ "required": false;
8226
+ "isSignal": true;
8227
+ };
7943
8228
  }, {}, ["optionLabel"], never, true, never>;
7944
8229
  }
7945
8230
  interface SelectItem<T> {
@@ -7992,6 +8277,9 @@ export declare const SIRIO_DEFAULT_SELECTION_SUMMARY: (count: number) => string;
7992
8277
  * valido") is shown. It runs again when the options change and ignores an empty options list
7993
8278
  * (options still loading).
7994
8279
  *
8280
+ * With no options (and `loading` false) the open list shows a single disabled row with `noDataText`
8281
+ * ("Nessun dato disponibile").
8282
+ *
7995
8283
  * Multiple choice extras: `selectAll` adds a "Seleziona tutto" row at the top of the list (it selects or
7996
8284
  * deselects all the enabled options shown, the search results when searching); `maxVisibleSelections`
7997
8285
  * shows "n elementi selezionati" (`selectionSummary`) instead of the labels when more options are selected.
@@ -8009,6 +8297,8 @@ export declare class SirioSelect<T = unknown> extends SirioControlBase<T | T[]>
8009
8297
  readonly searchMinLength: import("@angular/core").InputSignalWithTransform<number, unknown>;
8010
8298
  /** Text of the row shown when the search finds nothing. */
8011
8299
  readonly noResultsText: import("@angular/core").InputSignal<string>;
8300
+ /** Text of the row shown in the open list when there are no options (and they are not loading). */
8301
+ readonly noDataText: import("@angular/core").InputSignal<string>;
8012
8302
  /**
8013
8303
  * Options still loading (e.g. from a service): the list shows `loadingText` with the kit spinner,
8014
8304
  * the closed field shows it instead of the placeholder and a spinner, the combobox is aria-busy.
@@ -8095,6 +8385,8 @@ export declare class SirioSelect<T = unknown> extends SirioControlBase<T | T[]>
8095
8385
  protected onSearchFocus(event: FocusEvent): void;
8096
8386
  protected onSearch(event: Event): void;
8097
8387
  /** Reset button: clears the search and the selection, as the Sirio autocomplete reset. */
8388
+ /** nullable applies to the single select only (a multiple select is emptied by deselecting). */
8389
+ protected isNullValue(value: T | T[] | null): boolean;
8098
8390
  protected reset(): void;
8099
8391
  protected choose(index: number): void;
8100
8392
  private emitSelected;
@@ -8138,6 +8430,11 @@ export declare class SirioSelect<T = unknown> extends SirioControlBase<T | T[]>
8138
8430
  "required": false;
8139
8431
  "isSignal": true;
8140
8432
  };
8433
+ "noDataText": {
8434
+ "alias": "noDataText";
8435
+ "required": false;
8436
+ "isSignal": true;
8437
+ };
8141
8438
  "loading": {
8142
8439
  "alias": "loading";
8143
8440
  "required": false;
@@ -8734,6 +9031,415 @@ export declare class SirioFileUpload extends SirioControlBase<SirioFileItem[]> i
8734
9031
  "fileError": "fileError";
8735
9032
  }, never, never, true, never>;
8736
9033
  }
9034
+ /**
9035
+ * The subset of JSON Schema (draft-07) understood by wm-sirio-schema-form. Other keywords are
9036
+ * ignored; an empty schema (`{}`) accepts any JSON value.
9037
+ */
9038
+ export interface SirioJsonSchema {
9039
+ type?: string | string[];
9040
+ format?: string;
9041
+ title?: string;
9042
+ description?: string;
9043
+ enum?: unknown[];
9044
+ properties?: Record<string, SirioJsonSchema>;
9045
+ items?: SirioJsonSchema;
9046
+ required?: string[];
9047
+ pattern?: string;
9048
+ minimum?: number;
9049
+ maximum?: number;
9050
+ minLength?: number;
9051
+ maxLength?: number;
9052
+ minItems?: number;
9053
+ maxItems?: number;
9054
+ uniqueItems?: boolean;
9055
+ [keyword: string]: unknown;
9056
+ }
9057
+ /**
9058
+ * How a list is edited: `objects` in a grid (a row per item), `chips` for allowed values (multiple
9059
+ * choice), `tags` for texts and numbers typed one by one, `items` (a field per item) otherwise.
9060
+ */
9061
+ export type SirioSchemaListKind = 'objects' | 'chips' | 'tags' | 'items';
9062
+ /** One segment of a value path: a property name or an array index. */
9063
+ export type SirioSchemaPathSegment = string | number;
9064
+ /** A problem of a value against its schema, at a path like `figli[0].nome` ('' is the root). */
9065
+ export interface SirioSchemaError {
9066
+ path: string;
9067
+ message: string;
9068
+ }
9069
+ /** Errors by path (`figli[0].nome`), e.g. the ones returned by a server validation. */
9070
+ export type SirioSchemaErrors = Record<string, string>;
9071
+ /** The kind of editor used for a schema: one per JSON type, `json` for anything else. */
9072
+ export type SirioSchemaEditor = 'object' | 'array' | 'text' | 'number' | 'integer' | 'boolean' | 'enum' | 'date' | 'datetime' | 'time' | 'json';
9073
+ /** The path as text: `a.b[0].c`. */
9074
+ export declare function sirioSchemaPath(segments: readonly SirioSchemaPathSegment[]): string;
9075
+ /**
9076
+ * True when the schema admits null: a type list with `null` (`["string", "null"]`), the type `null`,
9077
+ * an enum with null, or no type at all.
9078
+ */
9079
+ export declare function sirioSchemaNullable(schema: SirioJsonSchema): boolean;
9080
+ /** The editor for a schema. */
9081
+ export declare function sirioSchemaEditor(schema: SirioJsonSchema): SirioSchemaEditor;
9082
+ /** How the list of the schema (an `array` with `items`) is edited. */
9083
+ export declare function sirioSchemaListKind(schema: SirioJsonSchema): SirioSchemaListKind;
9084
+ /** The problem of a list as a whole (`minItems`, `maxItems`, `uniqueItems`), or null. */
9085
+ export declare function sirioSchemaCheckList(schema: SirioJsonSchema, list: unknown): string | null;
9086
+ /** A short label of the type:`string`, `date`, `number`, `lista`, `valori ammessi`, `qualsiasi`... */
9087
+ export declare function sirioSchemaTypeLabel(schema: SirioJsonSchema): string;
9088
+ /** Every property of the schema with `null` (lists empty): the shape of the value, to fill in. */
9089
+ export declare function sirioSchemaSkeleton(schema: SirioJsonSchema): unknown;
9090
+ /** A plausible value for every property (lists with one item); a `pattern` is not followed. */
9091
+ export declare function sirioSchemaSample(schema: SirioJsonSchema, today?: Date): unknown;
9092
+ /** Adds the properties of the schema missing from the value (with `null`), keeping the others. */
9093
+ export declare function sirioSchemaComplete(schema: SirioJsonSchema, value: unknown): unknown;
9094
+ /** The paths of the value that the schema does not know (e.g. fields removed in a new version). */
9095
+ export declare function sirioSchemaUnknownPaths(schema: SirioJsonSchema, value: unknown): string[];
9096
+ /** The problem of a single (non object, non array) value, or null. `null` is accepted. */
9097
+ export declare function sirioSchemaCheck(schema: SirioJsonSchema, value: unknown): string | null;
9098
+ /** The problems of a value against the schema (missing properties are not problems). */
9099
+ export declare function sirioSchemaValidate(schema: SirioJsonSchema, value: unknown): SirioSchemaError[];
9100
+ /** The value at a path. */
9101
+ export declare function sirioSchemaGet(value: unknown, path: readonly SirioSchemaPathSegment[]): unknown;
9102
+ /**
9103
+ * A copy of the value with `item` at the path (`undefined` removes the property); the objects
9104
+ * left empty by a removal are removed too.
9105
+ */
9106
+ export declare function sirioSchemaSet(value: unknown, path: readonly SirioSchemaPathSegment[], item: unknown): unknown;
9107
+ /** The kinds of field of wm-sirio-schema-form (`json`: a value without type; `chips`: a list of allowed values). */
9108
+ export type SirioSchemaFieldKind = SirioSchemaEditor | 'chips';
9109
+ /**
9110
+ * What a field editor of its own receives (in the `field` input of a component, or as the
9111
+ * implicit value of a `wmSirioSchemaField` template). The form keeps the value: the editor only
9112
+ * reads and writes `control` (for `json` fields the text, read as JSON by the form).
9113
+ */
9114
+ export interface SirioSchemaFieldContext {
9115
+ /** The control of the field. */
9116
+ control: FormControl<unknown>;
9117
+ kind: SirioSchemaFieldKind;
9118
+ /** The part of the schema of this field. */
9119
+ schema: SirioJsonSchema;
9120
+ /** The property name (`nome`, `figli[0]` for a list item). */
9121
+ name: string;
9122
+ /** The path in the value (`figli[0].nome`). */
9123
+ path: string;
9124
+ /** Id for the input element: the label of the field points to it. */
9125
+ inputId: string;
9126
+ /** Ids of the help text and of the error message, for aria-describedby. */
9127
+ describedBy: string;
9128
+ /** Short field, without label and help (grid cell). */
9129
+ compact: boolean;
9130
+ readonly: boolean;
9131
+ disabled: boolean;
9132
+ }
9133
+ /** The components that edit the fields of a kind, in place of the Sirio control of the form. */
9134
+ export type SirioSchemaFieldEditors = Partial<Record<SirioSchemaFieldKind, Type<unknown>>>;
9135
+ /** The field editors of the application (see provideSirioSchemaFieldEditors). */
9136
+ export declare const SIRIO_SCHEMA_FIELD_EDITORS: InjectionToken<Partial<Record<SirioSchemaFieldKind, Type<unknown>>>>;
9137
+ /**
9138
+ * Field editors of their own for every wm-sirio-schema-form, by kind of field: each component
9139
+ * gets the SirioSchemaFieldContext in its `field` input. The label, the help text and the error
9140
+ * message stay the form's (Sirio field).
9141
+ *
9142
+ * ```ts
9143
+ * providers: [provideSirioSchemaFieldEditors({ json: MyJsonFieldComponent })]
9144
+ * ```
9145
+ */
9146
+ export declare function provideSirioSchemaFieldEditors(editors: SirioSchemaFieldEditors): Provider;
9147
+ /**
9148
+ * A field editor for one form, by kind of field (it wins over provideSirioSchemaFieldEditors):
9149
+ *
9150
+ * ```html
9151
+ * <wm-sirio-schema-form [schema]="schema" [(ngModel)]="value">
9152
+ * <ng-template wmSirioSchemaField="json" let-field>
9153
+ * <my-json-editor [formControl]="field.control" [attr.aria-describedby]="field.describedBy" />
9154
+ * </ng-template>
9155
+ * </wm-sirio-schema-form>
9156
+ * ```
9157
+ */
9158
+ export declare class SirioSchemaFieldTemplate {
9159
+ readonly kind: import("@angular/core").InputSignal<SirioSchemaFieldKind>;
9160
+ readonly template: TemplateRef<{
9161
+ $implicit: SirioSchemaFieldContext;
9162
+ }>;
9163
+ static ngTemplateContextGuard(_dir: SirioSchemaFieldTemplate, ctx: unknown): ctx is {
9164
+ $implicit: SirioSchemaFieldContext;
9165
+ };
9166
+ static ɵfac: i0.ɵɵFactoryDeclaration<SirioSchemaFieldTemplate, never>;
9167
+ static ɵdir: i0.ɵɵDirectiveDeclaration<SirioSchemaFieldTemplate, "ng-template[wmSirioSchemaField]", never, {
9168
+ "kind": {
9169
+ "alias": "wmSirioSchemaField";
9170
+ "required": true;
9171
+ "isSignal": true;
9172
+ };
9173
+ }, {}, never, never, true, never>;
9174
+ }
9175
+ interface SchemaNodeBase {
9176
+ /** Property name, or `name[i]` for a list item. */
9177
+ name: string;
9178
+ path: string;
9179
+ segments: SirioSchemaPathSegment[];
9180
+ schema: SirioJsonSchema;
9181
+ /** Nesting level of the groups: 0 for the properties of the root. */
9182
+ depth: number;
9183
+ }
9184
+ /** An object: a group that opens and closes, with its properties. */
9185
+ export interface SirioSchemaObjectNode extends SchemaNodeBase {
9186
+ kind: 'object';
9187
+ children: SirioSchemaNode[];
9188
+ }
9189
+ /**
9190
+ * A list. `objects`: a grid with a row per item (the simple properties in the cells, the others
9191
+ * in the row detail); `tags`: texts or numbers typed one by one; `items`: a field per item.
9192
+ * Lists of allowed values are fields (`chips` editor).
9193
+ */
9194
+ export interface SirioSchemaArrayNode extends SchemaNodeBase {
9195
+ kind: 'array';
9196
+ list: Exclude<SirioSchemaListKind, 'chips'>;
9197
+ items: SirioSchemaNode[];
9198
+ /** `objects`: the properties shown in the grid cells. */
9199
+ columns: string[];
9200
+ /** `objects`: some properties are not in the cells, so the rows open a detail with them. */
9201
+ hasDetail: boolean;
9202
+ }
9203
+ /** A field, edited by a Sirio control bound to its own FormControl. */
9204
+ export interface SirioSchemaFieldNode extends SchemaNodeBase {
9205
+ kind: 'field';
9206
+ editor: SirioSchemaEditor | 'chips';
9207
+ control: FormControl<unknown>;
9208
+ options: SirioOption<unknown>[];
9209
+ /** The schema admits null: the Sirio control is `nullable` (its "X" sets the property to null). */
9210
+ nullable: boolean;
9211
+ }
9212
+ export type SirioSchemaNode = SirioSchemaObjectNode | SirioSchemaArrayNode | SirioSchemaFieldNode;
9213
+ /** How many fields of the form have a value. */
9214
+ export interface SirioSchemaFormSummary {
9215
+ filled: number;
9216
+ total: number;
9217
+ }
9218
+ /**
9219
+ * Form generated from a JSON Schema (draft-07 subset, see `SirioJsonSchema`): one Sirio control per
9220
+ * property (textbox, number, date, datetime, time, select for `enum`, Sì/No/null for booleans,
9221
+ * JSON textarea for untyped values).
9222
+ *
9223
+ * Objects are groups that open and close (`expandDepth`, `expandAll()`, `collapseAll()`): the
9224
+ * header shows how many fields are filled, the state (not passed, `null`, `{ }`) and the errors,
9225
+ * and a menu fills the group with sample values or empty fields, sets it to `null`, removes it
9226
+ * or copies its JSON. Lists of objects are grids (simple properties in the cells, the others in
9227
+ * the row detail) with duplicate / move / remove per row; lists of allowed values are selection
9228
+ * chips; lists of texts or numbers are tags typed one by one. `minItems`, `maxItems` and
9229
+ * `uniqueItems` are checked.
9230
+ *
9231
+ * The model is the JSON value. A property is in the value only when it has one: an empty field,
9232
+ * or one cleared with its ✕ button, is not passed (that is different from `null`).
9233
+ *
9234
+ * Validation: each field checks its schema; `errors` adds errors from outside (e.g. a server
9235
+ * validation) by path (`figli[0].nome`), shown on the field, group or list until it is changed;
9236
+ * the groups with errors open. Errors on unknown paths are listed above the form. As a validator
9237
+ * the form returns `{ sirioSchema: SirioSchemaError[] }`.
9238
+ *
9239
+ * The control of a kind of field can be replaced by an editor of its own (e.g. a JSON editor for
9240
+ * the `json` fields), for the whole application with `provideSirioSchemaFieldEditors` or for one
9241
+ * form with `<ng-template wmSirioSchemaField="json" let-field>`: it gets the
9242
+ * SirioSchemaFieldContext, while label, help and message stay the form's.
9243
+ *
9244
+ * ```html
9245
+ * <wm-sirio-schema-form [schema]="schema" [errors]="serverErrors" [(ngModel)]="input" />
9246
+ * ```
9247
+ */
9248
+ export declare class SirioSchemaForm extends SirioControlBase<unknown> implements Validator {
9249
+ /** The JSON Schema of the value. */
9250
+ readonly schema: import("@angular/core").InputSignal<SirioJsonSchema>;
9251
+ /** Errors from outside by path (`figli[0].nome`; '' is the whole value). */
9252
+ readonly errors: import("@angular/core").InputSignal<SirioSchemaErrors | null>;
9253
+ /** Shows the type (and the description) of each field below it. */
9254
+ readonly showTypes: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
9255
+ /** Groups open at the start: those up to this nesting level (0 = all closed). */
9256
+ readonly expandDepth: import("@angular/core").InputSignalWithTransform<number, unknown>;
9257
+ /** Properties of a list item shown in the grid cells (the others are in the row detail). */
9258
+ readonly maxColumns: import("@angular/core").InputSignalWithTransform<number, unknown>;
9259
+ readonly clearLabel: import("@angular/core").InputSignal<string>;
9260
+ readonly addLabel: import("@angular/core").InputSignal<string>;
9261
+ readonly removeLabel: import("@angular/core").InputSignal<string>;
9262
+ readonly emptyListText: import("@angular/core").InputSignal<string>;
9263
+ readonly tagPlaceholder: import("@angular/core").InputSignal<string>;
9264
+ private readonly host;
9265
+ private readonly renderInjector;
9266
+ /** The fields' FormControls by path, with the subscription to their changes. */
9267
+ private readonly fields;
9268
+ private fieldsSchema;
9269
+ /** The text being typed in the tag lists, by path. */
9270
+ private readonly drafts;
9271
+ /** Changes when fields are dropped to be created again (e.g. items moved): the tree is built anew. */
9272
+ private readonly rebuild;
9273
+ /** Errors from `errors` still shown: an error goes away when its field, group or list changes. */
9274
+ private readonly pendingErrors;
9275
+ /** Groups opened or closed by the user (the others follow `expandDepth`). */
9276
+ private readonly openGroups;
9277
+ /** Grid rows with the detail open, by item path. */
9278
+ protected readonly expandedRows: import("@angular/core").WritableSignal<Record<string, boolean>>;
9279
+ protected readonly messages: SirioErrorMessages;
9280
+ /** The application's field editors (provideSirioSchemaFieldEditors). */
9281
+ private readonly fieldEditors;
9282
+ /** The field editors of this form (`<ng-template wmSirioSchemaField="json">`): they win. */
9283
+ private readonly fieldTemplates;
9284
+ /** Changes with the state of the fields' controls (value, validity, touched): their errors are shown again. */
9285
+ private readonly fieldState;
9286
+ private readonly fieldIds;
9287
+ /** The editor of its own for the kind of a field, if any. */
9288
+ protected customEditor(node: SirioSchemaFieldNode): {
9289
+ template?: TemplateRef<unknown>;
9290
+ component?: Type<unknown>;
9291
+ } | null;
9292
+ /** The ids of a field (input, help, error): stable for its path. */
9293
+ protected fieldId(node: SirioSchemaFieldNode): string;
9294
+ private readonly contexts;
9295
+ /** What an editor of its own gets: the same object while the field and its state do not change. */
9296
+ protected fieldContext(node: SirioSchemaFieldNode, compact: boolean): SirioSchemaFieldContext;
9297
+ /** The message of a field with an editor of its own: shown once it was touched or changed. */
9298
+ protected customError(node: SirioSchemaFieldNode): string | null;
9299
+ private onValidatorChange;
9300
+ constructor();
9301
+ /** The lengths of the lists in the value: the tree changes only with them (and the schema). */
9302
+ private readonly shape;
9303
+ /** The nodes of the form (the properties of the root object). */
9304
+ protected readonly tree: import("@angular/core").Signal<SirioSchemaNode[]>;
9305
+ /** Every node by path. */
9306
+ private readonly nodes;
9307
+ private readonly fieldNodes;
9308
+ /** Filled and total fields (an empty list counts as one empty field). */
9309
+ readonly summary: import("@angular/core").Signal<SirioSchemaFormSummary>;
9310
+ /** The paths with an error: from `errors` (until changed) and from the schema. */
9311
+ private readonly errorPaths;
9312
+ /** The external errors that are not on a field, group or list (e.g. on an unknown property). */
9313
+ protected readonly otherErrors: import("@angular/core").Signal<SirioSchemaError[]>;
9314
+ private node;
9315
+ private field;
9316
+ private dropFields;
9317
+ /** Forgets the external errors of a path and of what it contains (its items, its fields). */
9318
+ private forgetError;
9319
+ /** The external error of a path, or the first one of its items (`[1]: ...`). */
9320
+ private itemsError;
9321
+ private count;
9322
+ /**
9323
+ * The value of the JSON as the control's model. Not passed is an empty control (null), except for
9324
+ * a boolean that admits null: undefined, so that no option is checked (null checks "null").
9325
+ */
9326
+ private toField;
9327
+ /**
9328
+ * The control's model as the value of the JSON (`undefined`: not passed). An empty control is
9329
+ * null when the schema admits it (`nullable` controls: the "X" or an emptied text), not passed
9330
+ * otherwise.
9331
+ */
9332
+ private fromField;
9333
+ private sameField;
9334
+ private validateField;
9335
+ protected isOpen(node: SirioSchemaNode): boolean;
9336
+ protected setOpen(path: string, open: boolean): void;
9337
+ /** Opens every group and list. */
9338
+ expandAll(): void;
9339
+ /** Closes every group and list. */
9340
+ collapseAll(): void;
9341
+ private setAllGroups;
9342
+ /** Opens the groups and the grid rows that contain the paths. */
9343
+ private reveal;
9344
+ /** `n di m compilati` for an object, `n elementi` for a list. */
9345
+ protected groupSummary(node: SirioSchemaObjectNode | SirioSchemaArrayNode): string;
9346
+ /** The state of a group when it has no fields to show: not passed, `null`, `{ }`, `[ ]`. */
9347
+ protected stateLabel(node: SirioSchemaNode): string;
9348
+ protected errorCount(path: string): number;
9349
+ /** The error of the group or list itself (from `errors`, or `minItems` / `maxItems` / `uniqueItems`). */
9350
+ protected groupError(node: SirioSchemaNode): string | null;
9351
+ /** The menu of a group, kept while the group and its state do not change. */
9352
+ private readonly menus;
9353
+ protected menu(path: string): SirioDropdownItem[];
9354
+ protected onGroupAction(node: SirioSchemaObjectNode | SirioSchemaArrayNode, action: unknown): void;
9355
+ /** Replaces the value of a group or list (its fields are created again). */
9356
+ private replace;
9357
+ protected addItem(node: SirioSchemaArrayNode): void;
9358
+ protected removeItem(node: SirioSchemaArrayNode, index: number): void;
9359
+ protected onRowAction(node: SirioSchemaArrayNode, item: SirioSchemaNode, action: unknown): void;
9360
+ /** A new list: the items move, so their fields and open rows start again. */
9361
+ private replaceList;
9362
+ private listOf;
9363
+ protected setExpandedRows(expanded: SirioGridExpanded): void;
9364
+ /** The properties of a list item not shown in the grid cells. */
9365
+ protected detailNodes(list: SirioSchemaArrayNode, item: SirioSchemaNode): SirioSchemaNode[];
9366
+ protected cellNode(item: SirioSchemaNode, column: string): SirioSchemaNode | null;
9367
+ /** The width of a grid column, enough for its editor. */
9368
+ protected columnWidth(node: SirioSchemaArrayNode, column: string): string;
9369
+ protected readonly noDetail: () => boolean;
9370
+ protected readonly rowClass: (item: SirioSchemaNode) => "" | "wm-schema-row-invalid";
9371
+ protected draft(node: SirioSchemaArrayNode): FormControl<string | null>;
9372
+ protected tags(node: SirioSchemaArrayNode): unknown[];
9373
+ protected isRepeated(node: SirioSchemaArrayNode, index: number): boolean;
9374
+ protected addTag(node: SirioSchemaArrayNode, event: Event): void;
9375
+ /** Backspace in the empty field removes the last tag. */
9376
+ protected removeLastTag(node: SirioSchemaArrayNode): void;
9377
+ protected tagsHint(node: SirioSchemaArrayNode): string;
9378
+ protected isSet(node: SirioSchemaNode): boolean;
9379
+ /** Below the field: the type, `null` when the value is null, the description. */
9380
+ protected hint(node: SirioSchemaFieldNode): string;
9381
+ protected clear(node: SirioSchemaNode): void;
9382
+ protected index(node: SirioSchemaNode): number;
9383
+ /** Brings the field at the path (or its closest group) into view and focuses it. */
9384
+ focusPath(path: string): void;
9385
+ protected fromModel(value: unknown): unknown;
9386
+ protected hasValue(value: unknown): boolean;
9387
+ validate(control: AbstractControl): ValidationErrors | null;
9388
+ registerOnValidatorChange(fn: () => void): void;
9389
+ static ɵfac: i0.ɵɵFactoryDeclaration<SirioSchemaForm, never>;
9390
+ static ɵcmp: i0.ɵɵComponentDeclaration<SirioSchemaForm, "wm-sirio-schema-form", never, {
9391
+ "schema": {
9392
+ "alias": "schema";
9393
+ "required": true;
9394
+ "isSignal": true;
9395
+ };
9396
+ "errors": {
9397
+ "alias": "errors";
9398
+ "required": false;
9399
+ "isSignal": true;
9400
+ };
9401
+ "showTypes": {
9402
+ "alias": "showTypes";
9403
+ "required": false;
9404
+ "isSignal": true;
9405
+ };
9406
+ "expandDepth": {
9407
+ "alias": "expandDepth";
9408
+ "required": false;
9409
+ "isSignal": true;
9410
+ };
9411
+ "maxColumns": {
9412
+ "alias": "maxColumns";
9413
+ "required": false;
9414
+ "isSignal": true;
9415
+ };
9416
+ "clearLabel": {
9417
+ "alias": "clearLabel";
9418
+ "required": false;
9419
+ "isSignal": true;
9420
+ };
9421
+ "addLabel": {
9422
+ "alias": "addLabel";
9423
+ "required": false;
9424
+ "isSignal": true;
9425
+ };
9426
+ "removeLabel": {
9427
+ "alias": "removeLabel";
9428
+ "required": false;
9429
+ "isSignal": true;
9430
+ };
9431
+ "emptyListText": {
9432
+ "alias": "emptyListText";
9433
+ "required": false;
9434
+ "isSignal": true;
9435
+ };
9436
+ "tagPlaceholder": {
9437
+ "alias": "tagPlaceholder";
9438
+ "required": false;
9439
+ "isSignal": true;
9440
+ };
9441
+ }, {}, ["fieldTemplates"], never, true, never>;
9442
+ }
8737
9443
  /** All Sirio data-entry controls, buttons and helper directives, for `imports: [SIRIO_FORM_CONTROLS]`. */
8738
- export declare const SIRIO_FORM_CONTROLS: readonly [typeof SirioTextbox, typeof SirioTextarea, typeof SirioNumber, typeof SirioDate, typeof SirioTime, typeof SirioDateTime, typeof SirioCheckbox, typeof SirioChecklist, typeof SirioRadioGroup, typeof SirioSelect, typeof SirioAutocomplete, typeof SirioSearchbar, typeof SirioSlider, typeof SirioFileUpload, typeof SirioButton, typeof SirioPrefix, typeof SirioSuffix, typeof SirioOptionLabel];
9444
+ export declare const SIRIO_FORM_CONTROLS: readonly [typeof SirioTextbox, typeof SirioTextarea, typeof SirioNumber, typeof SirioDate, typeof SirioTime, typeof SirioDateTime, typeof SirioCheckbox, typeof SirioChecklist, typeof SirioRadioGroup, typeof SirioSelect, typeof SirioAutocomplete, typeof SirioSearchbar, typeof SirioSlider, typeof SirioFileUpload, typeof SirioSchemaForm, typeof SirioSchemaFieldTemplate, typeof SirioButton, typeof SirioPrefix, typeof SirioSuffix, typeof SirioOptionLabel];
8739
9445
  export {};