@a.nemreen/dga-dynamic-form 0.1.0 → 0.1.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.
Files changed (2) hide show
  1. package/README.md +197 -27
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -14,8 +14,6 @@ npm install @a.nemreen/dga-dynamic-form @a.nemreen/dga-ui @a.nemreen/dga-tokens
14
14
 
15
15
  ## Setup
16
16
 
17
- Provide adapters once in `app.config.ts`:
18
-
19
17
  ```ts
20
18
  import { provideHttpClient } from '@angular/common/http';
21
19
  import { provideDgaDynamicForm } from '@a.nemreen/dga-dynamic-form';
@@ -23,25 +21,24 @@ import { provideDgaDynamicForm } from '@a.nemreen/dga-dynamic-form';
23
21
  export const appConfig = {
24
22
  providers: [
25
23
  provideHttpClient(),
26
- provideDgaDynamicForm({ httpSubmit: true, dgaToast: true }),
24
+ provideDgaDynamicForm({ httpSubmit: true, httpLookup: true, dgaToast: true }),
27
25
  ],
28
26
  };
29
27
  ```
30
28
 
31
- Ensure Tailwind scans the package:
32
-
33
29
  ```css
34
30
  @source "../node_modules/@a.nemreen/dga-dynamic-form/**/*.{mjs,js}";
35
31
  @source "../node_modules/@a.nemreen/dga-ui/**/*.{mjs,js}";
36
32
  ```
37
33
 
38
- ## Usage
34
+ ## Quick usage
39
35
 
40
36
  ```ts
41
37
  import { DgaDynamicForm, type DgaDynamicFormConfig } from '@a.nemreen/dga-dynamic-form';
42
38
 
43
39
  readonly config: DgaDynamicFormConfig = {
44
- emitOnly: true,
40
+ endpoint: 'https://api.example.com/contact',
41
+ method: 'POST',
45
42
  submitButtonLabel: { en: 'Send', ar: 'إرسال' },
46
43
  fields: [
47
44
  {
@@ -51,13 +48,6 @@ readonly config: DgaDynamicFormConfig = {
51
48
  required: true,
52
49
  columns: { md: 6 },
53
50
  },
54
- {
55
- name: 'email',
56
- type: 'email',
57
- label: { en: 'Email', ar: 'البريد' },
58
- required: true,
59
- columns: { md: 6 },
60
- },
61
51
  ],
62
52
  };
63
53
  ```
