@axinom/mosaic-ui 0.56.0-rc.5 → 0.56.0-rc.6

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": "@axinom/mosaic-ui",
3
- "version": "0.56.0-rc.5",
3
+ "version": "0.56.0-rc.6",
4
4
  "description": "UI components for building Axinom Mosaic applications",
5
5
  "author": "Axinom",
6
6
  "license": "PROPRIETARY",
@@ -32,7 +32,7 @@
32
32
  "build-storybook": "storybook build"
33
33
  },
34
34
  "dependencies": {
35
- "@axinom/mosaic-core": "^0.4.29-rc.5",
35
+ "@axinom/mosaic-core": "^0.4.29-rc.6",
36
36
  "@faker-js/faker": "^7.4.0",
37
37
  "@geoffcox/react-splitter": "^2.1.2",
38
38
  "@mui/base": "5.0.0-beta.40",
@@ -107,5 +107,5 @@
107
107
  "publishConfig": {
108
108
  "access": "public"
109
109
  },
110
- "gitHead": "02b282719a41213749fe017cb2b2a18bd950a8b6"
110
+ "gitHead": "deae548d43a743e376cfb53bc291fc95fea13946"
111
111
  }
@@ -261,7 +261,7 @@ describe('DynamicListDataEntry', () => {
261
261
  expect(input.prop('disabled')).toBe(true);
262
262
  });
263
263
 
