@wiltech-labs/ngx-forms 0.1.0 → 1.0.1
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 +120 -65
- package/fesm2022/wiltech-labs-ngx-forms.mjs +323 -84
- package/fesm2022/wiltech-labs-ngx-forms.mjs.map +1 -1
- package/package.json +2 -1
- package/types/wiltech-labs-ngx-forms.d.ts +84 -13
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
|
-
import { InputSignal, WritableSignal } from "@angular/core";
|
|
2
|
+
import { InjectionToken, InputSignal, WritableSignal } from "@angular/core";
|
|
3
3
|
import { FieldTree, Schema } from "@angular/forms/signals";
|
|
4
|
+
import { MatChipInputEvent } from "@angular/material/chips";
|
|
4
5
|
export declare enum FormFieldType {
|
|
5
6
|
TEXT = "text",
|
|
6
7
|
EMAIL = "email",
|
|
@@ -11,6 +12,7 @@ export declare enum FormFieldType {
|
|
|
11
12
|
NUMBER = "number",
|
|
12
13
|
RANGE = "range",
|
|
13
14
|
SELECT = "select",
|
|
15
|
+
CHIPS = "chips",
|
|
14
16
|
TEXTAREA = "textarea",
|
|
15
17
|
CODE = "code",
|
|
16
18
|
BUSINESS_DATE = "business-date",
|
|
@@ -67,16 +69,24 @@ interface SchemaConfig<T extends BaseSchema> {
|
|
|
67
69
|
fields: FieldDef[];
|
|
68
70
|
initialValue: T;
|
|
69
71
|
}
|
|
70
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* Renders one Material field component per FieldDef, then right-aligned actions: a text
|
|
74
|
+
* secondary action ("Clear" by default — label it "Cancel" when it leaves the form) and the filled
|
|
75
|
+
* primary one ("Save"). Name both after what they do.
|
|
76
|
+
*/
|
|
71
77
|
export declare class DynamicForm<T extends BaseSchema = BaseSchema> {
|
|
72
78
|
metaInfo: InputSignal<FieldDef[]>;
|
|
73
79
|
dynamicForm: InputSignal<FieldTree<T>>;
|
|
80
|
+
/** Filled primary action. */
|
|
81
|
+
readonly submitLabel: InputSignal<string>;
|
|
82
|
+
/** Text secondary action; emits `onFormClear`. */
|
|
83
|
+
readonly clearLabel: InputSignal<string>;
|
|
74
84
|
onFormSubmit: import("@angular/core").OutputEmitterRef<void>;
|
|
75
85
|
onFormClear: import("@angular/core").OutputEmitterRef<void>;
|
|
76
86
|
protected handleSubmit(): void;
|
|
77
87
|
protected clearForm(): void;
|
|
78
88
|
static ɵfac: i0.ɵɵFactoryDeclaration<DynamicForm<any>, never>;
|
|
79
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<DynamicForm<any>, "
|
|
89
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<DynamicForm<any>, "ngx-dynamic-form", never, {
|
|
80
90
|
"metaInfo": {
|
|
81
91
|
"alias": "metaInfo";
|
|
82
92
|
"required": true;
|
|
@@ -87,6 +97,16 @@ export declare class DynamicForm<T extends BaseSchema = BaseSchema> {
|
|
|
87
97
|
"required": true;
|
|
88
98
|
"isSignal": true;
|
|
89
99
|
};
|
|
100
|
+
"submitLabel": {
|
|
101
|
+
"alias": "submitLabel";
|
|
102
|
+
"required": false;
|
|
103
|
+
"isSignal": true;
|
|
104
|
+
};
|
|
105
|
+
"clearLabel": {
|
|
106
|
+
"alias": "clearLabel";
|
|
107
|
+
"required": false;
|
|
108
|
+
"isSignal": true;
|
|
109
|
+
};
|
|
90
110
|
}, {
|
|
91
111
|
"onFormSubmit": "onFormSubmit";
|
|
92
112
|
"onFormClear": "onFormClear";
|
|
@@ -102,7 +122,7 @@ export declare class TextField {
|
|
|
102
122
|
readonly field: import("@angular/core").InputSignal<FieldTree<string> | FieldTree<number>>;
|
|
103
123
|
protected readonly formField: import("@angular/core").Signal<FieldTree<string>>;
|
|
104
124
|
static ɵfac: i0.ɵɵFactoryDeclaration<TextField, never>;
|
|
105
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<TextField, "
|
|
125
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<TextField, "ngx-text-field", never, {
|
|
106
126
|
"fieldDef": {
|
|
107
127
|
"alias": "fieldDef";
|
|
108
128
|
"required": true;
|
|
@@ -125,7 +145,7 @@ export declare class TextareaField {
|
|
|
125
145
|
protected readonly isCode: import("@angular/core").Signal<boolean>;
|
|
126
146
|
protected onKeydown(event: KeyboardEvent): void;
|
|
127
147
|
static ɵfac: i0.ɵɵFactoryDeclaration<TextareaField, never>;
|
|
128
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<TextareaField, "
|
|
148
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<TextareaField, "ngx-textarea-field", never, {
|
|
129
149
|
"fieldDef": {
|
|
130
150
|
"alias": "fieldDef";
|
|
131
151
|
"required": true;
|
|
@@ -143,7 +163,7 @@ export declare class CheckboxField {
|
|
|
143
163
|
readonly fieldDef: import("@angular/core").InputSignal<FieldDef>;
|
|
144
164
|
readonly field: import("@angular/core").InputSignal<FieldTree<boolean>>;
|
|
145
165
|
static ɵfac: i0.ɵɵFactoryDeclaration<CheckboxField, never>;
|
|
146
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<CheckboxField, "
|
|
166
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<CheckboxField, "ngx-checkbox-field", never, {
|
|
147
167
|
"fieldDef": {
|
|
148
168
|
"alias": "fieldDef";
|
|
149
169
|
"required": true;
|
|
@@ -162,7 +182,7 @@ export declare class RadioField {
|
|
|
162
182
|
readonly field: import("@angular/core").InputSignal<FieldTree<string | number | boolean>>;
|
|
163
183
|
protected readonly labelId: string;
|
|
164
184
|
static ɵfac: i0.ɵɵFactoryDeclaration<RadioField, never>;
|
|
165
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<RadioField, "
|
|
185
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<RadioField, "ngx-radio-field", never, {
|
|
166
186
|
"fieldDef": {
|
|
167
187
|
"alias": "fieldDef";
|
|
168
188
|
"required": true;
|
|
@@ -180,7 +200,34 @@ export declare class SelectField {
|
|
|
180
200
|
readonly fieldDef: import("@angular/core").InputSignal<FieldDef>;
|
|
181
201
|
readonly field: import("@angular/core").InputSignal<FieldTree<string | number | boolean>>;
|
|
182
202
|
static ɵfac: i0.ɵɵFactoryDeclaration<SelectField, never>;
|
|
183
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<SelectField, "
|
|
203
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SelectField, "ngx-select-field", never, {
|
|
204
|
+
"fieldDef": {
|
|
205
|
+
"alias": "fieldDef";
|
|
206
|
+
"required": true;
|
|
207
|
+
"isSignal": true;
|
|
208
|
+
};
|
|
209
|
+
"field": {
|
|
210
|
+
"alias": "field";
|
|
211
|
+
"required": true;
|
|
212
|
+
"isSignal": true;
|
|
213
|
+
};
|
|
214
|
+
}, {}, never, never, true, never>;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Material chip grid for the chips field type: a free-text list of tokens (Eg keywords), typed one
|
|
218
|
+
* at a time and removable individually. Driven by hand (`state().value.update(...)`), same as the
|
|
219
|
+
* date/time fields — `[formField]` targets a single control's value, not a token-by-token list.
|
|
220
|
+
*/
|
|
221
|
+
export declare class ChipsField {
|
|
222
|
+
readonly fieldDef: import("@angular/core").InputSignal<FieldDef>;
|
|
223
|
+
readonly field: import("@angular/core").InputSignal<FieldTree<string[]>>;
|
|
224
|
+
private readonly announcer;
|
|
225
|
+
protected readonly state: import("@angular/core").Signal<import("@angular/forms/signals").FieldState<string[], string | number>>;
|
|
226
|
+
protected readonly chips: import("@angular/core").Signal<string[]>;
|
|
227
|
+
protected addChip(event: MatChipInputEvent): void;
|
|
228
|
+
protected removeChip(chip: string): void;
|
|
229
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ChipsField, never>;
|
|
230
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ChipsField, "ngx-chips-field", never, {
|
|
184
231
|
"fieldDef": {
|
|
185
232
|
"alias": "fieldDef";
|
|
186
233
|
"required": true;
|
|
@@ -199,7 +246,7 @@ export declare class SliderField {
|
|
|
199
246
|
readonly field: import("@angular/core").InputSignal<FieldTree<number>>;
|
|
200
247
|
protected readonly labelId: string;
|
|
201
248
|
static ɵfac: i0.ɵɵFactoryDeclaration<SliderField, never>;
|
|
202
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<SliderField, "
|
|
249
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<SliderField, "ngx-slider-field", never, {
|
|
203
250
|
"fieldDef": {
|
|
204
251
|
"alias": "fieldDef";
|
|
205
252
|
"required": true;
|
|
@@ -220,6 +267,7 @@ export declare class BusinessDateField {
|
|
|
220
267
|
readonly fieldDef: import("@angular/core").InputSignal<FieldDef>;
|
|
221
268
|
readonly field: import("@angular/core").InputSignal<FieldTree<string | null>>;
|
|
222
269
|
private readonly dateAdapter;
|
|
270
|
+
private readonly resolveLocale;
|
|
223
271
|
protected readonly state: import("@angular/core").Signal<import("@angular/forms/signals").FieldState<string | null, string | number>>;
|
|
224
272
|
protected readonly date: import("@angular/core").Signal<Date | null>;
|
|
225
273
|
protected readonly minDate: import("@angular/core").Signal<Date | null>;
|
|
@@ -228,7 +276,7 @@ export declare class BusinessDateField {
|
|
|
228
276
|
constructor();
|
|
229
277
|
protected onDateChange(date: Date | null): void;
|
|
230
278
|
static ɵfac: i0.ɵɵFactoryDeclaration<BusinessDateField, never>;
|
|
231
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<BusinessDateField, "
|
|
279
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BusinessDateField, "ngx-business-date-field", never, {
|
|
232
280
|
"fieldDef": {
|
|
233
281
|
"alias": "fieldDef";
|
|
234
282
|
"required": true;
|
|
@@ -249,6 +297,7 @@ export declare class BusinessTimeField {
|
|
|
249
297
|
readonly fieldDef: import("@angular/core").InputSignal<FieldDef>;
|
|
250
298
|
readonly field: import("@angular/core").InputSignal<FieldTree<string | null>>;
|
|
251
299
|
private readonly dateAdapter;
|
|
300
|
+
private readonly resolveLocale;
|
|
252
301
|
protected readonly state: import("@angular/core").Signal<import("@angular/forms/signals").FieldState<string | null, string | number>>;
|
|
253
302
|
protected readonly time: import("@angular/core").Signal<Date | null>;
|
|
254
303
|
protected readonly minTime: import("@angular/core").Signal<Date | null>;
|
|
@@ -257,7 +306,7 @@ export declare class BusinessTimeField {
|
|
|
257
306
|
constructor();
|
|
258
307
|
protected onTimeChange(time: Date | null): void;
|
|
259
308
|
static ɵfac: i0.ɵɵFactoryDeclaration<BusinessTimeField, never>;
|
|
260
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<BusinessTimeField, "
|
|
309
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BusinessTimeField, "ngx-business-time-field", never, {
|
|
261
310
|
"fieldDef": {
|
|
262
311
|
"alias": "fieldDef";
|
|
263
312
|
"required": true;
|
|
@@ -280,6 +329,7 @@ export declare class InstantDateTimeField {
|
|
|
280
329
|
readonly field: import("@angular/core").InputSignal<FieldTree<string | null>>;
|
|
281
330
|
private readonly zonedDateTime;
|
|
282
331
|
private readonly dateAdapter;
|
|
332
|
+
private readonly resolveLocale;
|
|
283
333
|
/** Explains how a DST gap or overlap was resolved for the last value picked by the user. */
|
|
284
334
|
protected readonly notice: WritableSignal<string | null>;
|
|
285
335
|
protected readonly state: import("@angular/core").Signal<import("@angular/forms/signals").FieldState<string | null, string | number>>;
|
|
@@ -297,7 +347,7 @@ export declare class InstantDateTimeField {
|
|
|
297
347
|
protected onTimeChange(time: Date | null): void;
|
|
298
348
|
private commit;
|
|
299
349
|
static ɵfac: i0.ɵɵFactoryDeclaration<InstantDateTimeField, never>;
|
|
300
|
-
static ɵcmp: i0.ɵɵComponentDeclaration<InstantDateTimeField, "
|
|
350
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<InstantDateTimeField, "ngx-instant-date-time-field", never, {
|
|
301
351
|
"fieldDef": {
|
|
302
352
|
"alias": "fieldDef";
|
|
303
353
|
"required": true;
|
|
@@ -346,6 +396,8 @@ export declare class FormConfigBuilder<T extends BaseSchema> {
|
|
|
346
396
|
range(name: FieldName<T>, label: string, options?: FieldOptions): this;
|
|
347
397
|
radio(name: FieldName<T>, label: string, choices: FieldOption[], options?: FieldOptions): this;
|
|
348
398
|
select(name: FieldName<T>, label: string, choices: FieldOption[], options?: FieldOptions): this;
|
|
399
|
+
/** Freeform list of tokens (Eg keywords), typed one at a time. */
|
|
400
|
+
chips(name: FieldName<T>, label: string, options?: FieldOptions): this;
|
|
349
401
|
/** Calendar date with no timezone, stored as 'YYYY-MM-DD'. */
|
|
350
402
|
businessDate(name: FieldName<T>, label: string, options?: DateTimeFieldOptions): this;
|
|
351
403
|
/** Time of day with no timezone, stored as 'HH:mm'. */
|
|
@@ -362,6 +414,25 @@ export declare class FormConfigBuilder<T extends BaseSchema> {
|
|
|
362
414
|
}
|
|
363
415
|
/** Starts a FormConfigBuilder for schema `T`. */
|
|
364
416
|
export declare function formConfig<T extends BaseSchema>(schemaType: T['schemaType']): FormConfigBuilder<T>;
|
|
417
|
+
/** A plain function the app supplies, read fresh on every call — see `NGX_FORMS_LOCALE`. */
|
|
418
|
+
type FormsLocaleResolver = () => string;
|
|
419
|
+
/**
|
|
420
|
+
* Which locale a date/time field's picker displays and parses in, when its own `FieldDef`
|
|
421
|
+
* doesn't set `dateTimeConfig.locale` — an explicit per-field `locale` always wins over this.
|
|
422
|
+
* Defaults to `DEFAULT_DATE_TIME_LOCALE` ('en-GB'), same as before this token existed, not the
|
|
423
|
+
* browser's own language: unlike `ngx-dates`' `NGX_DATES_LOCALE` (read-only display text), this
|
|
424
|
+
* locale also decides which *typed* day/month order `LocaleDateAdapter.parse()` accepts, so
|
|
425
|
+
* switching it changes user input behaviour, not just wording — an app opts in deliberately:
|
|
426
|
+
*
|
|
427
|
+
* ```ts
|
|
428
|
+
* { provide: NGX_FORMS_LOCALE, useFactory: () => { const translations = inject(TranslationsService); return () => translations.locale(); } }
|
|
429
|
+
* ```
|
|
430
|
+
*
|
|
431
|
+
* A plain function rather than a direct import of `ngx-translations`' `TranslationsService`, so this package
|
|
432
|
+
* stays buildable and publishable on its own — same reasoning as `ngx-dates`' `NGX_DATES_LOCALE`
|
|
433
|
+
* (see root `CLAUDE.md`'s "Inter-package deps").
|
|
434
|
+
*/
|
|
435
|
+
export declare const NGX_FORMS_LOCALE: InjectionToken<FormsLocaleResolver>;
|
|
365
436
|
interface ZonedInstantResult {
|
|
366
437
|
instant: string;
|
|
367
438
|
notice: string | null;
|
|
@@ -387,4 +458,4 @@ export declare function defineSchema<T extends BaseSchema>(config: SchemaConfig<
|
|
|
387
458
|
export declare function createEmptyEntity<T extends BaseSchema>(schemaType: T['schemaType'], defaults: Omit<T, 'id' | 'schemaType'>): T;
|
|
388
459
|
/** Turns field definitions into Signals Forms rules. The model can be any object, not just a BaseSchema. */
|
|
389
460
|
export declare function toSchema<T>(meta: FieldDef[]): Schema<T>;
|
|
390
|
-
export type { BaseSchema, DateTimeConfig, DateTimeDisambiguation, DateTimeFieldOptions, FieldDef, FieldName, FieldOption, FieldOptions, SchemaConfig, ZonedInstantResult };
|
|
461
|
+
export type { BaseSchema, DateTimeConfig, DateTimeDisambiguation, DateTimeFieldOptions, FieldDef, FieldName, FieldOption, FieldOptions, FormsLocaleResolver, SchemaConfig, ZonedInstantResult };
|