@@ -66,20 +56,204 @@ readonly config: DgaDynamicFormConfig = {
66
56
  <dga-dynamic-form [config]="config" (formSubmitted)="onSubmit($event)" />
67
57
  ```
68
58
 
69
- ## Adapters
59
+ ---
60
+
61
+ ## Config reference (`DgaDynamicFormConfig`)
62
+
63
+ Passed as `[config]` on `<dga-dynamic-form>`.
64
+
65
+ | Key | Type | Default | Description |
66
+ |-----|------|---------|-------------|
67
+ | `endpoint` | `string?` | — | Submit URL. Omit (or use `emitOnly`) to only emit `formSubmitted`. |
68
+ | `method` | `'GET' \| 'POST' \| 'PUT' \| 'PATCH' \| 'DELETE'` | `'POST'` | HTTP method for the submit adapter. |
69
+ | `emitOnly` | `boolean?` | `false` | Skip HTTP; emit the payload on `formSubmitted`. |
70
+ | `fields` | `DgaFormField[]` | **required** | Field list. Can be `[]` when using `wizard.steps` only. |
71
+ | `description` | `DgaFormLabel?` | — | Bilingual text above the form. |
72
+ | `submitButtonLabel` | `DgaFormLabel?` | Submit / إرسال | Primary button label. |
73
+ | `clearButtonLabel` | `DgaFormLabel?` | — | Shows Clear when set. |
74
+ | `saveButtonLabel` | `DgaFormLabel?` | — | Draft save button label. |
75
+ | `successMessage` | `DgaFormLabel?` | — | Toast on success. |
76
+ | `errorMessage` | `DgaFormLabel?` | — | Toast on failure. |
77
+ | `fieldMapping` | `Record<string, string>?` | — | Rename field keys in the submit payload. |
78
+ | `payloadTransformer` | `(data) => object \| FormData` | — | Final reshape before submit. |
79
+ | `formId` | `string?` | — | localStorage namespace for drafts. |
80
+ | `enableLocalStorageSave` | `boolean?` | `false` | Enable Save draft + restore on init. |
81
+ | `idempotencyKey` | `string?` | — | Sent as `Idempotency-Key` header. |
82
+ | `wizard` | `DgaWizardConfig?` | — | Multi-step mode (see below). |
83
+
84
+ `DgaFormLabel` is always `{ en: string; ar: string }`.
85
+
86
+ ### Example with endpoint
87
+
88
+ ```ts
89
+ const EDIT_STUDY: DgaDynamicFormConfig = {
90
+ endpoint: `${apiUrl}/consulting-studies/{id}`,
91
+ method: 'PUT',
92
+ successMessage: { en: 'Saved', ar: 'تم الحفظ' },
93
+ errorMessage: { en: 'Failed', ar: 'فشل' },
94
+ fields: [ /* ... */ ],
95
+ };
96
+ ```
97
+
98
+ ---
99
+
100
+ ## Wizard (`config.wizard` → `DgaWizardConfig`)
101
+
102
+ When `wizard.enabled` is true, fields are taken from `wizard.steps[].fields` (root `fields` can be empty).
103
+
104
+ | Key | Type | Default | Description |
105
+ |-----|------|---------|-------------|
106
+ | `enabled` | `boolean` | — | Turn on stepper UI. |
107
+ | `steps` | `DgaFormStep[]` | — | Ordered steps. |
108
+ | `validateOnStepChange` | `boolean?` | `true` | Block Next if current step invalid. |
109
+ | `allowSkipSteps` | `boolean?` | `false` | Allow jumping ahead (reserved). |
110
+ | `showSaveButton` | `boolean?` | — | Show draft save in wizard chrome. |
111
+ | `autoSave` | `boolean?` | — | Auto-save drafts (host / reserved). |
112
+ | `saveEndpoint` | `string?` | — | Optional draft HTTP URL. |
113
+ | `saveMethod` | `DgaHttpMethod?` | — | Method for `saveEndpoint`. |
114
+ | `nextButtonText` | `DgaFormLabel?` | Next / التالي | |
115
+ | `previousButtonText` | `DgaFormLabel?` | Previous / السابق | |
116
+ | `submitButtonText` | `DgaFormLabel?` | Finish / إنهاء | Final step. |
117
+ | `saveButtonText` | `DgaFormLabel?` | Save / حفظ | |
118
+
119
+ ### Step (`DgaFormStep`)
70
120
 
71
- Override via InjectionTokens:
121
+ | Key | Type | Description |
122
+ |-----|------|-------------|
123
+ | `id` | `string` | Stable step id. |
124
+ | `title` | `DgaFormLabel` | Stepper title. |
125
+ | `description` | `DgaFormLabel?` | Stepper subtitle. |
126
+ | `fields` | `DgaFormField[]` | Fields in this step. |
127
+ | `optional` | `boolean?` | Mark step optional. |
128
+
129
+ ---
130
+
131
+ ## Field (`DgaFormField`)
132
+
133
+ ### Core
134
+
135
+ | Key | Type | Description |
136
+ |-----|------|-------------|
137
+ | `name` | `string` | FormControl name / payload key. |
138
+ | `type` | `DgaFormFieldType` | See built-in types below. |
139
+ | `label` | `DgaFormLabel` | Bilingual label. |
140
+ | `required` | `boolean?` | Always-required. |
141
+ | `placeholder` | `DgaFormLabel?` | |
142
+ | `hint` | `DgaFormLabel?` | Helper under the field. |
143
+ | `value` | `unknown?` | Initial value. |
144
+ | `disabled` | `boolean?` | |
145
+ | `readonly` | `boolean?` | Text-like inputs. |
146
+ | `hidden` | `boolean?` | Hide from layout. |
147
+ | `excludeFromPayload` | `boolean?` | Keep in UI; drop from submit body. |
148
+ | `columns` | `{ sm?, md?, lg?, xl? }` | 12-column grid spans (default 12). |
149
+ | `maxLength` | `number?` | |
150
+ | `rows` | `number?` | Textarea rows. |
151
+ | `inputRestriction` | `'numbers' \| 'english' \| 'arabic'` | Filter keystrokes. |
152
+
153
+ ### Built-in `type` values
154
+
155
+ `text` · `email` · `textarea` · `number` · `otp` · `phone` · `select` · `multiselect` · `checkbox` · `radio` · `date` · `chips` · `toggle` · `file` · `hidden`
156
+
157
+ ### Options (select / radio / checkbox)
158
+
159
+ | Key | Type | Description |
160
+ |-----|------|-------------|
161
+ | `options` | `DgaFormFieldOption[]?` | Static options. |
162
+ | `groupedOptions` | `{ groupLabel, options }[]?` | Grouped static options. |
163
+ | `optionsLayout` | `'stack' \| 'grid'` | Radio/checkbox layout (default `stack`). |
164
+
165
+ **Option object:** `value`, `label`, optional `requiresTextInput`, `description`, `disabled`.
166
+
167
+ ### Visibility & conditional required
168
+
169
+ | Key | Type | Description |
170
+ |-----|------|-------------|
171
+ | `dependsOn` | `string?` | Other field that controls visibility. |
172
+ | `showOnValues` | `unknown[]?` | Show when `dependsOn` value is in list. |
173
+ | `showWhenOptionProperty` | `{ property, value }?` | Show when selected option has `property === value`. |
174
+ | `requiredWhen` | object? | Conditional required (see below). |
175
+
176
+ ```ts
177
+ requiredWhen: {
178
+ field: 'topic',
179
+ value?: 'other', // single match
180
+ values?: ['a', 'b'], // any-of match
181
+ optionProperty?: 'requiresTextInput',
182
+ optionPropertyValue?: true,
183
+ }
184
+ ```
185
+
186
+ ### Lookup (remote options)
187
+
188
+ | Key | Type | Description |
189
+ |-----|------|-------------|
190
+ | `lookupDomain` | `string?` | Base URL for lookup adapter. |
191
+ | `lookupName` | `string?` | Resource → `{domain}/lookup/{name}`. |
192
+ | `lookupFilter` | `{ property, value }?` | Client-side filter on loaded options. |
193
+ | `useParentId` | `boolean?` | Pass `parentId` for cascading lookups. |
194
+ | `searchLookup` | `boolean?` | Search-as-you-type. |
195
+ | `searchParamName` | `string?` | Query param (default `q`). |
196
+ | `minSearchLength` | `number?` | Min chars before search (default 3). |
197
+
198
+ ### Type-specific
199
+
200
+ | Key | Types | Description |
201
+ |-----|-------|-------------|
202
+ | `minDate` / `maxDate` | `date` | ISO date bounds. |
203
+ | `monthPicker` | `date` | Month-only picker. |
204
+ | `acceptedFileTypes` | `file` | e.g. `.pdf,.png`. |
205
+ | `maxFileSize` | `file` | Max bytes. |
206
+ | `maxFiles` | `file` | Max files (`>1` → multiple). |
207
+ | `maxChips` | `chips` | Max chip count. |
208
+ | `allowDuplicates` | `chips` | Allow duplicate chips. |
209
+
210
+ ### Validation (`field.validation`)
211
+
212
+ | Key | Description |
213
+ |-----|-------------|
214
+ | `pattern` | Regex string, or `'email'`. |
215
+ | `minLength` / `maxLength` | Length validators. |
216
+ | `min` / `max` | Numeric bounds. |
217
+ | `required` | Same as `field.required`. |
218
+ | `errorMessages.*` | Bilingual messages for `required`, `pattern`, `minLength`, `maxLength`, `email`, `min`, `max`, `minDate`, `maxDate`, `maxChips`, `invalidFormat`. |
219
+
220
+ ---
221
+
222
+ ## Component API
223
+
224
+ | Member | Kind | Description |
225
+ |--------|------|-------------|
226
+ | `config` | input | `DgaDynamicFormConfig` (required). |
227
+ | `locale` | input | `'ar' \| 'en' \| null` (default from `<html lang>`). |
228
+ | `formSubmitted` | output | HTTP response, or payload when `emitOnly` / no endpoint. |
229
+ | `formError` | output | Submit failure. |
230
+ | `clearButtonClick` | output | After Clear. |
231
+ | `draftSaved` | output | After localStorage save. |
232
+ | `patchFormValues(values)` | method | Patch controls. |
233
+ | `getForm()` | method | Returns `FormGroup`. |
234
+
235
+ ---
236
+
237
+ ## Adapters
72
238
 
73
239
  | Token | Role |
74
240
  |-------|------|
75
- | `DGA_LOOKUP_ADAPTER` | Lookup / search options |
76
- | `DGA_SUBMIT_ADAPTER` | HTTP submit |
77
- | `DGA_FORM_TOAST_ADAPTER` | Success / error feedback |
78
- | `DGA_CAPTCHA_ADAPTER` | Optional captcha token |
79
- | `DGA_FORM_I18N_ADAPTER` | Label resolution |
80
- | `DGA_DYNAMIC_FORM_FIELD_REGISTRY` | Custom field type component map |
241
+ | `DGA_SUBMIT_ADAPTER` | `submit({ endpoint, method, body, headers })` |
242
+ | `DGA_LOOKUP_ADAPTER` | `lookup({ domain, name, parentId?, search? })` |
243
+ | `DGA_FORM_TOAST_ADAPTER` | `show({ title?, message?, variant? })` |
244
+ | `DGA_CAPTCHA_ADAPTER` | `getToken(action?) Observable<string \| null>` |
245
+ | `DGA_FORM_I18N_ADAPTER` | `resolveLabel(label, locale)` |
246
+ | `DGA_DYNAMIC_FORM_FIELD_REGISTRY` | `{ type, component }[]` custom field renderers |
81
247
 
82
- ## Custom field types
248
+ ```ts
249
+ provideDgaDynamicForm({
250
+ httpSubmit: true,
251
+ httpLookup: true,
252
+ dgaToast: true,
253
+ });
254
+ ```
255
+
256
+ ### Custom field type
83
257
 
84
258
  ```ts
85
259
  {
@@ -87,7 +261,3 @@ Override via InjectionTokens:
87
261
  useValue: [{ type: 'nationalId', component: NationalIdField }],
88
262
  }
89
263
  ```
90
-
91
- ## Built-in field types
92
-
93
- `text` · `email` · `textarea` · `number` · `otp` · `phone` · `select` · `multiselect` · `checkbox` · `radio` · `date` · `chips` · `toggle` · `file` · `hidden`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a.nemreen/dga-dynamic-form",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Schema-driven dynamic forms for Angular, rendered with @a.nemreen/dga-ui controls",
5
5
  "license": "MIT",
6
6
  "author": {