264
- it('accepts default values and sets them', () => {
264
+ it('accepts default values and sets them', async () => {
265
265
  const defaultData: Partial<TestData> = {
266
266
  desc: 'Description',
267
267
  };
@@ -280,15 +280,15 @@ describe('DynamicListDataEntry', () => {
280
280
 
281
281
  const button = wrapper.find(Button);
282
282
 
283
- act(() => {
283
+ await act(async () => {
284
284
  // @ts-expect-error not full event args object
285
- button.prop('onButtonClicked')?.(mockEvent);
285
+ await button.prop('onButtonClicked')?.(mockEvent);
286
286
  });
287
287
 
288
288
  expect(spy).toHaveBeenCalledWith(defaultData);
289
289
  });
290
290
 
291
- it(`does not emit onActionClicked if data is invalid`, () => {
291
+ it(`does not emit onActionClicked if data is invalid`, async () => {
292
292
  const spy = jest.fn();
293
293
  const mockEvent = {
294
294
  e: 'event',
@@ -307,15 +307,15 @@ describe('DynamicListDataEntry', () => {
307
307
 
308
308
  const button = wrapper.find(Button);
309
309
 
310
- act(() => {
310
+ await act(async () => {
311
311
  // @ts-expect-error not full event args object
312
- button.prop('onButtonClicked')?.(mockEvent);
312
+ await button.prop('onButtonClicked')?.(mockEvent);
313
313
  });
314
314
 
315
315
  expect(spy).not.toHaveBeenCalled();
316
316
  });
317
317
 
318
- it(`emits onActionClicked with property name and new value if there is data to send`, () => {
318
+ it(`emits onActionClicked with property name and new value if there is data to send`, async () => {
319
319
  const spy = jest.fn();
320
320
  const mockNewValue = 'test-value';
321
321
  const mockEvent = {
@@ -341,16 +341,16 @@ describe('DynamicListDataEntry', () => {
341
341
 
342
342
  const button = wrapper.find(Button);
343
343
 
344
- act(() => {
344
+ await act(async () => {
345
345
  // @ts-expect-error not full event args object
346
- button.prop('onButtonClicked')?.(mockEvent);
346
+ await button.prop('onButtonClicked')?.(mockEvent);
347
347
  });
348
348
 
349
349
  expect(spy).toHaveBeenCalledTimes(1);
350
350
  expect(spy).toHaveBeenCalledWith({ [propertyName]: mockNewValue });
351
351
  });
352
352
 
353
- it(`emits row data and new position when 'allowReordering' is true, 'newDataPosition' is defined, and is 'positionKey' is defined`, () => {
353
+ it(`emits row data and new position when 'allowReordering' is true, 'newDataPosition' is defined, and is 'positionKey' is defined`, async () => {
354
354
  const spy = jest.fn();
355
355
  const mockEvent = {
356
356
  e: 'event',
@@ -381,9 +381,9 @@ describe('DynamicListDataEntry', () => {
381
381
 
382
382
  const button = wrapper.find(Button);
383
383
 
384
- act(() => {
384
+ await act(async () => {
385
385
  // @ts-expect-error not full event args object
386
- button.prop('onButtonClicked')?.(mockEvent);
386
+ await button.prop('onButtonClicked')?.(mockEvent);
387
387
  });
388
388
 
389
389
  expect(spy).toHaveBeenCalledTimes(1);
@@ -393,7 +393,7 @@ describe('DynamicListDataEntry', () => {
393
393
  });
394
394
  });
395
395
 
396
- it(`emits only row data when 'allowReordering' is false, 'newDataPosition' is defined, and is 'positionKey' is defined`, () => {
396
+ it(`emits only row data when 'allowReordering' is false, 'newDataPosition' is defined, and is 'positionKey' is defined`, async () => {
397
397
  const spy = jest.fn();
398
398
  const mockEvent = {
399
399
  e: 'event',
@@ -423,9 +423,9 @@ describe('DynamicListDataEntry', () => {
423
423
 
424
424
  const button = wrapper.find(Button);
425
425
 
426
- act(() => {
426
+ await act(async () => {
427
427
  // @ts-expect-error not full event args object
428
- button.prop('onButtonClicked')?.(mockEvent);
428
+ await button.prop('onButtonClicked')?.(mockEvent);
429
429
  });
430
430
 
431
431
  expect(spy).toHaveBeenCalledTimes(1);
@@ -434,7 +434,7 @@ describe('DynamicListDataEntry', () => {
434
434
  });
435
435
  });
436
436
 
437
- it(`emits only row data when 'allowReordering' is true, 'newDataPosition' is undefined, and is 'positionKey' is defined`, () => {
437
+ it(`emits only row data when 'allowReordering' is true, 'newDataPosition' is undefined, and is 'positionKey' is defined`, async () => {
438
438
  const spy = jest.fn();
439
439
  const mockEvent = {
440
440
  e: 'event',
@@ -464,9 +464,9 @@ describe('DynamicListDataEntry', () => {
464
464
 
465
465
  const button = wrapper.find(Button);
466
466
 
467
- act(() => {
467
+ await act(async () => {
468
468
  // @ts-expect-error not full event args object
469
- button.prop('onButtonClicked')?.(mockEvent);
469
+ await button.prop('onButtonClicked')?.(mockEvent);
470
470
  });
471
471
 
472
472
  expect(spy).toHaveBeenCalledTimes(1);
@@ -475,7 +475,7 @@ describe('DynamicListDataEntry', () => {
475
475
  });
476
476
  });
477
477
 
478
- it(`emits only row data when 'allowReordering' is true, 'newDataPosition' is defined, and is 'positionKey' is undefined`, () => {
478
+ it(`emits only row data when 'allowReordering' is true, 'newDataPosition' is defined, and is 'positionKey' is undefined`, async () => {
479
479
  const spy = jest.fn();
480
480
  const mockEvent = {
481
481
  e: 'event',
@@ -504,9 +504,9 @@ describe('DynamicListDataEntry', () => {
504
504
 
505
505
  const button = wrapper.find(Button);
506
506
 
507
- act(() => {
507
+ await act(async () => {
508
508
  // @ts-expect-error not full event args object
509
- button.prop('onButtonClicked')?.(mockEvent);
509
+ await button.prop('onButtonClicked')?.(mockEvent);
510
510
  });
511
511
 
512
512
  expect(spy).toHaveBeenCalledTimes(1);
@@ -515,7 +515,7 @@ describe('DynamicListDataEntry', () => {
515
515
  });
516
516
  });
517
517
 
518
- it(`transform property if 'onAddTransformer' is set as a column option`, () => {
518
+ it(`transform property if 'onAddTransformer' is set as a column option`, async () => {
519
519
  const spy = jest.fn();
520
520
  const mockNewValue = 'test-value1';
521
521
  const mockEvent = {
@@ -550,9 +550,9 @@ describe('DynamicListDataEntry', () => {
550
550
 
551
551
  const button = wrapper.find(Button);
552
552
 
553
- act(() => {
553
+ await act(async () => {
554
554
  // @ts-expect-error not full event args object
555
- button.prop('onButtonClicked')?.(mockEvent);
555
+ await button.prop('onButtonClicked')?.(mockEvent);
556
556
  });
557
557
 
558
558
  expect(spy).toHaveBeenCalledTimes(1);
@@ -1,10 +1,5 @@
1
1
  import clsx from 'clsx';
2
- import React, {
3
- PropsWithChildren,
4
- ReactElement,
5
- useEffect,
6
- useState,
7
- } from 'react';
2
+ import React, { PropsWithChildren, ReactElement, useState } from 'react';
8
3
  import { ValidationError } from 'yup';
9
4
  import { OptionalObjectSchema } from 'yup/lib/object';
10
5
  import { noop } from '../../../helpers/utils';
@@ -110,27 +105,29 @@ export const DynamicListDataEntry = <T extends Data>({
110
105
  const [isDirty, setIsDirty] = useState<boolean>(false);
111
106
  const [error, setError] = useState<Record<string, string>>({});
112
107
 
113
- useEffect(() => {
114
- if (rowValidationSchema && isDirty) {
115
- rowValidationSchema
116
- ?.validate(state, { abortEarly: false })
117
- .then(() => {
118
- setError({});
119
- })
120
- .catch((e: ValidationError) => {
121
- const newErrors: Record<string, string> = {};
122
- e.inner.forEach((validationError) => {
123
- if (validationError.path !== undefined) {
124
- const path = validationError.path;
125
- if (newErrors?.[path] === undefined) {
126
- newErrors[path] = validationError.message;
127
- }
128
- }
129
- });
130
- setError(newErrors);
131
- });
108
+ const validateSchema = async (data: T): Promise<boolean> => {
109
+ if (!rowValidationSchema) {
110
+ return true;
132
111
  }
133
- }, [isDirty, rowValidationSchema, state]);
112
+
113
+ try {
114
+ await rowValidationSchema.validate(data, { abortEarly: false });
115
+ setError({});
116
+
117
+ return true;
118
+ } catch (e) {
119
+ const newErrors: Record<string, string> = {};
120
+ (e as ValidationError).inner.forEach((validationError) => {
121
+ const path = validationError.path;
122
+ if (path !== undefined && newErrors?.[path] === undefined) {
123
+ newErrors[path] = validationError.message;
124
+ }
125
+ });
126
+ setError(newErrors);
127
+
128
+ return false;
129
+ }
130
+ };
134
131
 
135
132
  /**
136
133
  * Updates new data object with supplied key/value pair
@@ -138,10 +135,12 @@ export const DynamicListDataEntry = <T extends Data>({
138
135
  * @param value new value
139
136
  */
140
137
  const valueChangedHandler = (property: keyof T, value: unknown): void => {
138
+ const newState = { ...state, [property]: value };
139
+
141
140
  setIsDirty(true);
142
- setState((prevState) => {
143
- return { ...prevState, [property]: value };
144
- });
141
+ setState(newState);
142
+
143
+ validateSchema(newState);
145
144
  };
146
145
 
147
146
  /**
@@ -149,11 +148,11 @@ export const DynamicListDataEntry = <T extends Data>({
149
148
  * @param data T
150
149
  */
151
150
  const onAddItemHandler = async (): Promise<void> => {
152
- // TODO: Display a warning if no data was entered?
153
- if (rowValidationSchema && !(await rowValidationSchema?.isValid(state))) {
151
+ const isValid = await validateSchema(state);
152
+
153
+ if (!isValid) {
154
154
  setIsDirty(true);
155
- // eslint-disable-next-line no-console
156
- return console.warn('Data not valid');
155
+ return;
157
156
  }
158
157
 
159
158
  let transformedState: T = state;