@bgroup/wise-form 1.0.8 → 1.0.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgroup/wise-form",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "Wise Form - A reactive form library",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -33,20 +33,78 @@ export class FormField extends ReactiveModel<IFormField> {
33
33
  get disabled() {
34
34
  if (typeof this.#disabled !== 'object' || !this.#disabled?.fields) return this.#disabled;
35
35
 
36
- const validate = field => {
37
- if (typeof field !== 'object') return !this.#parent.form.getField(field).value;
38
- const { name, value } = field;
39
- const fieldInstance = this.#parent.getField(name);
36
+ const { action, operator = 'or' } = this.#disabled;
37
+ const isEnableAction = action === 'enable';
38
+
39
+ const validate = fieldSettings => {
40
+ // 1. Get the target field instance
41
+ const name = typeof fieldSettings === 'string' ? fieldSettings : fieldSettings.name;
42
+ const fieldInstance = this.#parent.form.getField(name);
43
+
44
+ // If field dependency is missing, we can't evaluate.
40
45
  if (!fieldInstance) return false;
41
- if (field.hasOwnProperty('condition')) {
42
- const compare = this.evaluations[field.condition](fieldInstance.value, field.value);
43
- return compare;
46
+
47
+ // 2. Determine the value to check from that field
48
+ let currentValue;
49
+ if (typeof fieldSettings === 'object' && fieldSettings.property) {
50
+ // Access specific property (e.g. 'entries', 'length', 'value')
51
+ const props = fieldInstance.getProperties();
52
+ const propPath = fieldSettings.property.split('.');
53
+
54
+ let val: any = props;
55
+ // If property is 'value', start from fieldInstance.value
56
+ if (propPath[0] === 'value') {
57
+ val = fieldInstance.value;
58
+ propPath.shift(); // consume 'value'
59
+ }
60
+
61
+ // Traverse path safely
62
+ for (const p of propPath) {
63
+ if (val === undefined || val === null) break;
64
+ val = val[p];
65
+ }
66
+ currentValue = val;
67
+ } else {
68
+ // Default: use the field's main value
69
+ currentValue = fieldInstance.value;
70
+ }
71
+
72
+ // 3. Simple boolean check if settings is just a string
73
+ if (typeof fieldSettings !== 'object') {
74
+ return !currentValue;
75
+ }
76
+
77
+ // 4. Determine comparison value
78
+ let comparisonValue = fieldSettings.value;
79
+ if (fieldSettings.valueFromField) {
80
+ const compareField = this.#parent.form.getField(fieldSettings.valueFromField);
81
+ comparisonValue = compareField ? compareField.value : undefined;
44
82
  }
45
- const { value: fieldValue } = fieldInstance;
46
- return value !== fieldValue;
83
+
84
+ // 5. Evaluate condition
85
+ const condition = fieldSettings.condition;
86
+ if (condition && this.evaluations[condition]) {
87
+ return this.evaluations[condition](currentValue, comparisonValue);
88
+ }
89
+
90
+ // Default behavior
91
+ return currentValue !== comparisonValue;
47
92
  };
48
93
 
49
- return this.#disabled.fields.some(validate);
94
+ const results = this.#disabled.fields.map(validate);
95
+
96
+ let conditionsMet = false;
97
+ if (operator === 'and') {
98
+ conditionsMet = results.every(r => r === true);
99
+ } else {
100
+ conditionsMet = results.some(r => r === true);
101
+ }
102
+
103
+ if (isEnableAction) {
104
+ return !conditionsMet;
105
+ }
106
+
107
+ return conditionsMet;
50
108
  }
51
109
 
52
110
  set disabled(value) {
@@ -184,34 +242,34 @@ export class FormField extends ReactiveModel<IFormField> {
184
242
  if (typeof props.disabled !== 'object') {
185
243
  throw new Error(`The disabled property of the field ${props.name} must be a boolean or an object`);
186
244
  }
187
- if (!props.disabled.fields && !props.disabled.mode) {
188
- throw new Error(`The disabled property of the field ${props.name} must have a fields property or a mode defined`);
189
- }
190
-
191
245
  if (props.disabled.mode) {
192
246
  // posible modes : create, update;
193
247
  this.#disabled = this.#parent.form.mode === props.disabled.mode;
194
248
  return;
195
249
  }
196
250
 
197
- let allValid;
198
- props.disabled.fields.forEach(item => {
199
- const name = typeof item === 'string' ? item : item.name;
200
-
201
- const instance = this.#parent.form.getField(name);
202
- allValid = instance;
203
- if (!allValid) return;
204
- instance.on('change', this.#listenSiblings);
205
- instance.on('value.change', this.#listenSiblings);
206
- this.#listeningItems.set(name, {
207
- item: instance,
208
- listener: this.#listenSiblings,
209
- });
210
- });
251
+ if (props.disabled.fields && Array.isArray(props.disabled.fields)) {
252
+ props.disabled.fields.forEach(item => {
253
+ const namesToListen: string[] = [];
254
+ if (typeof item === 'string') {
255
+ namesToListen.push(item);
256
+ } else {
257
+ if (item.name) namesToListen.push(item.name);
258
+ if (item.valueFromField) namesToListen.push(item.valueFromField);
259
+ }
211
260
 
212
- if (!allValid) {
213
- const fieldName = this.getProperties().name || 'unknown';
214
- throw new Error(`the field ${allValid} does not exist in the form ${(this.#parent as any).name}, field passed in invalid settings of field "${fieldName}"`);
261
+ namesToListen.forEach(name => {
262
+ const instance = this.#parent.form.getField(name);
263
+ if (!instance) return;
264
+
265
+ instance.on('change', this.#listenSiblings);
266
+ instance.on('value.change', this.#listenSiblings);
267
+ this.#listeningItems.set(name, {
268
+ item: instance,
269
+ listener: this.#listenSiblings,
270
+ });
271
+ });
272
+ });
215
273
  }
216
274
  this.#disabled = props.disabled;
217
275
  }
@@ -1,8 +1,15 @@
1
1
  export type TDisabledSettings = {
2
2
  name: string;
3
3
  value: any;
4
+ condition?: string;
5
+ property?: string;
6
+ operator?: 'and' | 'or';
7
+ valueFromField?: string;
4
8
  };
9
+
5
10
  export interface IDisabled {
6
11
  fields: string[] | TDisabledSettings[];
12
+ action?: 'enable' | 'disable';
13
+ operator?: 'and' | 'or'; // Operator for the top-level list of fields/conditions
7
14
  }
8
15