@mmstack/form-core 21.0.0 → 21.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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025-present Miha J. Mulec
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025-present Miha J. Mulec
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,219 +1,219 @@
1
- # @mmstack/form-core
2
-
3
- [![npm version](https://badge.fury.io/js/%40mmstack%2Fform-core.svg)](https://www.npmjs.com/package/@mmstack/form-core)
4
- [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/mihajm/mmstack/blob/master/packages/form/core/LICENSE)
5
-
6
- `@mmstack/form-core` is an Angular library that provides a powerful, signal-based approach to building reactive forms. It offers a flexible and type-safe alternative to `ngModel` and Angular's built-in reactive forms, while leveraging the efficiency of Angular signals. This library is designed for fine-grained reactivity and predictable state management, making it ideal for complex forms and applications.
7
-
8
- ## Features
9
-
10
- - **Signal-Based:** Fully utilizes Angular signals for efficient change detection and reactivity.
11
- - **Type-Safe:** Strongly typed API with excellent TypeScript support, ensuring compile-time safety and reducing runtime errors.
12
- - **Composable Primitives:** Provides `formControl`, `formGroup`, and `formArray` primitives that can be composed to create forms of any complexity.
13
- - **Predictable State:** Emphasizes immutability and a clear data flow, making it easier to reason about form state.
14
- - **Customizable Validation:** Supports synchronous validators with full type safety.
15
- - **Dirty and Touched Tracking:** Built-in tracking of `dirty` and `touched` states for individual controls and aggregated states for groups and arrays.
16
- - **Reconciliation:** Efficiently updates form state when underlying data changes (e.g., when receiving data from an API).
17
- - **Extensible:** Designed to be easily extended with custom form controls and validation logic.
18
- - **UI Library Agnostic**: `form-core` can be used with any UI library
19
-
20
- ## Quick Start
21
-
22
- 1. Install `@mmstack/form-core`.
23
-
24
- ```bash
25
- npm install @mmstack/form-core
26
- ```
27
-
28
- 2. Start creating cool forms! :)
29
-
30
- ```typescript
31
- import { Component } from '@angular/core';
32
- import { formControl, formGroup } from '@mmstack/form-core';
33
- import { FormsModule } from '@angular/forms';
34
-
35
- @Component({
36
- selector: 'app-user-form',
37
- imports: [FormsModule],
38
- template: `
39
- <div>
40
- <label>
41
- Name:
42
- <input [value]="name.value()" (input)="name.value.set($any($event.target).value)" [class.invalid]="name.error() && name.touched()" (blur)="name.markAsTouched()" />
43
- </label>
44
- </div>
45
- <div>
46
- <label>
47
- Age:
48
- <input [(ngModel)]="age.value" type="number" [class.invalid]="age.error() && age.touched()" (blur)="age.markAsTouched()" />
49
- <span *ngIf="age.error() && age.touched()">{{ age.error() }}</span>
50
- </label>
51
- </div>
52
- `,
53
- })
54
- export class UserFormComponent {
55
- name = formControl('', {
56
- validator: () => (value) => (value ? '' : 'Name is required'),
57
- });
58
- age = formControl<number | undefined>(undefined, {
59
- //specify the type explicitely to have number type.
60
- validator: () => (value) => (value && value > 0 ? '' : 'Age must be a positive number'),
61
- });
62
- }
63
- ```
64
-
65
- ## Slightly more complex example
66
-
67
- ```typescript
68
- import { Component, computed, inject, Injectable, isDevMode, linkedSignal, Signal, signal, untracked } from '@angular/core';
69
- import { FormsModule } from '@angular/forms';
70
- import { derived, formControl, FormControlSignal, formGroup, FormGroupSignal } from '@mmstack/form-core';
71
- import { mutationResource, queryResource } from '@mmstack/resource';
72
-
73
- type Post = {
74
- id: number;
75
- title?: string;
76
- body?: string;
77
- };
78
-
79
- @Injectable({
80
- providedIn: 'root',
81
- })
82
- export class PostsService {
83
- private readonly endpoint = 'https://jsonplaceholder.typicode.com/posts';
84
-
85
- readonly id = signal(1);
86
-
87
- readonly post = queryResource<Post>(
88
- () => ({
89
- url: `${this.endpoint}/${this.id()}`,
90
- }),
91
- {
92
- keepPrevious: true,
93
- cache: true,
94
- },
95
- );
96
-
97
- next() {
98
- this.id.update((id) => id + 1);
99
- }
100
-
101
- prev() {
102
- this.id.update((id) => id - 1);
103
- }
104
-
105
- private readonly createPostResource = mutationResource(
106
- () => ({
107
- url: this.endpoint,
108
- method: 'POST',
109
- }),
110
- {
111
- onMutate: (post: Post) => {
112
- const prev = untracked(this.post.value);
113
- this.post.set({ ...prev, ...post });
114
- return prev;
115
- },
116
- onError: (err, prev) => {
117
- if (isDevMode()) console.error(err);
118
- this.post.set(prev); // rollback on error
119
- },
120
- onSuccess: (next) => {
121
- this.post.set(next);
122
- },
123
- },
124
- );
125
-
126
- readonly loading = computed(() => this.createPostResource.isLoading() || this.post.isLoading());
127
-
128
- createPost(post: Post) {
129
- this.createPostResource.mutate({
130
- body: post,
131
- }); // send the request
132
- }
133
-
134
- updatePost(id: number, post: Partial<Post>) {
135
- this.createPostResource.mutate({
136
- body: { id, ...post },
137
- url: `${this.endpoint}/${id}`,
138
- method: 'PATCH',
139
- }); // send the request
140
- }
141
- }
142
-
143
- type PostState = FormGroupSignal<
144
- Post,
145
- {
146
- title: FormControlSignal<string | undefined, Post>;
147
- body: FormControlSignal<string | undefined, Post>;
148
- }
149
- >;
150
-
151
- function createPostState(post: Post, loading: Signal<boolean>): PostState {
152
- const value = signal<Post>(post);
153
-
154
- return formGroup(value, {
155
- title: formControl(derived(value, 'title'), {
156
- label: () => 'Title',
157
- readonly: loading,
158
- validator: () => (value) => (value ? '' : 'Title is required'),
159
- }),
160
- body: formControl(derived(value, 'body'), {
161
- label: () => 'Body',
162
- readonly: loading,
163
- validator: () => (value) => {
164
- if (value && value.length > 255) return 'Body is too long';
165
- return '';
166
- },
167
- }),
168
- });
169
- }
170
-
171
- @Component({
172
- selector: 'app-post-form',
173
- imports: [FormsModule],
174
- template: `
175
- <label
176
- >{{ formState().children().title.label() }}
177
- <input [(ngModel)]="formState().children().title.value" [readonly]="formState().children().body.readonly()" [class.error]="formState().children().title.touched() && formState().children().title.error()" />
178
- </label>
179
- <br />
180
-
181
- <label
182
- >{{ formState().children().body.label() }}
183
- <textarea [(ngModel)]="formState().children().body.value" [readonly]="formState().children().body.readonly()" [class.error]="formState().children().body.touched() && formState().children().body.error()"></textarea>
184
- </label>
185
-
186
- <br />
187
-
188
- <button (click)="submit()" [disabled]="svc.loading()">Submit</button>
189
- `,
190
- })
191
- export class PostFormComponent {
192
- protected readonly svc = inject(PostsService);
193
-
194
- protected readonly formState = linkedSignal<Post, PostState>({
195
- source: () => this.svc.post.value() ?? { title: '', body: '', id: -1, userId: -1 },
196
- computation: (source, prev) => {
197
- if (prev) {
198
- prev.value.forceReconcile(source);
199
- return prev.value;
200
- }
201
-
202
- return createPostState(source, this.svc.loading);
203
- },
204
- });
205
-
206
- protected submit() {
207
- if (untracked(this.svc.loading)) return;
208
- const state = untracked(this.formState);
209
- if (!untracked(state.valid)) return state.markAllAsTouched();
210
- const value = untracked(state.value);
211
- if (value.id === -1) this.svc.createPost(value);
212
- else this.svc.updatePost(value.id, untracked(state.partialValue));
213
- }
214
- }
215
- ```
216
-
217
- ## In-depth
218
-
219
- For an in-depth explanation of the primitives & how they work check out this article: [Fun-grained Reactivity in Angular: Part 2 - Forms](https://dev.to/mihamulec/fun-grained-reactivity-in-angular-part-2-forms-e84)
1
+ # @mmstack/form-core
2
+
3
+ [![npm version](https://badge.fury.io/js/%40mmstack%2Fform-core.svg)](https://www.npmjs.com/package/@mmstack/form-core)
4
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/mihajm/mmstack/blob/master/packages/form/core/LICENSE)
5
+
6
+ `@mmstack/form-core` is an Angular library that provides a powerful, signal-based approach to building reactive forms. It offers a flexible and type-safe alternative to `ngModel` and Angular's built-in reactive forms, while leveraging the efficiency of Angular signals. This library is designed for fine-grained reactivity and predictable state management, making it ideal for complex forms and applications.
7
+
8
+ ## Features
9
+
10
+ - **Signal-Based:** Fully utilizes Angular signals for efficient change detection and reactivity.
11
+ - **Type-Safe:** Strongly typed API with excellent TypeScript support, ensuring compile-time safety and reducing runtime errors.
12
+ - **Composable Primitives:** Provides `formControl`, `formGroup`, and `formArray` primitives that can be composed to create forms of any complexity.
13
+ - **Predictable State:** Emphasizes immutability and a clear data flow, making it easier to reason about form state.
14
+ - **Customizable Validation:** Supports synchronous validators with full type safety.
15
+ - **Dirty and Touched Tracking:** Built-in tracking of `dirty` and `touched` states for individual controls and aggregated states for groups and arrays.
16
+ - **Reconciliation:** Efficiently updates form state when underlying data changes (e.g., when receiving data from an API).
17
+ - **Extensible:** Designed to be easily extended with custom form controls and validation logic.
18
+ - **UI Library Agnostic**: `form-core` can be used with any UI library
19
+
20
+ ## Quick Start
21
+
22
+ 1. Install `@mmstack/form-core`.
23
+
24
+ ```bash
25
+ npm install @mmstack/form-core
26
+ ```
27
+
28
+ 2. Start creating cool forms! :)
29
+
30
+ ```typescript
31
+ import { Component } from '@angular/core';
32
+ import { formControl, formGroup } from '@mmstack/form-core';
33
+ import { FormsModule } from '@angular/forms';
34
+
35
+ @Component({
36
+ selector: 'app-user-form',
37
+ imports: [FormsModule],
38
+ template: `
39
+ <div>
40
+ <label>
41
+ Name:
42
+ <input [value]="name.value()" (input)="name.value.set($any($event.target).value)" [class.invalid]="name.error() && name.touched()" (blur)="name.markAsTouched()" />
43
+ </label>
44
+ </div>
45
+ <div>
46
+ <label>
47
+ Age:
48
+ <input [(ngModel)]="age.value" type="number" [class.invalid]="age.error() && age.touched()" (blur)="age.markAsTouched()" />
49
+ <span *ngIf="age.error() && age.touched()">{{ age.error() }}</span>
50
+ </label>
51
+ </div>
52
+ `,
53
+ })
54
+ export class UserFormComponent {
55
+ name = formControl('', {
56
+ validator: () => (value) => (value ? '' : 'Name is required'),
57
+ });
58
+ age = formControl<number | undefined>(undefined, {
59
+ //specify the type explicitely to have number type.
60
+ validator: () => (value) => (value && value > 0 ? '' : 'Age must be a positive number'),
61
+ });
62
+ }
63
+ ```
64
+
65
+ ## Slightly more complex example
66
+
67
+ ```typescript
68
+ import { Component, computed, inject, Injectable, isDevMode, linkedSignal, Signal, signal, untracked } from '@angular/core';
69
+ import { FormsModule } from '@angular/forms';
70
+ import { derived, formControl, FormControlSignal, formGroup, FormGroupSignal } from '@mmstack/form-core';
71
+ import { mutationResource, queryResource } from '@mmstack/resource';
72
+
73
+ type Post = {
74
+ id: number;
75
+ title?: string;
76
+ body?: string;
77
+ };
78
+
79
+ @Injectable({
80
+ providedIn: 'root',
81
+ })
82
+ export class PostsService {
83
+ private readonly endpoint = 'https://jsonplaceholder.typicode.com/posts';
84
+
85
+ readonly id = signal(1);
86
+
87
+ readonly post = queryResource<Post>(
88
+ () => ({
89
+ url: `${this.endpoint}/${this.id()}`,
90
+ }),
91
+ {
92
+ keepPrevious: true,
93
+ cache: true,
94
+ },
95
+ );
96
+
97
+ next() {
98
+ this.id.update((id) => id + 1);
99
+ }
100
+
101
+ prev() {
102
+ this.id.update((id) => id - 1);
103
+ }
104
+
105
+ private readonly createPostResource = mutationResource(
106
+ () => ({
107
+ url: this.endpoint,
108
+ method: 'POST',
109
+ }),
110
+ {
111
+ onMutate: (post: Post) => {
112
+ const prev = untracked(this.post.value);
113
+ this.post.set({ ...prev, ...post });
114
+ return prev;
115
+ },
116
+ onError: (err, prev) => {
117
+ if (isDevMode()) console.error(err);
118
+ this.post.set(prev); // rollback on error
119
+ },
120
+ onSuccess: (next) => {
121
+ this.post.set(next);
122
+ },
123
+ },
124
+ );
125
+
126
+ readonly loading = computed(() => this.createPostResource.isLoading() || this.post.isLoading());
127
+
128
+ createPost(post: Post) {
129
+ this.createPostResource.mutate({
130
+ body: post,
131
+ }); // send the request
132
+ }
133
+
134
+ updatePost(id: number, post: Partial<Post>) {
135
+ this.createPostResource.mutate({
136
+ body: { id, ...post },
137
+ url: `${this.endpoint}/${id}`,
138
+ method: 'PATCH',
139
+ }); // send the request
140
+ }
141
+ }
142
+
143
+ type PostState = FormGroupSignal<
144
+ Post,
145
+ {
146
+ title: FormControlSignal<string | undefined, Post>;
147
+ body: FormControlSignal<string | undefined, Post>;
148
+ }
149
+ >;
150
+
151
+ function createPostState(post: Post, loading: Signal<boolean>): PostState {
152
+ const value = signal<Post>(post);
153
+
154
+ return formGroup(value, {
155
+ title: formControl(derived(value, 'title'), {
156
+ label: () => 'Title',
157
+ readonly: loading,
158
+ validator: () => (value) => (value ? '' : 'Title is required'),
159
+ }),
160
+ body: formControl(derived(value, 'body'), {
161
+ label: () => 'Body',
162
+ readonly: loading,
163
+ validator: () => (value) => {
164
+ if (value && value.length > 255) return 'Body is too long';
165
+ return '';
166
+ },
167
+ }),
168
+ });
169
+ }
170
+
171
+ @Component({
172
+ selector: 'app-post-form',
173
+ imports: [FormsModule],
174
+ template: `
175
+ <label
176
+ >{{ formState().children().title.label() }}
177
+ <input [(ngModel)]="formState().children().title.value" [readonly]="formState().children().body.readonly()" [class.error]="formState().children().title.touched() && formState().children().title.error()" />
178
+ </label>
179
+ <br />
180
+
181
+ <label
182
+ >{{ formState().children().body.label() }}
183
+ <textarea [(ngModel)]="formState().children().body.value" [readonly]="formState().children().body.readonly()" [class.error]="formState().children().body.touched() && formState().children().body.error()"></textarea>
184
+ </label>
185
+
186
+ <br />
187
+
188
+ <button (click)="submit()" [disabled]="svc.loading()">Submit</button>
189
+ `,
190
+ })
191
+ export class PostFormComponent {
192
+ protected readonly svc = inject(PostsService);
193
+
194
+ protected readonly formState = linkedSignal<Post, PostState>({
195
+ source: () => this.svc.post.value() ?? { title: '', body: '', id: -1, userId: -1 },
196
+ computation: (source, prev) => {
197
+ if (prev) {
198
+ prev.value.forceReconcile(source);
199
+ return prev.value;
200
+ }
201
+
202
+ return createPostState(source, this.svc.loading);
203
+ },
204
+ });
205
+
206
+ protected submit() {
207
+ if (untracked(this.svc.loading)) return;
208
+ const state = untracked(this.formState);
209
+ if (!untracked(state.valid)) return state.markAllAsTouched();
210
+ const value = untracked(state.value);
211
+ if (value.id === -1) this.svc.createPost(value);
212
+ else this.svc.updatePost(value.id, untracked(state.partialValue));
213
+ }
214
+ }
215
+ ```
216
+
217
+ ## In-depth
218
+
219
+ For an in-depth explanation of the primitives & how they work check out this article: [Fun-grained Reactivity in Angular: Part 2 - Forms](https://dev.to/mihamulec/fun-grained-reactivity-in-angular-part-2-forms-e84)
@@ -223,11 +223,8 @@ function formArray(initial, factory, opt) {
223
223
  const length = computed(() => ctrl.value().length, ...(ngDevMode ? [{ debugName: "length" }] : []));
224
224
  const reconcileChildren = createReconcileChildren(factory, { equal: eq });
225
225
  // linkedSignal used to re-use previous value so that only length changes are affected and existing controls are kept, but updated
226
- const children = linkedSignal(...(ngDevMode ? [{ debugName: "children", source: () => length(),
227
- computation: (len, prev) => reconcileChildren(len, ctrl.value, prev?.value) }] : [{
228
- source: () => length(),
229
- computation: (len, prev) => reconcileChildren(len, ctrl.value, prev?.value),
230
- }]));
226
+ const children = linkedSignal({ ...(ngDevMode ? { debugName: "children" } : {}), source: () => length(),
227
+ computation: (len, prev) => reconcileChildren(len, ctrl.value, prev?.value) });
231
228
  const ownError = computed(() => ctrl.error(), ...(ngDevMode ? [{ debugName: "ownError" }] : []));
232
229
  const error = computed(() => {
233
230
  const own = ownError();
@@ -1 +1 @@
1
- {"version":3,"file":"mmstack-form-core.mjs","sources":["../../../../../packages/form/core/src/lib/util.ts","../../../../../packages/form/core/src/lib/form-control.ts","../../../../../packages/form/core/src/lib/form-array.ts","../../../../../packages/form/core/src/lib/form-group.ts","../../../../../packages/form/core/src/mmstack-form-core.ts"],"sourcesContent":["/**\r\n * Merges two arrays element by element using the `mergeIfObject` logic.\r\n *\r\n * The resulting array will have the same length as the `next` array.\r\n * For each index `i`, the element in the resulting array is determined by:\r\n * `mergeIfObject(prev[i], next[i])`.\r\n * If `prev` is shorter than `next`, `prev[i]` will be `undefined` for the out-of-bounds indices.\r\n *\r\n * @template {any[]} T The array type being merged.\r\n * @param {T} prev The previous array.\r\n * @param {T} next The next array.\r\n * @returns {T} A new array containing the merged elements.\r\n * @example\r\n * const prev = [1, { id: 1, name: \"A\" }, [10], \"extraPrev\"];\r\n * const next = [2, { id: 1, status: \"B\" }, [20, 21], missing , { id: 2 }];\r\n *\r\n * mergeArray(prev, next);\r\n * // Result approx:\r\n * // [\r\n * // 2, // Primitive replaced\r\n * // { id: 1, name: \"A\", status: \"B\" }, // Objects shallow-merged\r\n * // [20, 21], // Arrays replaced (via mergeIfObject -> mergeArray)\r\n * // undefined, // Primitive replaced by missing item in sparse 'next' array\r\n * // { id: 2 } // Added from 'next' (prev[4] was undefined)\r\n * // ]\r\n */\r\nexport function mergeArray<T extends any[]>(prev: T, next: T): T {\r\n return next.map((item, index): T[number] =>\r\n mergeIfObject<T[number]>(prev[index], item),\r\n ) as T;\r\n}\r\n\r\n/**\r\n * Merges two values (`prev`, `next`), prioritizing `next` in most cases.\r\n *\r\n * Behavior:\r\n * - If both `prev` and `next` are non-null, non-array objects, it performs a **shallow merge**\r\n * (`{ ...prev, ...next }`), where properties from `next` overwrite those in `prev`.\r\n * - If both `prev` and `next` are arrays, it delegates to `mergeArray` for element-wise merging.\r\n * - In all other scenarios (type mismatch, primitives, null involved, array mixed with object),\r\n * it simply returns the `next` value.\r\n *\r\n * @template T The type of the values being merged.\r\n * @param {T | undefined} prev The previous value (can be undefined if accessed out of array bounds).\r\n * @param {T} next The next value.\r\n * @returns {T} The merged result based on the rules above.\r\n */\r\nexport function mergeIfObject<T>(prev: T, next: T): T {\r\n if (typeof prev !== typeof next) return next;\r\n if (typeof prev !== 'object' || typeof next !== 'object') return next;\r\n if (prev === null || next === null) return next;\r\n if (Array.isArray(prev) && Array.isArray(next)) return mergeArray(prev, next);\r\n if (Array.isArray(prev) || Array.isArray(next)) return next;\r\n\r\n return { ...prev, ...next };\r\n}\r\n\r\n/**\r\n * Generates a unique ID using crypto.randomUUID if available,\r\n * otherwise falls back to a non-secure random string.\r\n * @returns {string}\r\n */\r\nexport function generateID() {\r\n if (globalThis.crypto?.randomUUID) {\r\n return globalThis.crypto.randomUUID();\r\n }\r\n return Math.random().toString(36).substring(2);\r\n}\r\n","import {\r\n computed,\r\n isSignal,\r\n signal,\r\n untracked,\r\n type CreateSignalOptions,\r\n type Signal,\r\n type ValueEqualityFn,\r\n type WritableSignal,\r\n} from '@angular/core';\r\nimport { type DerivedSignal } from '@mmstack/primitives';\r\nimport { generateID } from './util';\r\n\r\n/**\r\n * Represents the type of a form control.\r\n * - `control`: A single form control (e.g., an input field).\r\n * - `array`: An array of form controls (like Angular's `FormArray`).\r\n * - `group`: A group of form controls (like Angular's `FormGroup`).\r\n */\r\nexport type ControlType = 'control' | 'array' | 'group';\r\n\r\n/**\r\n * Represents a reactive form control. It holds the value, validation status, and other\r\n * metadata for a form field. This is the core building block for creating reactive forms\r\n * with signals.\r\n *\r\n * @typeParam T - The type of the form control's value.\r\n * @typeParam TParent - The type of the parent form control's value (if this control is part of a group or array). Defaults to `undefined`.\r\n * @typeParam TControlType - The type of the control ('control', 'array', or 'group'). Defaults to 'control'.\r\n * @typeParam TPartialValue - The type of the partial value, used for patching.\r\n */\r\nexport type FormControlSignal<\r\n T,\r\n TParent = undefined,\r\n TControlType extends ControlType = 'control',\r\n TPartialValue = T | undefined,\r\n> = {\r\n /** A unique identifier for the control. Used for tracking in `@for` loops. */\r\n id: string;\r\n /** The main value signal for the control. */\r\n value: WritableSignal<T>;\r\n /** A signal indicating whether the control's value has been changed. */\r\n dirty: Signal<boolean>;\r\n /** A signal indicating whether the control has been interacted with (e.g., blurred). */\r\n touched: Signal<boolean>;\r\n /** A signal containing the current validation error message (empty string if valid). */\r\n error: Signal<string>;\r\n /** A signal indicating whether the control is pending */\r\n pending: Signal<boolean>;\r\n /** A signal indicating whether the control is disabled. */\r\n /** A signal indicating whether the control is in a valid state (without errors & not pending) */\r\n valid: Signal<boolean>;\r\n disabled: Signal<boolean>;\r\n /** A signal indicating whether the control is read-only. */\r\n readonly: Signal<boolean>;\r\n /** A signal indicating whether the control is required. */\r\n required: Signal<boolean>;\r\n /** A signal containing the label for the control. */\r\n label: Signal<string>;\r\n /** A signal containing the hint text for the control. */\r\n hint: Signal<string>;\r\n /** Marks the control as touched. */\r\n markAsTouched: () => void;\r\n /** Marks the control and all its child controls (if any) as touched. */\r\n markAllAsTouched: () => void;\r\n /** Marks the control as pristine (not touched). */\r\n markAsPristine: () => void;\r\n /** Marks the control and all its child controls (if any) as pristine. */\r\n markAllAsPristine: () => void;\r\n /**\r\n * Resets the control to a new value and sets a new initial value. This is intended for\r\n * scenarios where the underlying data is updated externally (e.g., data coming from\r\n * the server). If the control is not dirty, the value is updated. If the control *is*\r\n * dirty, the value is *not* updated (preserving user changes).\r\n */\r\n reconcile: (newValue: T) => void;\r\n /**\r\n * Similar to `reconcile`, but forces the update even if the control is dirty.\r\n */\r\n forceReconcile: (newValue: T) => void;\r\n /** Resets the control's value to its initial value. */\r\n reset: () => void;\r\n /** Resets the control's value and initial value. */\r\n resetWithInitial: (initial: T) => void;\r\n /**\r\n * The derivation function used to create this control if it's part of a `formGroup` or `formArray`.\r\n * @internal\r\n */\r\n from?: DerivedSignal<TParent, T>['from'];\r\n /** The equality function used to compare values. Defaults to `Object.is`. */\r\n equal: (a: T, b: T) => boolean;\r\n /** The type of the control ('control', 'array', or 'group'). */\r\n controlType: TControlType;\r\n /**\r\n * A signal representing the partial value of the control, suitable for patching data on a server.\r\n * It contains the changed value if `dirty` is `true`.\r\n */\r\n partialValue: Signal<TPartialValue>;\r\n};\r\n\r\nexport type CreateFormControlOptions<\r\n T,\r\n TControlType extends ControlType = ControlType,\r\n> = CreateSignalOptions<T> & {\r\n validator?: () => (value: T) => string;\r\n onTouched?: () => void;\r\n disable?: () => boolean;\r\n readonly?: () => boolean;\r\n required?: () => boolean;\r\n label?: () => string;\r\n id?: () => string;\r\n hint?: () => string;\r\n dirtyEquality?: ValueEqualityFn<T>;\r\n onReset?: () => void;\r\n controlType?: TControlType;\r\n overrideValidation?: () => string;\r\n pending?: () => boolean;\r\n};\r\n\r\n/**\r\n * Creates a `FormControlSignal`, a reactive form control that holds a value and tracks its\r\n * validity, dirty state, touched state, and other metadata.\r\n *\r\n * @typeParam T - The type of the form control's value.\r\n * @typeParam TParent - The type of the parent form control's value (if this control is part of a group or array).\r\n * @typeParam TControlType - The type of the control. Defaults to `'control'`.\r\n * @typeParam TPartialValue - The type of value when patching\r\n * @param initial - The initial value of the control, or a `DerivedSignal` if this control is part of a `formGroup` or `formArray`.\r\n * @param options - Optional configuration options for the control.\r\n * @returns A `FormControlSignal` instance.\r\n *\r\n * @example\r\n * // Create a simple form control:\r\n * const name = formControl('Initial Name');\r\n *\r\n * // Create a form control with validation:\r\n * const age = formControl(0, {\r\n * validator: () => (value) => value >= 18 ? '' : 'Must be at least 18',\r\n * });\r\n *\r\n * // Create a derived form control (equivalent to the above, but more explicit):\r\n * const user = signal({ name: 'John Doe', age: 30 });\r\n * const name = formControl(derived(user, {\r\n * from: (u) => u.name,\r\n * onChange: (newName) => user.update(u => ({...u, name: newName}))\r\n * }));\r\n *\r\n * // Create a form group with nested controls:\r\n * const user = signal({ name: 'John Doe', age: 30 });\r\n * const form = formGroup(user, {\r\n * name: formControl(derived(user, 'name')),\r\n * age: formControl(derived(user, 'age')),\r\n * })\r\n */\r\nexport function formControl<\r\n T,\r\n TParent = undefined,\r\n TControlType extends ControlType = 'control',\r\n TPartialValue = T | undefined,\r\n>(\r\n initial: DerivedSignal<TParent, T> | T,\r\n opt?: CreateFormControlOptions<T, TControlType>,\r\n): FormControlSignal<T, TParent, TControlType, TPartialValue> {\r\n const value = isSignal(initial) ? initial : signal(initial, opt);\r\n const initialValue = signal(untracked(value));\r\n const eq = opt?.equal ?? Object.is;\r\n\r\n const dirtyEq = opt?.dirtyEquality ?? eq;\r\n\r\n const disabled = computed(() => opt?.disable?.() ?? false);\r\n const readonly = computed(() => opt?.readonly?.() ?? false);\r\n\r\n const dirty = computed(() => !dirtyEq(value(), initialValue()));\r\n\r\n const touched = signal(false);\r\n\r\n const validator = computed(() => opt?.validator?.() ?? (() => ''));\r\n\r\n const error = computed(() => {\r\n if (opt?.overrideValidation) return opt.overrideValidation();\r\n if (disabled() || readonly()) return '';\r\n return validator()(value());\r\n });\r\n\r\n const markAsTouched = () => {\r\n touched.set(true);\r\n opt?.onTouched?.();\r\n };\r\n const markAllAsTouched = markAsTouched;\r\n\r\n const markAsPristine = () => touched.set(false);\r\n const markAllAsPristine = markAsPristine;\r\n\r\n const label = computed(() => opt?.label?.() ?? '');\r\n\r\n const partialValue = computed(() => (dirty() ? value() : undefined));\r\n\r\n const internalReconcile = (newValue: T, force = false) => {\r\n const isDirty = untracked(dirty);\r\n\r\n if (!isDirty || force) {\r\n // very dangerous use of untracked here, don't do this everywhere :)\r\n // thanks to u/synalx for the idea to use untracked here\r\n\r\n untracked(() => {\r\n initialValue.set(newValue);\r\n value.set(newValue);\r\n });\r\n }\r\n };\r\n\r\n const pending = computed(() => opt?.pending?.() ?? false);\r\n\r\n return {\r\n id: opt?.id?.() ?? generateID(),\r\n value,\r\n dirty,\r\n touched,\r\n error,\r\n label,\r\n required: computed(() => opt?.required?.() ?? false),\r\n disabled,\r\n readonly,\r\n pending,\r\n valid: computed(() => !pending() && !error()),\r\n hint: computed(() => opt?.hint?.() ?? ''),\r\n markAsTouched,\r\n markAllAsTouched,\r\n markAsPristine,\r\n markAllAsPristine,\r\n from: (isSignal(initial) ? initial.from : undefined) as FormControlSignal<\r\n T,\r\n TParent,\r\n TControlType\r\n >['from'],\r\n reconcile: (newValue: T) => internalReconcile(newValue),\r\n forceReconcile: (newValue: T) => internalReconcile(newValue, true),\r\n reset: () => {\r\n opt?.onReset?.();\r\n value.set(untracked(initialValue));\r\n },\r\n resetWithInitial: (initial: T) => {\r\n opt?.onReset?.();\r\n initialValue.set(initial);\r\n value.set(initial);\r\n },\r\n equal: eq,\r\n controlType: (opt?.controlType ?? 'control') as TControlType,\r\n partialValue: partialValue as Signal<TPartialValue>,\r\n };\r\n}\r\n","import {\r\n computed,\r\n linkedSignal,\r\n untracked,\r\n type Signal,\r\n type WritableSignal,\r\n} from '@angular/core';\r\nimport { derived, type DerivedSignal } from '@mmstack/primitives';\r\nimport {\r\n formControl,\r\n type CreateFormControlOptions,\r\n type FormControlSignal,\r\n} from './form-control';\r\nimport { type SignalValue } from './signal-value.type';\r\nimport { mergeArray } from './util';\r\n\r\nexport type FormArraySignal<\r\n T,\r\n TIndividualState extends FormControlSignal<\r\n T,\r\n any,\r\n any,\r\n any\r\n > = FormControlSignal<T, any, any, any>,\r\n TParent = undefined,\r\n> = FormControlSignal<\r\n T[],\r\n TParent,\r\n 'array',\r\n | Exclude<SignalValue<TIndividualState['partialValue']>, null | undefined>[]\r\n | undefined\r\n> & {\r\n ownError: Signal<string>;\r\n children: Signal<TIndividualState[]>;\r\n push: (value: T) => void; // add new control with value\r\n remove: (index: number) => void; // remove at index\r\n min: Signal<number>; // for display purposes\r\n max: Signal<number>; // for display purposes\r\n canAdd: Signal<boolean>; // disable add button if false\r\n canRemove: Signal<boolean>; // disable remove buttons if false\r\n};\r\n\r\nexport type CreateFormArraySignalOptions<\r\n T,\r\n TIndividualState extends FormControlSignal<T, any, any, any>,\r\n> = Omit<CreateFormControlOptions<T[]>, 'equal'> & {\r\n min?: () => number;\r\n max?: () => number;\r\n equal?: (a: T, b: T) => boolean;\r\n toPartialValue?: (\r\n v: T,\r\n ) => Exclude<SignalValue<TIndividualState['partialValue']>, null | undefined>;\r\n};\r\n\r\nfunction createReconcileChildren<\r\n T,\r\n TIndividualState extends FormControlSignal<T, any, any, any>,\r\n>(\r\n factory: (val: DerivedSignal<T[], T>, idx: number) => TIndividualState,\r\n opt: { equal: (a: T, b: T) => boolean },\r\n) {\r\n return (\r\n length: number,\r\n source: WritableSignal<T[]>,\r\n prev?: TIndividualState[],\r\n ): TIndividualState[] => {\r\n if (!prev) {\r\n const nextControls = [];\r\n\r\n for (let i = 0; i < length; i++) {\r\n nextControls.push(\r\n factory(derived(source, i, { equal: opt?.equal }), i),\r\n );\r\n }\r\n\r\n return nextControls;\r\n }\r\n\r\n if (length === prev.length) return prev;\r\n\r\n const next = [...prev];\r\n\r\n if (length < prev.length) {\r\n next.splice(length);\r\n } else if (length > prev.length) {\r\n for (let i = prev.length; i < length; i++) {\r\n next.push(factory(derived(source, i, { equal: opt?.equal }), i));\r\n }\r\n }\r\n\r\n return next;\r\n };\r\n}\r\n\r\nexport function formArray<\r\n T,\r\n TIndividualState extends FormControlSignal<\r\n T,\r\n any,\r\n any,\r\n any\r\n > = FormControlSignal<T, any, any, any>,\r\n TParent = undefined,\r\n>(\r\n initial: T[] | DerivedSignal<TParent, T[]>,\r\n factory: (val: DerivedSignal<T[], T>, idx: number) => TIndividualState,\r\n opt?: CreateFormArraySignalOptions<T, TIndividualState>,\r\n): FormArraySignal<T, TIndividualState, TParent> {\r\n const eq = opt?.equal ?? Object.is;\r\n\r\n const arrayEqual = (a: T[], b: T[]) => {\r\n if (a.length !== b.length) return false;\r\n if (!a.length) return true;\r\n\r\n return a.every((v, i) => eq(v, b[i]));\r\n };\r\n\r\n const min = computed(() => opt?.min?.() ?? 0);\r\n const max = computed(() => opt?.max?.() ?? Number.MAX_SAFE_INTEGER);\r\n\r\n const arrayOptions: CreateFormControlOptions<T[], 'array'> = {\r\n ...opt,\r\n equal: arrayEqual,\r\n dirtyEquality: (a, b) => a.length === b.length,\r\n controlType: 'array',\r\n };\r\n\r\n const ctrl = formControl<T[], TParent, 'array'>(\r\n initial,\r\n arrayOptions,\r\n ) satisfies FormControlSignal<T[], TParent, 'array'>;\r\n\r\n const length = computed(() => ctrl.value().length);\r\n\r\n const reconcileChildren = createReconcileChildren<T, TIndividualState>(\r\n factory,\r\n { equal: eq },\r\n );\r\n\r\n // linkedSignal used to re-use previous value so that only length changes are affected and existing controls are kept, but updated\r\n const children = linkedSignal<number, TIndividualState[]>({\r\n source: () => length(),\r\n computation: (len, prev) => reconcileChildren(len, ctrl.value, prev?.value),\r\n });\r\n\r\n const ownError = computed(() => ctrl.error());\r\n\r\n const error = computed((): string => {\r\n const own = ownError();\r\n if (own) return own;\r\n if (!children().length) return '';\r\n return children()\r\n .map((c, idx) => (c.error() ? `${idx}: ${c.error()}` : ''))\r\n .filter(Boolean)\r\n .join('\\n');\r\n });\r\n\r\n const dirty = computed(() => {\r\n if (ctrl.dirty()) return true;\r\n if (!children().length) return false;\r\n return children().some((c) => c.dirty());\r\n });\r\n\r\n const markAllAsTouched = () => {\r\n ctrl.markAllAsTouched();\r\n for (const c of untracked(children)) {\r\n c.markAllAsTouched();\r\n }\r\n };\r\n const markAllAsPristine = () => {\r\n ctrl.markAllAsPristine();\r\n for (const c of untracked(children)) {\r\n c.markAllAsPristine();\r\n }\r\n };\r\n\r\n const toPartialValue = opt?.toPartialValue ?? ((v: T) => v);\r\n const partialValue = computed(() => {\r\n if (!dirty()) return undefined;\r\n return children().map((c) => {\r\n const pv = c.partialValue();\r\n if (pv) return pv;\r\n if (c.controlType === 'control') return undefined;\r\n\r\n // return full value for child objects/arrays as this cannot be partially patched without idx\r\n return toPartialValue(c.value());\r\n });\r\n });\r\n\r\n const touched = computed(\r\n () =>\r\n ctrl.touched() ||\r\n !!(children().length && children().some((c) => c.touched())),\r\n );\r\n\r\n const reconcile = (newValue: T[]) => {\r\n const ctrls = untracked(children);\r\n\r\n for (let i = 0; i < newValue.length; i++) {\r\n ctrls.at(i)?.reconcile(newValue[i]); // reconcile existing controls that are relevant addition/removal will be handled after ctrl.reconcile through linkedSignal\r\n }\r\n\r\n ctrl.reconcile(mergeArray(newValue, untracked(ctrl.value)));\r\n };\r\n\r\n const forceReconcile = (newValue: T[]) => {\r\n const ctrls = untracked(children);\r\n\r\n for (let i = 0; i < newValue.length; i++) {\r\n ctrls.at(i)?.forceReconcile(newValue[i]);\r\n }\r\n\r\n ctrl.forceReconcile(newValue);\r\n };\r\n\r\n const childrenValid = computed(() => {\r\n if (!children().length) return true;\r\n return children().every((d) => d.valid());\r\n });\r\n\r\n const childrenPending = computed(\r\n () => !!children().length && children().some((d) => d.pending()),\r\n );\r\n\r\n return {\r\n ...ctrl,\r\n ownError,\r\n error,\r\n valid: computed(() => ctrl.valid() && childrenValid()),\r\n pending: computed(() => ctrl.pending() || childrenPending()),\r\n touched,\r\n children,\r\n dirty,\r\n markAllAsTouched,\r\n markAllAsPristine,\r\n min,\r\n max,\r\n partialValue,\r\n canAdd: computed(\r\n () => !ctrl.disabled() && !ctrl.readonly() && length() < max(),\r\n ),\r\n canRemove: computed(\r\n () => !ctrl.disabled() && !ctrl.readonly() && length() > min(),\r\n ),\r\n reconcile,\r\n forceReconcile,\r\n reset: () => {\r\n for (const c of untracked(children)) {\r\n c.reset();\r\n }\r\n ctrl.reset();\r\n },\r\n resetWithInitial: (initial: T[]) => {\r\n const ctrls = untracked(children);\r\n for (let i = 0; i < initial.length; i++) {\r\n ctrls.at(i)?.resetWithInitial(initial[i]);\r\n }\r\n ctrl.resetWithInitial(initial);\r\n },\r\n push: (next) => ctrl.value.update((cur) => [...cur, next]),\r\n remove: (idx) =>\r\n ctrl.value.update((cur) => cur.filter((_, i) => i !== idx)),\r\n };\r\n}\r\n","import {\r\n computed,\r\n isSignal,\r\n signal,\r\n untracked,\r\n type Signal,\r\n type WritableSignal,\r\n} from '@angular/core';\r\nimport {\r\n isDerivation,\r\n toFakeSignalDerivation,\r\n type DerivedSignal,\r\n} from '@mmstack/primitives';\r\nimport {\r\n formControl,\r\n type CreateFormControlOptions,\r\n type FormControlSignal,\r\n} from './form-control';\r\nimport { type SignalValue } from './signal-value.type';\r\nimport { mergeIfObject } from './util';\r\n\r\ntype AnyObject = Record<PropertyKey, any>;\r\n\r\n/**\r\n * Extracts the partial value types from a record of `FormControlSignal` instances.\r\n * This is used to construct the `partialValue` type for `FormGroupSignal`.\r\n * @internal\r\n */\r\ntype DerivationPartialValues<\r\n TDerivations extends Record<string, FormControlSignal<any, any, any, any>>,\r\n> = {\r\n [K in keyof TDerivations]: Exclude<\r\n SignalValue<TDerivations[K]['partialValue']>,\r\n undefined\r\n >;\r\n};\r\n\r\n/**\r\n * Represents a group of form controls, similar to Angular's `FormGroup`. It aggregates\r\n * the values and states of its child controls into a single object.\r\n *\r\n * @typeParam T - The type of the form group's value (an object).\r\n * @typeParam TDerivations - A record where keys are the names of the child controls and values are the `FormControlSignal` instances.\r\n * @typeParam TParent - The type of the parent form control's value (if this group is nested).\r\n */\r\nexport type FormGroupSignal<\r\n T,\r\n TDerivations extends Record<string, FormControlSignal<any, T, any, any>>,\r\n TParent = undefined,\r\n> = FormControlSignal<\r\n T,\r\n TParent,\r\n 'group',\r\n Partial<DerivationPartialValues<TDerivations>>\r\n> & {\r\n /**\r\n * A signal that holds a record of the child form controls. The keys are the names\r\n * of the controls, and the values are the `FormControlSignal` instances.\r\n */\r\n children: Signal<TDerivations>;\r\n /**\r\n * A signal that holds the validation error message of the group itself (excluding child errors).\r\n */\r\n ownError: Signal<string>;\r\n};\r\n\r\n/**\r\n * Options for creating a `FormGroupSignal`. Extends `CreateFormControlOptions`.\r\n */\r\nexport type CreateFormGroupOptions<\r\n T,\r\n TDerivations extends Record<string, FormControlSignal<any, T, any, any>>,\r\n> = CreateFormControlOptions<T, 'group'> & {\r\n /**\r\n * An optional function to create a base object for the `partialValue` signal.\r\n * This can be used to pre-populate the partial value with default values or\r\n * to perform custom logic before merging in the partial values from child controls.\r\n */\r\n createBasePartialValue?: (\r\n value: T,\r\n ) => Partial<DerivationPartialValues<TDerivations>>;\r\n};\r\n\r\n/**\r\n * Creates a `FormGroupSignal`, which aggregates a set of child form controls into a single object.\r\n *\r\n * @typeParam T - The type of the form group's value (an object).\r\n * @typeParam TDerivations - A record where keys are the names of the child controls and values are the `FormControlSignal` instances.\r\n * @typeParam TParent - The type of the parent form control's value (if this group is nested within another group or array).\r\n * @param initial - The initial value of the form group (or a `WritableSignal` or `DerivedSignal` if the group is nested).\r\n * @param providedChildren - An object containing the child `FormControlSignal` instances, or a function that returns such an object.\r\n * Using a function allows for dynamic creation of child controls (e.g., in response to changes in other signals).\r\n * @param options - Optional configuration options for the form group.\r\n * @returns A `FormGroupSignal` instance.\r\n *\r\n * @example\r\n * // Create a simple form group:\r\n * const user = signal({ name: 'John Doe', age: 30 });\r\n * const form = formGroup(user, {\r\n * name: formControl(derived(user, 'name')),\r\n * age: formControl(derived(user, 'age')),\r\n * })\r\n *\r\n * // Create a nested form group:\r\n * const user = signal({ name: 'John', age: 30, address: {street: \"Some street\"} });\r\n *\r\n * const address = derived(user, 'address');\r\n * const userForm = formGroup(user, {\r\n * name: formControl(derived(user, 'name')),\r\n * age: formControl(derived(user, 'age')),\r\n * address: formGroup(address, {\r\n * street: formControl(derived(address, (address) => address.street), {\r\n * validator: () => (value) => value ? \"\" : \"required!\"\r\n * }) // you can create deeply nested structures.\r\n * })\r\n * });\r\n *\r\n * // Create a form group with dynamically created children replaced rare FormRecord requirements.\r\n * const showAddress = signal(false);\r\n * type Characteristic = {\r\n * valueType: 'string';\r\n * value: string;\r\n * } | {\r\n * valueType: 'number';\r\n * value: number;\r\n * }\r\n * const char = signal<Characteristic>({ valueType: 'string', value: '' });\r\n * const charForm = formGroup(char, () => {\r\n * if (char().valueType === 'string) return createStringControl(char);\r\n * return createNumberControl(char);\r\n * });\r\n *\r\n */\r\nexport function formGroup<\r\n T,\r\n TDerivations extends Record<string, FormControlSignal<any, T, any, any>>,\r\n TParent = undefined,\r\n>(\r\n initial: DerivedSignal<TParent, T> | T | WritableSignal<T>,\r\n providedChildren: (() => TDerivations) | TDerivations,\r\n opt?: CreateFormGroupOptions<T, TDerivations>,\r\n): FormGroupSignal<T, TDerivations, TParent> {\r\n const valueSignal = isSignal(initial) ? initial : signal(initial);\r\n // we fake a derivation if not present, so that .from is present on the signal\r\n const value = isDerivation<TParent, T>(valueSignal)\r\n ? valueSignal\r\n : toFakeSignalDerivation<TParent, T>(valueSignal);\r\n\r\n // we allow for a function/signal to be passed, this case should only be used if the child controls change dependent upon something, say if a formControl is flipped into a formGroup.\r\n const children =\r\n typeof providedChildren === 'function'\r\n ? computed(() => providedChildren())\r\n : computed(() => providedChildren);\r\n\r\n // array allows for easier handling\r\n const derivationsArray = computed(() => Object.values(children()));\r\n\r\n const childrenDirty = computed(\r\n () =>\r\n !!derivationsArray().length && derivationsArray().some((d) => d.dirty()),\r\n );\r\n\r\n // by default dont compare object references, just use childrenDirtySignal\r\n const baseDirtyEq = opt?.dirtyEquality ?? opt?.equal ?? (() => true);\r\n\r\n // function which calls a signal becomes a signal\r\n const dirtyEquality = (a: T, b: T) => {\r\n return baseDirtyEq(a, b) && !childrenDirty();\r\n };\r\n\r\n // group control\r\n const ctrl = formControl<T, TParent, 'group'>(value, {\r\n ...opt,\r\n dirtyEquality,\r\n controlType: 'group',\r\n readonly: () => {\r\n // readonly if is readonly or all children are readonly\r\n if (opt?.readonly?.()) return true;\r\n return (\r\n !!derivationsArray().length &&\r\n derivationsArray().every((d) => d.readonly())\r\n );\r\n },\r\n disable: () => {\r\n if (opt?.disable?.()) return true;\r\n return (\r\n !!derivationsArray().length &&\r\n derivationsArray().every((d) => d.disabled())\r\n );\r\n },\r\n }) satisfies FormControlSignal<T, TParent, 'group'>;\r\n\r\n const childrenTouched = computed(\r\n () =>\r\n !!derivationsArray().length &&\r\n derivationsArray().some((d) => d.touched()),\r\n );\r\n\r\n const touched = computed(() => ctrl.touched() || childrenTouched());\r\n\r\n const childError = computed(() => {\r\n if (!derivationsArray().length) return '';\r\n return derivationsArray()\r\n .map((d) => (d.error() ? `${d.label()}: ${d.error()}` : ''))\r\n .filter(Boolean)\r\n .join('\\n');\r\n });\r\n\r\n const error = computed(() => {\r\n const ownError = ctrl.error();\r\n if (ownError) return ownError;\r\n return childError() ? 'INVALID' : '';\r\n });\r\n\r\n const markAllAsTouched = () => {\r\n ctrl.markAllAsTouched();\r\n for (const ctrl of untracked(derivationsArray)) {\r\n ctrl.markAllAsTouched();\r\n }\r\n };\r\n\r\n const markAllAsPristine = () => {\r\n ctrl.markAllAsPristine();\r\n for (const ctrl of untracked(derivationsArray)) {\r\n ctrl.markAllAsPristine();\r\n }\r\n };\r\n\r\n const reconcile = (newValue: T) => {\r\n // set the children values based on the derivation of the new value\r\n for (const ctrl of untracked(derivationsArray)) {\r\n const from = ctrl.from;\r\n if (!from) continue;\r\n ctrl.reconcile(from(newValue));\r\n }\r\n ctrl.reconcile(mergeIfObject(newValue, untracked(value)));\r\n };\r\n\r\n const forceReconcile = (newValue: T) => {\r\n for (const ctrl of untracked(derivationsArray)) {\r\n const from = ctrl.from;\r\n if (!from) continue;\r\n ctrl.forceReconcile(from(newValue));\r\n }\r\n ctrl.forceReconcile(newValue);\r\n };\r\n\r\n const createBaseValueFn = opt?.createBasePartialValue;\r\n\r\n const basePartialValue: Signal<\r\n Partial<DerivationPartialValues<TDerivations>>\r\n > = createBaseValueFn\r\n ? computed(() => createBaseValueFn(ctrl.value()))\r\n : computed(() => ({}));\r\n\r\n const partialValue = computed(() => {\r\n const obj: Partial<DerivationPartialValues<TDerivations>> = {\r\n ...basePartialValue(),\r\n };\r\n\r\n if (!ctrl.dirty()) return obj;\r\n\r\n for (const [key, ctrl] of Object.entries(children())) {\r\n const pv = ctrl.partialValue();\r\n\r\n if (pv === undefined) continue;\r\n (obj as AnyObject)[key] = pv;\r\n }\r\n\r\n return obj;\r\n });\r\n\r\n const childrenValid = computed(() => {\r\n if (!derivationsArray().length) return true;\r\n return derivationsArray().every((d) => d.valid());\r\n });\r\n\r\n const childrenPending = computed(\r\n () =>\r\n !!derivationsArray().length &&\r\n derivationsArray().some((d) => d.pending()),\r\n );\r\n\r\n return {\r\n ...ctrl,\r\n children,\r\n partialValue,\r\n reconcile,\r\n forceReconcile,\r\n ownError: ctrl.error,\r\n touched,\r\n error,\r\n valid: computed(() => ctrl.valid() && childrenValid()),\r\n pending: computed(() => ctrl.pending() || childrenPending()),\r\n markAllAsPristine,\r\n markAllAsTouched,\r\n reset: () => {\r\n for (const ctrl of untracked(derivationsArray)) {\r\n ctrl.reset();\r\n }\r\n ctrl.reset();\r\n },\r\n resetWithInitial: (initial: T) => {\r\n for (const ctrl of untracked(derivationsArray)) {\r\n const from = ctrl.from;\r\n if (from) ctrl.resetWithInitial(from(initial));\r\n else ctrl.reset();\r\n }\r\n ctrl.resetWithInitial(initial);\r\n },\r\n };\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mmstack-form-core.mjs","sources":["../../../../../packages/form/core/src/lib/util.ts","../../../../../packages/form/core/src/lib/form-control.ts","../../../../../packages/form/core/src/lib/form-array.ts","../../../../../packages/form/core/src/lib/form-group.ts","../../../../../packages/form/core/src/mmstack-form-core.ts"],"sourcesContent":["/**\n * Merges two arrays element by element using the `mergeIfObject` logic.\n *\n * The resulting array will have the same length as the `next` array.\n * For each index `i`, the element in the resulting array is determined by:\n * `mergeIfObject(prev[i], next[i])`.\n * If `prev` is shorter than `next`, `prev[i]` will be `undefined` for the out-of-bounds indices.\n *\n * @template {any[]} T The array type being merged.\n * @param {T} prev The previous array.\n * @param {T} next The next array.\n * @returns {T} A new array containing the merged elements.\n * @example\n * const prev = [1, { id: 1, name: \"A\" }, [10], \"extraPrev\"];\n * const next = [2, { id: 1, status: \"B\" }, [20, 21], missing , { id: 2 }];\n *\n * mergeArray(prev, next);\n * // Result approx:\n * // [\n * // 2, // Primitive replaced\n * // { id: 1, name: \"A\", status: \"B\" }, // Objects shallow-merged\n * // [20, 21], // Arrays replaced (via mergeIfObject -> mergeArray)\n * // undefined, // Primitive replaced by missing item in sparse 'next' array\n * // { id: 2 } // Added from 'next' (prev[4] was undefined)\n * // ]\n */\nexport function mergeArray<T extends any[]>(prev: T, next: T): T {\n return next.map((item, index): T[number] =>\n mergeIfObject<T[number]>(prev[index], item),\n ) as T;\n}\n\n/**\n * Merges two values (`prev`, `next`), prioritizing `next` in most cases.\n *\n * Behavior:\n * - If both `prev` and `next` are non-null, non-array objects, it performs a **shallow merge**\n * (`{ ...prev, ...next }`), where properties from `next` overwrite those in `prev`.\n * - If both `prev` and `next` are arrays, it delegates to `mergeArray` for element-wise merging.\n * - In all other scenarios (type mismatch, primitives, null involved, array mixed with object),\n * it simply returns the `next` value.\n *\n * @template T The type of the values being merged.\n * @param {T | undefined} prev The previous value (can be undefined if accessed out of array bounds).\n * @param {T} next The next value.\n * @returns {T} The merged result based on the rules above.\n */\nexport function mergeIfObject<T>(prev: T, next: T): T {\n if (typeof prev !== typeof next) return next;\n if (typeof prev !== 'object' || typeof next !== 'object') return next;\n if (prev === null || next === null) return next;\n if (Array.isArray(prev) && Array.isArray(next)) return mergeArray(prev, next);\n if (Array.isArray(prev) || Array.isArray(next)) return next;\n\n return { ...prev, ...next };\n}\n\n/**\n * Generates a unique ID using crypto.randomUUID if available,\n * otherwise falls back to a non-secure random string.\n * @returns {string}\n */\nexport function generateID() {\n if (globalThis.crypto?.randomUUID) {\n return globalThis.crypto.randomUUID();\n }\n return Math.random().toString(36).substring(2);\n}\n","import {\n computed,\n isSignal,\n signal,\n untracked,\n type CreateSignalOptions,\n type Signal,\n type ValueEqualityFn,\n type WritableSignal,\n} from '@angular/core';\nimport { type DerivedSignal } from '@mmstack/primitives';\nimport { generateID } from './util';\n\n/**\n * Represents the type of a form control.\n * - `control`: A single form control (e.g., an input field).\n * - `array`: An array of form controls (like Angular's `FormArray`).\n * - `group`: A group of form controls (like Angular's `FormGroup`).\n */\nexport type ControlType = 'control' | 'array' | 'group';\n\n/**\n * Represents a reactive form control. It holds the value, validation status, and other\n * metadata for a form field. This is the core building block for creating reactive forms\n * with signals.\n *\n * @typeParam T - The type of the form control's value.\n * @typeParam TParent - The type of the parent form control's value (if this control is part of a group or array). Defaults to `undefined`.\n * @typeParam TControlType - The type of the control ('control', 'array', or 'group'). Defaults to 'control'.\n * @typeParam TPartialValue - The type of the partial value, used for patching.\n */\nexport type FormControlSignal<\n T,\n TParent = undefined,\n TControlType extends ControlType = 'control',\n TPartialValue = T | undefined,\n> = {\n /** A unique identifier for the control. Used for tracking in `@for` loops. */\n id: string;\n /** The main value signal for the control. */\n value: WritableSignal<T>;\n /** A signal indicating whether the control's value has been changed. */\n dirty: Signal<boolean>;\n /** A signal indicating whether the control has been interacted with (e.g., blurred). */\n touched: Signal<boolean>;\n /** A signal containing the current validation error message (empty string if valid). */\n error: Signal<string>;\n /** A signal indicating whether the control is pending */\n pending: Signal<boolean>;\n /** A signal indicating whether the control is disabled. */\n /** A signal indicating whether the control is in a valid state (without errors & not pending) */\n valid: Signal<boolean>;\n disabled: Signal<boolean>;\n /** A signal indicating whether the control is read-only. */\n readonly: Signal<boolean>;\n /** A signal indicating whether the control is required. */\n required: Signal<boolean>;\n /** A signal containing the label for the control. */\n label: Signal<string>;\n /** A signal containing the hint text for the control. */\n hint: Signal<string>;\n /** Marks the control as touched. */\n markAsTouched: () => void;\n /** Marks the control and all its child controls (if any) as touched. */\n markAllAsTouched: () => void;\n /** Marks the control as pristine (not touched). */\n markAsPristine: () => void;\n /** Marks the control and all its child controls (if any) as pristine. */\n markAllAsPristine: () => void;\n /**\n * Resets the control to a new value and sets a new initial value. This is intended for\n * scenarios where the underlying data is updated externally (e.g., data coming from\n * the server). If the control is not dirty, the value is updated. If the control *is*\n * dirty, the value is *not* updated (preserving user changes).\n */\n reconcile: (newValue: T) => void;\n /**\n * Similar to `reconcile`, but forces the update even if the control is dirty.\n */\n forceReconcile: (newValue: T) => void;\n /** Resets the control's value to its initial value. */\n reset: () => void;\n /** Resets the control's value and initial value. */\n resetWithInitial: (initial: T) => void;\n /**\n * The derivation function used to create this control if it's part of a `formGroup` or `formArray`.\n * @internal\n */\n from?: DerivedSignal<TParent, T>['from'];\n /** The equality function used to compare values. Defaults to `Object.is`. */\n equal: (a: T, b: T) => boolean;\n /** The type of the control ('control', 'array', or 'group'). */\n controlType: TControlType;\n /**\n * A signal representing the partial value of the control, suitable for patching data on a server.\n * It contains the changed value if `dirty` is `true`.\n */\n partialValue: Signal<TPartialValue>;\n};\n\nexport type CreateFormControlOptions<\n T,\n TControlType extends ControlType = ControlType,\n> = CreateSignalOptions<T> & {\n validator?: () => (value: T) => string;\n onTouched?: () => void;\n disable?: () => boolean;\n readonly?: () => boolean;\n required?: () => boolean;\n label?: () => string;\n id?: () => string;\n hint?: () => string;\n dirtyEquality?: ValueEqualityFn<T>;\n onReset?: () => void;\n controlType?: TControlType;\n overrideValidation?: () => string;\n pending?: () => boolean;\n};\n\n/**\n * Creates a `FormControlSignal`, a reactive form control that holds a value and tracks its\n * validity, dirty state, touched state, and other metadata.\n *\n * @typeParam T - The type of the form control's value.\n * @typeParam TParent - The type of the parent form control's value (if this control is part of a group or array).\n * @typeParam TControlType - The type of the control. Defaults to `'control'`.\n * @typeParam TPartialValue - The type of value when patching\n * @param initial - The initial value of the control, or a `DerivedSignal` if this control is part of a `formGroup` or `formArray`.\n * @param options - Optional configuration options for the control.\n * @returns A `FormControlSignal` instance.\n *\n * @example\n * // Create a simple form control:\n * const name = formControl('Initial Name');\n *\n * // Create a form control with validation:\n * const age = formControl(0, {\n * validator: () => (value) => value >= 18 ? '' : 'Must be at least 18',\n * });\n *\n * // Create a derived form control (equivalent to the above, but more explicit):\n * const user = signal({ name: 'John Doe', age: 30 });\n * const name = formControl(derived(user, {\n * from: (u) => u.name,\n * onChange: (newName) => user.update(u => ({...u, name: newName}))\n * }));\n *\n * // Create a form group with nested controls:\n * const user = signal({ name: 'John Doe', age: 30 });\n * const form = formGroup(user, {\n * name: formControl(derived(user, 'name')),\n * age: formControl(derived(user, 'age')),\n * })\n */\nexport function formControl<\n T,\n TParent = undefined,\n TControlType extends ControlType = 'control',\n TPartialValue = T | undefined,\n>(\n initial: DerivedSignal<TParent, T> | T,\n opt?: CreateFormControlOptions<T, TControlType>,\n): FormControlSignal<T, TParent, TControlType, TPartialValue> {\n const value = isSignal(initial) ? initial : signal(initial, opt);\n const initialValue = signal(untracked(value));\n const eq = opt?.equal ?? Object.is;\n\n const dirtyEq = opt?.dirtyEquality ?? eq;\n\n const disabled = computed(() => opt?.disable?.() ?? false);\n const readonly = computed(() => opt?.readonly?.() ?? false);\n\n const dirty = computed(() => !dirtyEq(value(), initialValue()));\n\n const touched = signal(false);\n\n const validator = computed(() => opt?.validator?.() ?? (() => ''));\n\n const error = computed(() => {\n if (opt?.overrideValidation) return opt.overrideValidation();\n if (disabled() || readonly()) return '';\n return validator()(value());\n });\n\n const markAsTouched = () => {\n touched.set(true);\n opt?.onTouched?.();\n };\n const markAllAsTouched = markAsTouched;\n\n const markAsPristine = () => touched.set(false);\n const markAllAsPristine = markAsPristine;\n\n const label = computed(() => opt?.label?.() ?? '');\n\n const partialValue = computed(() => (dirty() ? value() : undefined));\n\n const internalReconcile = (newValue: T, force = false) => {\n const isDirty = untracked(dirty);\n\n if (!isDirty || force) {\n // very dangerous use of untracked here, don't do this everywhere :)\n // thanks to u/synalx for the idea to use untracked here\n\n untracked(() => {\n initialValue.set(newValue);\n value.set(newValue);\n });\n }\n };\n\n const pending = computed(() => opt?.pending?.() ?? false);\n\n return {\n id: opt?.id?.() ?? generateID(),\n value,\n dirty,\n touched,\n error,\n label,\n required: computed(() => opt?.required?.() ?? false),\n disabled,\n readonly,\n pending,\n valid: computed(() => !pending() && !error()),\n hint: computed(() => opt?.hint?.() ?? ''),\n markAsTouched,\n markAllAsTouched,\n markAsPristine,\n markAllAsPristine,\n from: (isSignal(initial) ? initial.from : undefined) as FormControlSignal<\n T,\n TParent,\n TControlType\n >['from'],\n reconcile: (newValue: T) => internalReconcile(newValue),\n forceReconcile: (newValue: T) => internalReconcile(newValue, true),\n reset: () => {\n opt?.onReset?.();\n value.set(untracked(initialValue));\n },\n resetWithInitial: (initial: T) => {\n opt?.onReset?.();\n initialValue.set(initial);\n value.set(initial);\n },\n equal: eq,\n controlType: (opt?.controlType ?? 'control') as TControlType,\n partialValue: partialValue as Signal<TPartialValue>,\n };\n}\n","import {\n computed,\n linkedSignal,\n untracked,\n type Signal,\n type WritableSignal,\n} from '@angular/core';\nimport { derived, type DerivedSignal } from '@mmstack/primitives';\nimport {\n formControl,\n type CreateFormControlOptions,\n type FormControlSignal,\n} from './form-control';\nimport { type SignalValue } from './signal-value.type';\nimport { mergeArray } from './util';\n\nexport type FormArraySignal<\n T,\n TIndividualState extends FormControlSignal<\n T,\n any,\n any,\n any\n > = FormControlSignal<T, any, any, any>,\n TParent = undefined,\n> = FormControlSignal<\n T[],\n TParent,\n 'array',\n | Exclude<SignalValue<TIndividualState['partialValue']>, null | undefined>[]\n | undefined\n> & {\n ownError: Signal<string>;\n children: Signal<TIndividualState[]>;\n push: (value: T) => void; // add new control with value\n remove: (index: number) => void; // remove at index\n min: Signal<number>; // for display purposes\n max: Signal<number>; // for display purposes\n canAdd: Signal<boolean>; // disable add button if false\n canRemove: Signal<boolean>; // disable remove buttons if false\n};\n\nexport type CreateFormArraySignalOptions<\n T,\n TIndividualState extends FormControlSignal<T, any, any, any>,\n> = Omit<CreateFormControlOptions<T[]>, 'equal'> & {\n min?: () => number;\n max?: () => number;\n equal?: (a: T, b: T) => boolean;\n toPartialValue?: (\n v: T,\n ) => Exclude<SignalValue<TIndividualState['partialValue']>, null | undefined>;\n};\n\nfunction createReconcileChildren<\n T,\n TIndividualState extends FormControlSignal<T, any, any, any>,\n>(\n factory: (val: DerivedSignal<T[], T>, idx: number) => TIndividualState,\n opt: { equal: (a: T, b: T) => boolean },\n) {\n return (\n length: number,\n source: WritableSignal<T[]>,\n prev?: TIndividualState[],\n ): TIndividualState[] => {\n if (!prev) {\n const nextControls = [];\n\n for (let i = 0; i < length; i++) {\n nextControls.push(\n factory(derived(source, i, { equal: opt?.equal }), i),\n );\n }\n\n return nextControls;\n }\n\n if (length === prev.length) return prev;\n\n const next = [...prev];\n\n if (length < prev.length) {\n next.splice(length);\n } else if (length > prev.length) {\n for (let i = prev.length; i < length; i++) {\n next.push(factory(derived(source, i, { equal: opt?.equal }), i));\n }\n }\n\n return next;\n };\n}\n\nexport function formArray<\n T,\n TIndividualState extends FormControlSignal<\n T,\n any,\n any,\n any\n > = FormControlSignal<T, any, any, any>,\n TParent = undefined,\n>(\n initial: T[] | DerivedSignal<TParent, T[]>,\n factory: (val: DerivedSignal<T[], T>, idx: number) => TIndividualState,\n opt?: CreateFormArraySignalOptions<T, TIndividualState>,\n): FormArraySignal<T, TIndividualState, TParent> {\n const eq = opt?.equal ?? Object.is;\n\n const arrayEqual = (a: T[], b: T[]) => {\n if (a.length !== b.length) return false;\n if (!a.length) return true;\n\n return a.every((v, i) => eq(v, b[i]));\n };\n\n const min = computed(() => opt?.min?.() ?? 0);\n const max = computed(() => opt?.max?.() ?? Number.MAX_SAFE_INTEGER);\n\n const arrayOptions: CreateFormControlOptions<T[], 'array'> = {\n ...opt,\n equal: arrayEqual,\n dirtyEquality: (a, b) => a.length === b.length,\n controlType: 'array',\n };\n\n const ctrl = formControl<T[], TParent, 'array'>(\n initial,\n arrayOptions,\n ) satisfies FormControlSignal<T[], TParent, 'array'>;\n\n const length = computed(() => ctrl.value().length);\n\n const reconcileChildren = createReconcileChildren<T, TIndividualState>(\n factory,\n { equal: eq },\n );\n\n // linkedSignal used to re-use previous value so that only length changes are affected and existing controls are kept, but updated\n const children = linkedSignal<number, TIndividualState[]>({\n source: () => length(),\n computation: (len, prev) => reconcileChildren(len, ctrl.value, prev?.value),\n });\n\n const ownError = computed(() => ctrl.error());\n\n const error = computed((): string => {\n const own = ownError();\n if (own) return own;\n if (!children().length) return '';\n return children()\n .map((c, idx) => (c.error() ? `${idx}: ${c.error()}` : ''))\n .filter(Boolean)\n .join('\\n');\n });\n\n const dirty = computed(() => {\n if (ctrl.dirty()) return true;\n if (!children().length) return false;\n return children().some((c) => c.dirty());\n });\n\n const markAllAsTouched = () => {\n ctrl.markAllAsTouched();\n for (const c of untracked(children)) {\n c.markAllAsTouched();\n }\n };\n const markAllAsPristine = () => {\n ctrl.markAllAsPristine();\n for (const c of untracked(children)) {\n c.markAllAsPristine();\n }\n };\n\n const toPartialValue = opt?.toPartialValue ?? ((v: T) => v);\n const partialValue = computed(() => {\n if (!dirty()) return undefined;\n return children().map((c) => {\n const pv = c.partialValue();\n if (pv) return pv;\n if (c.controlType === 'control') return undefined;\n\n // return full value for child objects/arrays as this cannot be partially patched without idx\n return toPartialValue(c.value());\n });\n });\n\n const touched = computed(\n () =>\n ctrl.touched() ||\n !!(children().length && children().some((c) => c.touched())),\n );\n\n const reconcile = (newValue: T[]) => {\n const ctrls = untracked(children);\n\n for (let i = 0; i < newValue.length; i++) {\n ctrls.at(i)?.reconcile(newValue[i]); // reconcile existing controls that are relevant addition/removal will be handled after ctrl.reconcile through linkedSignal\n }\n\n ctrl.reconcile(mergeArray(newValue, untracked(ctrl.value)));\n };\n\n const forceReconcile = (newValue: T[]) => {\n const ctrls = untracked(children);\n\n for (let i = 0; i < newValue.length; i++) {\n ctrls.at(i)?.forceReconcile(newValue[i]);\n }\n\n ctrl.forceReconcile(newValue);\n };\n\n const childrenValid = computed(() => {\n if (!children().length) return true;\n return children().every((d) => d.valid());\n });\n\n const childrenPending = computed(\n () => !!children().length && children().some((d) => d.pending()),\n );\n\n return {\n ...ctrl,\n ownError,\n error,\n valid: computed(() => ctrl.valid() && childrenValid()),\n pending: computed(() => ctrl.pending() || childrenPending()),\n touched,\n children,\n dirty,\n markAllAsTouched,\n markAllAsPristine,\n min,\n max,\n partialValue,\n canAdd: computed(\n () => !ctrl.disabled() && !ctrl.readonly() && length() < max(),\n ),\n canRemove: computed(\n () => !ctrl.disabled() && !ctrl.readonly() && length() > min(),\n ),\n reconcile,\n forceReconcile,\n reset: () => {\n for (const c of untracked(children)) {\n c.reset();\n }\n ctrl.reset();\n },\n resetWithInitial: (initial: T[]) => {\n const ctrls = untracked(children);\n for (let i = 0; i < initial.length; i++) {\n ctrls.at(i)?.resetWithInitial(initial[i]);\n }\n ctrl.resetWithInitial(initial);\n },\n push: (next) => ctrl.value.update((cur) => [...cur, next]),\n remove: (idx) =>\n ctrl.value.update((cur) => cur.filter((_, i) => i !== idx)),\n };\n}\n","import {\n computed,\n isSignal,\n signal,\n untracked,\n type Signal,\n type WritableSignal,\n} from '@angular/core';\nimport {\n isDerivation,\n toFakeSignalDerivation,\n type DerivedSignal,\n} from '@mmstack/primitives';\nimport {\n formControl,\n type CreateFormControlOptions,\n type FormControlSignal,\n} from './form-control';\nimport { type SignalValue } from './signal-value.type';\nimport { mergeIfObject } from './util';\n\ntype AnyObject = Record<PropertyKey, any>;\n\n/**\n * Extracts the partial value types from a record of `FormControlSignal` instances.\n * This is used to construct the `partialValue` type for `FormGroupSignal`.\n * @internal\n */\ntype DerivationPartialValues<\n TDerivations extends Record<string, FormControlSignal<any, any, any, any>>,\n> = {\n [K in keyof TDerivations]: Exclude<\n SignalValue<TDerivations[K]['partialValue']>,\n undefined\n >;\n};\n\n/**\n * Represents a group of form controls, similar to Angular's `FormGroup`. It aggregates\n * the values and states of its child controls into a single object.\n *\n * @typeParam T - The type of the form group's value (an object).\n * @typeParam TDerivations - A record where keys are the names of the child controls and values are the `FormControlSignal` instances.\n * @typeParam TParent - The type of the parent form control's value (if this group is nested).\n */\nexport type FormGroupSignal<\n T,\n TDerivations extends Record<string, FormControlSignal<any, T, any, any>>,\n TParent = undefined,\n> = FormControlSignal<\n T,\n TParent,\n 'group',\n Partial<DerivationPartialValues<TDerivations>>\n> & {\n /**\n * A signal that holds a record of the child form controls. The keys are the names\n * of the controls, and the values are the `FormControlSignal` instances.\n */\n children: Signal<TDerivations>;\n /**\n * A signal that holds the validation error message of the group itself (excluding child errors).\n */\n ownError: Signal<string>;\n};\n\n/**\n * Options for creating a `FormGroupSignal`. Extends `CreateFormControlOptions`.\n */\nexport type CreateFormGroupOptions<\n T,\n TDerivations extends Record<string, FormControlSignal<any, T, any, any>>,\n> = CreateFormControlOptions<T, 'group'> & {\n /**\n * An optional function to create a base object for the `partialValue` signal.\n * This can be used to pre-populate the partial value with default values or\n * to perform custom logic before merging in the partial values from child controls.\n */\n createBasePartialValue?: (\n value: T,\n ) => Partial<DerivationPartialValues<TDerivations>>;\n};\n\n/**\n * Creates a `FormGroupSignal`, which aggregates a set of child form controls into a single object.\n *\n * @typeParam T - The type of the form group's value (an object).\n * @typeParam TDerivations - A record where keys are the names of the child controls and values are the `FormControlSignal` instances.\n * @typeParam TParent - The type of the parent form control's value (if this group is nested within another group or array).\n * @param initial - The initial value of the form group (or a `WritableSignal` or `DerivedSignal` if the group is nested).\n * @param providedChildren - An object containing the child `FormControlSignal` instances, or a function that returns such an object.\n * Using a function allows for dynamic creation of child controls (e.g., in response to changes in other signals).\n * @param options - Optional configuration options for the form group.\n * @returns A `FormGroupSignal` instance.\n *\n * @example\n * // Create a simple form group:\n * const user = signal({ name: 'John Doe', age: 30 });\n * const form = formGroup(user, {\n * name: formControl(derived(user, 'name')),\n * age: formControl(derived(user, 'age')),\n * })\n *\n * // Create a nested form group:\n * const user = signal({ name: 'John', age: 30, address: {street: \"Some street\"} });\n *\n * const address = derived(user, 'address');\n * const userForm = formGroup(user, {\n * name: formControl(derived(user, 'name')),\n * age: formControl(derived(user, 'age')),\n * address: formGroup(address, {\n * street: formControl(derived(address, (address) => address.street), {\n * validator: () => (value) => value ? \"\" : \"required!\"\n * }) // you can create deeply nested structures.\n * })\n * });\n *\n * // Create a form group with dynamically created children replaced rare FormRecord requirements.\n * const showAddress = signal(false);\n * type Characteristic = {\n * valueType: 'string';\n * value: string;\n * } | {\n * valueType: 'number';\n * value: number;\n * }\n * const char = signal<Characteristic>({ valueType: 'string', value: '' });\n * const charForm = formGroup(char, () => {\n * if (char().valueType === 'string) return createStringControl(char);\n * return createNumberControl(char);\n * });\n *\n */\nexport function formGroup<\n T,\n TDerivations extends Record<string, FormControlSignal<any, T, any, any>>,\n TParent = undefined,\n>(\n initial: DerivedSignal<TParent, T> | T | WritableSignal<T>,\n providedChildren: (() => TDerivations) | TDerivations,\n opt?: CreateFormGroupOptions<T, TDerivations>,\n): FormGroupSignal<T, TDerivations, TParent> {\n const valueSignal = isSignal(initial) ? initial : signal(initial);\n // we fake a derivation if not present, so that .from is present on the signal\n const value = isDerivation<TParent, T>(valueSignal)\n ? valueSignal\n : toFakeSignalDerivation<TParent, T>(valueSignal);\n\n // we allow for a function/signal to be passed, this case should only be used if the child controls change dependent upon something, say if a formControl is flipped into a formGroup.\n const children =\n typeof providedChildren === 'function'\n ? computed(() => providedChildren())\n : computed(() => providedChildren);\n\n // array allows for easier handling\n const derivationsArray = computed(() => Object.values(children()));\n\n const childrenDirty = computed(\n () =>\n !!derivationsArray().length && derivationsArray().some((d) => d.dirty()),\n );\n\n // by default dont compare object references, just use childrenDirtySignal\n const baseDirtyEq = opt?.dirtyEquality ?? opt?.equal ?? (() => true);\n\n // function which calls a signal becomes a signal\n const dirtyEquality = (a: T, b: T) => {\n return baseDirtyEq(a, b) && !childrenDirty();\n };\n\n // group control\n const ctrl = formControl<T, TParent, 'group'>(value, {\n ...opt,\n dirtyEquality,\n controlType: 'group',\n readonly: () => {\n // readonly if is readonly or all children are readonly\n if (opt?.readonly?.()) return true;\n return (\n !!derivationsArray().length &&\n derivationsArray().every((d) => d.readonly())\n );\n },\n disable: () => {\n if (opt?.disable?.()) return true;\n return (\n !!derivationsArray().length &&\n derivationsArray().every((d) => d.disabled())\n );\n },\n }) satisfies FormControlSignal<T, TParent, 'group'>;\n\n const childrenTouched = computed(\n () =>\n !!derivationsArray().length &&\n derivationsArray().some((d) => d.touched()),\n );\n\n const touched = computed(() => ctrl.touched() || childrenTouched());\n\n const childError = computed(() => {\n if (!derivationsArray().length) return '';\n return derivationsArray()\n .map((d) => (d.error() ? `${d.label()}: ${d.error()}` : ''))\n .filter(Boolean)\n .join('\\n');\n });\n\n const error = computed(() => {\n const ownError = ctrl.error();\n if (ownError) return ownError;\n return childError() ? 'INVALID' : '';\n });\n\n const markAllAsTouched = () => {\n ctrl.markAllAsTouched();\n for (const ctrl of untracked(derivationsArray)) {\n ctrl.markAllAsTouched();\n }\n };\n\n const markAllAsPristine = () => {\n ctrl.markAllAsPristine();\n for (const ctrl of untracked(derivationsArray)) {\n ctrl.markAllAsPristine();\n }\n };\n\n const reconcile = (newValue: T) => {\n // set the children values based on the derivation of the new value\n for (const ctrl of untracked(derivationsArray)) {\n const from = ctrl.from;\n if (!from) continue;\n ctrl.reconcile(from(newValue));\n }\n ctrl.reconcile(mergeIfObject(newValue, untracked(value)));\n };\n\n const forceReconcile = (newValue: T) => {\n for (const ctrl of untracked(derivationsArray)) {\n const from = ctrl.from;\n if (!from) continue;\n ctrl.forceReconcile(from(newValue));\n }\n ctrl.forceReconcile(newValue);\n };\n\n const createBaseValueFn = opt?.createBasePartialValue;\n\n const basePartialValue: Signal<\n Partial<DerivationPartialValues<TDerivations>>\n > = createBaseValueFn\n ? computed(() => createBaseValueFn(ctrl.value()))\n : computed(() => ({}));\n\n const partialValue = computed(() => {\n const obj: Partial<DerivationPartialValues<TDerivations>> = {\n ...basePartialValue(),\n };\n\n if (!ctrl.dirty()) return obj;\n\n for (const [key, ctrl] of Object.entries(children())) {\n const pv = ctrl.partialValue();\n\n if (pv === undefined) continue;\n (obj as AnyObject)[key] = pv;\n }\n\n return obj;\n });\n\n const childrenValid = computed(() => {\n if (!derivationsArray().length) return true;\n return derivationsArray().every((d) => d.valid());\n });\n\n const childrenPending = computed(\n () =>\n !!derivationsArray().length &&\n derivationsArray().some((d) => d.pending()),\n );\n\n return {\n ...ctrl,\n children,\n partialValue,\n reconcile,\n forceReconcile,\n ownError: ctrl.error,\n touched,\n error,\n valid: computed(() => ctrl.valid() && childrenValid()),\n pending: computed(() => ctrl.pending() || childrenPending()),\n markAllAsPristine,\n markAllAsTouched,\n reset: () => {\n for (const ctrl of untracked(derivationsArray)) {\n ctrl.reset();\n }\n ctrl.reset();\n },\n resetWithInitial: (initial: T) => {\n for (const ctrl of untracked(derivationsArray)) {\n const from = ctrl.from;\n if (from) ctrl.resetWithInitial(from(initial));\n else ctrl.reset();\n }\n ctrl.resetWithInitial(initial);\n },\n };\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmstack/form-core",
3
- "version": "21.0.0",
3
+ "version": "21.0.1",
4
4
  "keywords": [
5
5
  "angular",
6
6
  "signals",