chili-ui 0.7.3 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/chili/components/AutoComplete/handlers.ts +26 -0
  2. package/chili/components/AutoComplete/index.tsx +2 -0
  3. package/chili/components/ButtonGroup/handlers.ts +20 -0
  4. package/chili/components/ButtonGroup/index.tsx +2 -1
  5. package/chili/components/Calendar/handlers.ts +31 -0
  6. package/chili/components/Calendar/index.tsx +2 -1
  7. package/chili/components/Calendar/types.ts +1 -1
  8. package/chili/components/CheckBox/handlers.ts +15 -0
  9. package/chili/components/CheckBox/index.tsx +2 -1
  10. package/chili/components/DatePicker/index.tsx +1 -1
  11. package/chili/components/DateRange/index.tsx +1 -1
  12. package/chili/components/DateTimePicker/index.tsx +1 -1
  13. package/chili/components/DateTimeRange/index.tsx +1 -1
  14. package/chili/components/DropDownSelect/handlers.ts +22 -0
  15. package/chili/components/DropDownSelect/index.tsx +2 -0
  16. package/chili/components/Input/handlers.ts +15 -0
  17. package/chili/components/Input/index.tsx +2 -0
  18. package/chili/components/MaskedInput/MaskedInput.persistence.test.tsx +44 -0
  19. package/chili/components/MaskedInput/handlers.ts +21 -0
  20. package/chili/components/MaskedInput/index.tsx +11 -10
  21. package/chili/components/MultiSelect/handlers.ts +22 -0
  22. package/chili/components/MultiSelect/index.tsx +2 -0
  23. package/chili/components/NumericTextBox/handlers.ts +23 -0
  24. package/chili/components/NumericTextBox/index.tsx +4 -0
  25. package/chili/components/Password/handlers.ts +15 -0
  26. package/chili/components/Password/index.tsx +2 -0
  27. package/chili/components/Radio/RadioGroup.tsx +16 -11
  28. package/chili/components/Radio/handlers.ts +15 -0
  29. package/chili/components/Radio/types.ts +1 -1
  30. package/chili/components/Rating/handlers.ts +16 -0
  31. package/chili/components/Rating/index.tsx +2 -0
  32. package/chili/components/Switcher/index.tsx +2 -0
  33. package/chili/components/Textarea/handlers.ts +17 -0
  34. package/chili/components/Textarea/index.tsx +2 -1
  35. package/chili/components/Validation/helpers.ts +4 -1
  36. package/chili/components/Validation/types.ts +9 -0
  37. package/chili/components/Validation/useValidation.tsx +12 -1
  38. package/chili/form/form.test.tsx +20 -0
  39. package/chili/form/form.ts +28 -1
  40. package/chili/form/types.ts +1 -0
  41. package/chili/index.ts +2 -0
  42. package/chili/src/DateTimeInput/DateTimeInput.tsx +5 -0
  43. package/chili/src/DateTimeInput/handlers/handleSetValue.ts +53 -0
  44. package/chili/src/DateTimeInput/handlers/index.ts +1 -0
  45. package/chili/utils/index.ts +2 -0
  46. package/chili/utils/usePersistence.ts +83 -0
  47. package/dist/components/AutoComplete/handlers.d.ts +4 -0
  48. package/dist/components/AutoComplete/handlers.js +18 -0
  49. package/dist/components/AutoComplete/handlers.js.map +1 -1
  50. package/dist/components/AutoComplete/index.js +2 -1
  51. package/dist/components/AutoComplete/index.js.map +1 -1
  52. package/dist/components/ButtonGroup/handlers.d.ts +4 -0
  53. package/dist/components/ButtonGroup/handlers.js +13 -0
  54. package/dist/components/ButtonGroup/handlers.js.map +1 -1
  55. package/dist/components/ButtonGroup/index.js +2 -1
  56. package/dist/components/ButtonGroup/index.js.map +1 -1
  57. package/dist/components/Calendar/handlers.d.ts +4 -0
  58. package/dist/components/Calendar/handlers.js +20 -0
  59. package/dist/components/Calendar/handlers.js.map +1 -1
  60. package/dist/components/Calendar/index.js +2 -1
  61. package/dist/components/Calendar/index.js.map +1 -1
  62. package/dist/components/Calendar/types.d.ts +1 -1
  63. package/dist/components/CheckBox/handlers.d.ts +1 -0
  64. package/dist/components/CheckBox/handlers.js +11 -0
  65. package/dist/components/CheckBox/handlers.js.map +1 -1
  66. package/dist/components/CheckBox/index.js +2 -1
  67. package/dist/components/CheckBox/index.js.map +1 -1
  68. package/dist/components/DatePicker/index.js +1 -1
  69. package/dist/components/DatePicker/index.js.map +1 -1
  70. package/dist/components/DateRange/index.js +1 -1
  71. package/dist/components/DateRange/index.js.map +1 -1
  72. package/dist/components/DateTimePicker/index.js +1 -1
  73. package/dist/components/DateTimePicker/index.js.map +1 -1
  74. package/dist/components/DateTimeRange/index.js +1 -1
  75. package/dist/components/DateTimeRange/index.js.map +1 -1
  76. package/dist/components/DropDownSelect/handlers.d.ts +4 -0
  77. package/dist/components/DropDownSelect/handlers.js +13 -0
  78. package/dist/components/DropDownSelect/handlers.js.map +1 -1
  79. package/dist/components/DropDownSelect/index.js +2 -1
  80. package/dist/components/DropDownSelect/index.js.map +1 -1
  81. package/dist/components/Input/handlers.d.ts +1 -0
  82. package/dist/components/Input/handlers.js +11 -0
  83. package/dist/components/Input/handlers.js.map +1 -1
  84. package/dist/components/Input/index.js +2 -1
  85. package/dist/components/Input/index.js.map +1 -1
  86. package/dist/components/MaskedInput/MaskedInput.persistence.test.d.ts +1 -0
  87. package/dist/components/MaskedInput/MaskedInput.persistence.test.js +29 -0
  88. package/dist/components/MaskedInput/MaskedInput.persistence.test.js.map +1 -0
  89. package/dist/components/MaskedInput/handlers.d.ts +4 -0
  90. package/dist/components/MaskedInput/handlers.js +14 -0
  91. package/dist/components/MaskedInput/handlers.js.map +1 -1
  92. package/dist/components/MaskedInput/index.js +3 -4
  93. package/dist/components/MaskedInput/index.js.map +1 -1
  94. package/dist/components/MultiSelect/handlers.d.ts +4 -0
  95. package/dist/components/MultiSelect/handlers.js +15 -0
  96. package/dist/components/MultiSelect/handlers.js.map +1 -1
  97. package/dist/components/MultiSelect/index.js +2 -1
  98. package/dist/components/MultiSelect/index.js.map +1 -1
  99. package/dist/components/NumericTextBox/handlers.d.ts +6 -0
  100. package/dist/components/NumericTextBox/handlers.js +12 -0
  101. package/dist/components/NumericTextBox/handlers.js.map +1 -1
  102. package/dist/components/NumericTextBox/index.js +4 -1
  103. package/dist/components/NumericTextBox/index.js.map +1 -1
  104. package/dist/components/Password/handlers.d.ts +1 -0
  105. package/dist/components/Password/handlers.js +11 -0
  106. package/dist/components/Password/handlers.js.map +1 -1
  107. package/dist/components/Password/index.js +2 -1
  108. package/dist/components/Password/index.js.map +1 -1
  109. package/dist/components/Radio/RadioGroup.js +8 -8
  110. package/dist/components/Radio/RadioGroup.js.map +1 -1
  111. package/dist/components/Radio/handlers.d.ts +1 -0
  112. package/dist/components/Radio/handlers.js +11 -0
  113. package/dist/components/Radio/handlers.js.map +1 -1
  114. package/dist/components/Radio/types.d.ts +1 -1
  115. package/dist/components/Rating/handlers.d.ts +1 -0
  116. package/dist/components/Rating/handlers.js +12 -0
  117. package/dist/components/Rating/handlers.js.map +1 -1
  118. package/dist/components/Rating/index.js +2 -1
  119. package/dist/components/Rating/index.js.map +1 -1
  120. package/dist/components/Switcher/index.js +2 -0
  121. package/dist/components/Switcher/index.js.map +1 -1
  122. package/dist/components/Textarea/handlers.d.ts +1 -0
  123. package/dist/components/Textarea/handlers.js +13 -0
  124. package/dist/components/Textarea/handlers.js.map +1 -1
  125. package/dist/components/Textarea/index.js +2 -1
  126. package/dist/components/Textarea/index.js.map +1 -1
  127. package/dist/components/Validation/helpers.d.ts +1 -1
  128. package/dist/components/Validation/helpers.js +4 -2
  129. package/dist/components/Validation/helpers.js.map +1 -1
  130. package/dist/components/Validation/types.d.ts +8 -0
  131. package/dist/components/Validation/types.js +5 -1
  132. package/dist/components/Validation/types.js.map +1 -1
  133. package/dist/components/Validation/useValidation.js +11 -2
  134. package/dist/components/Validation/useValidation.js.map +1 -1
  135. package/dist/form/form.js +25 -1
  136. package/dist/form/form.js.map +1 -1
  137. package/dist/form/form.test.js +13 -0
  138. package/dist/form/form.test.js.map +1 -1
  139. package/dist/form/types.d.ts +1 -0
  140. package/dist/index.d.ts +1 -0
  141. package/dist/index.js +2 -1
  142. package/dist/index.js.map +1 -1
  143. package/dist/src/DateTimeInput/DateTimeInput.js +6 -2
  144. package/dist/src/DateTimeInput/DateTimeInput.js.map +1 -1
  145. package/dist/src/DateTimeInput/handlers/handleSetValue.d.ts +6 -0
  146. package/dist/src/DateTimeInput/handlers/handleSetValue.js +37 -0
  147. package/dist/src/DateTimeInput/handlers/handleSetValue.js.map +1 -0
  148. package/dist/src/DateTimeInput/handlers/index.d.ts +1 -0
  149. package/dist/src/DateTimeInput/handlers/index.js +1 -0
  150. package/dist/src/DateTimeInput/handlers/index.js.map +1 -1
  151. package/dist/styles/chili.base.css +2 -2
  152. package/dist/utils/index.d.ts +1 -0
  153. package/dist/utils/index.js +1 -0
  154. package/dist/utils/index.js.map +1 -1
  155. package/dist/utils/usePersistence.d.ts +10 -0
  156. package/dist/utils/usePersistence.js +64 -0
  157. package/dist/utils/usePersistence.js.map +1 -0
  158. package/docs/src/app/form-components/autocomplete/MainDemo/PersistenceDemo.tsx +20 -0
  159. package/docs/src/app/form-components/autocomplete/MainDemo/index.tsx +4 -0
  160. package/docs/src/app/form-helpers/form/page.tsx +12 -0
  161. package/docs/src/app/other/persistence/page.tsx +217 -0
  162. package/docs/src/components/nav/index.tsx +1 -0
  163. package/docs/src/sections/ValidationSection.tsx +21 -14
  164. package/package.json +1 -1
@@ -345,3 +345,29 @@ export const createResetHandler = ({
345
345
  },
346
346
  });
347
347
  };
348
+
349
+ export const createSetValueHandler = ({
350
+ props,
351
+ setStateValue,
352
+ }: {
353
+ props: AutoCompleteProps,
354
+ setStateValue: SetState<string>,
355
+ }) => (value: unknown) => {
356
+ const newValue = value as string;
357
+ const suggestion = getSuggestionFromValue({
358
+ data: props.data || [],
359
+ value: newValue,
360
+ textField: props.textField,
361
+ });
362
+
363
+ setStateValue(newValue);
364
+
365
+ props.onChange?.({
366
+ component: {
367
+ value: newValue,
368
+ method: ChangeMethod.reset,
369
+ name: props.name,
370
+ suggestion,
371
+ },
372
+ });
373
+ };
@@ -27,6 +27,7 @@ import {
27
27
  suggestionClickHandlerCreator,
28
28
  clearButtonClickHandlerCreator,
29
29
  createResetHandler,
30
+ createSetValueHandler,
30
31
  } from './handlers';
31
32
 
32
33
  import type {
@@ -141,6 +142,7 @@ export const AutoComplete = React.forwardRef((props: AutoCompleteProps, ref: Rea
141
142
  reset: createResetHandler({
142
143
  props, setStateValue, value: defaultValue ?? '',
143
144
  }),
145
+ setValue: createSetValueHandler({ props, setStateValue }),
144
146
  });
145
147
 
146
148
  const value = isValueControlled ? propValue : stateValue;
@@ -63,3 +63,23 @@ export const createResetHandler = ({
63
63
  props.onChange(customEvent);
64
64
  }
65
65
  };
66
+
67
+ export const createSetValueHandler = ({
68
+ props,
69
+ setUncontrolledValue,
70
+ }: {
71
+ props: ButtonGroupProps,
72
+ setUncontrolledValue: SetState<Value | Value[] | undefined>,
73
+ }) => (value: unknown) => {
74
+ const newValue = value as Value | Value[] | undefined;
75
+ setUncontrolledValue(newValue);
76
+ if (isFunction(props.onChange)) {
77
+ const customEvent = {
78
+ component: {
79
+ name: props.name,
80
+ value: newValue,
81
+ },
82
+ };
83
+ props.onChange(customEvent);
84
+ }
85
+ };
@@ -5,7 +5,7 @@ import {
5
5
  getClassNames, useTheme, useValue, useElement, useProps, getIsEmptyAndRequired,
6
6
  } from '../../utils';
7
7
  import { COMPONENTS_NAMESPACES } from '../../constants';
8
- import { createChangeHandler, createResetHandler } from './handlers';
8
+ import { createChangeHandler, createResetHandler, createSetValueHandler } from './handlers';
9
9
  import { compareItems } from './helpers';
10
10
  import type {
11
11
  ButtonGroupProps, Value,
@@ -47,6 +47,7 @@ export const ButtonGroup = React.forwardRef((props: ButtonGroupProps, ref?: Reac
47
47
  reset: createResetHandler({
48
48
  props, setUncontrolledValue, value: defaultValue,
49
49
  }),
50
+ setValue: createSetValueHandler({ props, setUncontrolledValue }),
50
51
  });
51
52
 
52
53
  const handleChange = createChangeHandler(props, {
@@ -161,3 +161,34 @@ export const createResetHandler = ({
161
161
  },
162
162
  });
163
163
  };
164
+
165
+ export const createSetValueHandler = ({
166
+ props,
167
+ dispatch,
168
+ }: {
169
+ props: StandaloneCalendarProps,
170
+ dispatch: React.Dispatch<StandaloneCalendarActionTypes>,
171
+ }) => (value: unknown) => {
172
+ const newValue = (() => {
173
+ if (typeof value === 'string') {
174
+ const parsed = new Date(value);
175
+ const dateValue = Number.isNaN(parsed.getTime()) ? null : parsed;
176
+ return dateValue;
177
+ }
178
+
179
+ return value as Date | null;
180
+ })();
181
+
182
+ if (!(newValue instanceof Date) && value !== null) {
183
+ console.error('setValue unsupported date format');
184
+ }
185
+
186
+ dispatch(setDate(newValue));
187
+
188
+ props.onChange({
189
+ component: {
190
+ value: newValue,
191
+ name: props.name,
192
+ },
193
+ });
194
+ };
@@ -10,7 +10,7 @@ import { CALENDAR_CLICK_ACTION, DEFAULT_DATE_FORMAT, VIEW_TYPES } from '../../sr
10
10
  import { TodayButton } from '../../src/CalendarBase/TodayButton';
11
11
  import { useCustomElements } from './hooks';
12
12
  import { getCalendarConditions } from '../../src/CalendarBase/helpers';
13
- import { createClickHandler, createResetHandler } from './handlers';
13
+ import { createClickHandler, createResetHandler, createSetValueHandler } from './handlers';
14
14
  import { stateReducer } from './reducer';
15
15
  import { useValidation } from '../Validation';
16
16
 
@@ -58,6 +58,7 @@ export const Calendar = React.forwardRef((props: StandaloneCalendarProps, ref?:
58
58
  reset: createResetHandler({
59
59
  props, dispatch, value: null,
60
60
  }),
61
+ setValue: createSetValueHandler({ props, dispatch }),
61
62
  });
62
63
 
63
64
  // these flags are used to switch off header buttons in min-max case
@@ -16,7 +16,7 @@ import type { ValidationProps } from '../Validation/types';
16
16
 
17
17
  export interface ResetChangeEvent {
18
18
  component: {
19
- value: null,
19
+ value: null | Date,
20
20
  name?: string,
21
21
  },
22
22
  }
@@ -45,3 +45,18 @@ export const createResetHandler = (
45
45
  },
46
46
  });
47
47
  };
48
+
49
+ export const createSetValueHandler = (
50
+ props: CheckBoxProps,
51
+ setValue: SetState<boolean>,
52
+ ) => (value: unknown) => {
53
+ const newValue = value as boolean;
54
+ setValue(newValue);
55
+
56
+ props.onChange?.({
57
+ component: {
58
+ name: props.name,
59
+ value: newValue,
60
+ },
61
+ });
62
+ };
@@ -4,7 +4,7 @@ import {
4
4
  useTheme, useElement, generateId, useValue, useProps,
5
5
  } from '../../utils';
6
6
  import { COMPONENTS_NAMESPACES } from '../../constants';
7
- import { createChangeHandler, createResetHandler } from './handlers';
7
+ import { createChangeHandler, createResetHandler, createSetValueHandler } from './handlers';
8
8
  import type { CheckBoxProps } from './types';
9
9
  import { ChiliContext } from '../ChiliProvider';
10
10
  import {
@@ -42,6 +42,7 @@ export const CheckBox = React.forwardRef((props: CheckBoxProps, ref?: React.Ref<
42
42
  value,
43
43
  }, {
44
44
  reset: createResetHandler(props, setUncontrolledValue),
45
+ setValue: createSetValueHandler(props, setUncontrolledValue),
45
46
  });
46
47
 
47
48
  const Wrapper = useElement(
@@ -24,11 +24,11 @@ export const DatePicker = React.forwardRef((rawProps: DatePickerProps, ref: Reac
24
24
  <DateTimeInput
25
25
  {...restProps}
26
26
  defaultValue={defaultValue}
27
- value={value}
28
27
  onChange={handleChange}
29
28
  format={props.format || 'dd.MM.yyyy'}
30
29
  type={COMPONENT_TYPES.DATE_ONLY}
31
30
  ref={ref}
31
+ {...(valueProp !== undefined ? { value } : {})}
32
32
  />
33
33
  );
34
34
  }) as React.FC<DatePickerProps>;
@@ -26,9 +26,9 @@ export const DateRange = React.forwardRef((rawProps: DateRangeProps, ref: React.
26
26
  type={COMPONENT_TYPES.DATE_ONLY}
27
27
  format={props.format || 'dd.MM.yyyy'}
28
28
  defaultValue={defaultValue}
29
- value={value}
30
29
  onChange={handleChange}
31
30
  ref={ref}
31
+ {...(valueProp !== undefined ? { value } : {})}
32
32
  />
33
33
  );
34
34
  }) as React.FC<DateRangeProps>;
@@ -25,10 +25,10 @@ export const DateTimePicker = React.forwardRef((rawProps: DateTimePickerProps, r
25
25
  {...restProps}
26
26
  format={props.format || 'dd.MM.yyyy hh:mm'}
27
27
  defaultValue={defaultValue}
28
- value={value}
29
28
  onChange={handleChange}
30
29
  ref={ref}
31
30
  type={COMPONENT_TYPES.DATE_TIME}
31
+ {...(valueProp !== undefined ? { value } : {})}
32
32
  />
33
33
  );
34
34
  }) as React.FC<DateTimePickerProps>;
@@ -26,9 +26,9 @@ export const DateTimeRange = React.forwardRef((rawProps: DateTimeRangeProps, ref
26
26
  type={COMPONENT_TYPES.DATE_TIME}
27
27
  format={props.format || 'dd.MM.yyyy hh:mm'}
28
28
  defaultValue={defaultValue}
29
- value={value}
30
29
  onChange={handleChange}
31
30
  ref={ref}
31
+ {...(valueProp !== undefined ? { value } : {})}
32
32
  />
33
33
  );
34
34
  }) as React.FC<DateTimeRangeProps>;
@@ -361,3 +361,25 @@ export const createResetHandler = ({
361
361
  props.onChange(customEvent);
362
362
  }
363
363
  };
364
+
365
+ export const createSetValueHandler = ({
366
+ props,
367
+ mergeState,
368
+ }: {
369
+ props: DropDownSelectProps,
370
+ mergeState: (state: Partial<DropDownSelectState>) => void,
371
+ }) => (value: unknown) => {
372
+ const newValue = value as Value;
373
+ mergeState({ value: newValue });
374
+
375
+ if (isFunction(props.onChange)) {
376
+ const customEvent = {
377
+ component: {
378
+ name: props.name,
379
+ value: newValue,
380
+ },
381
+ };
382
+
383
+ props.onChange(customEvent);
384
+ }
385
+ };
@@ -19,6 +19,7 @@ import {
19
19
  createIconClickHandler,
20
20
  createKeyDownHandler,
21
21
  createResetHandler,
22
+ createSetValueHandler,
22
23
  } from './handlers';
23
24
  import { filterData, getComponentClassNames, getInputValue } from './helpers';
24
25
  import { useCorrectSuggestionsInControlledMode, useCustomElements, useSyncedHighlightedValue } from './hooks';
@@ -102,6 +103,7 @@ export const DropDownSelect = React.forwardRef((props: DropDownSelectProps, ref:
102
103
  reset: createResetHandler({
103
104
  props, mergeState, value: defaultValue,
104
105
  }),
106
+ setValue: createSetValueHandler({ props, mergeState }),
105
107
  });
106
108
 
107
109
  const inputRef = React.useRef<HTMLInputElement | null>(null);
@@ -118,3 +118,18 @@ export const createResetHandler = (
118
118
  },
119
119
  });
120
120
  };
121
+
122
+ export const createSetValueHandler = (
123
+ props: InputProps,
124
+ setValue: SetState<string>,
125
+ ) => (value: unknown) => {
126
+ const newValue = value as string;
127
+ setValue(newValue);
128
+
129
+ props.onChange?.({
130
+ component: {
131
+ name: props.name,
132
+ value: newValue,
133
+ },
134
+ });
135
+ };
@@ -15,6 +15,7 @@ import {
15
15
  createFocusHandler,
16
16
  createKeyDownHandler,
17
17
  createResetHandler,
18
+ createSetValueHandler,
18
19
  } from './handlers';
19
20
  import { getValue } from './helpers';
20
21
 
@@ -61,6 +62,7 @@ export const Input = React.forwardRef((props: InputProps, ref: React.Ref<HTMLHtm
61
62
  value,
62
63
  }, {
63
64
  reset: createResetHandler(props, setValue),
65
+ setValue: createSetValueHandler(props, setValue),
64
66
  });
65
67
 
66
68
  const theme = useTheme(themeProp, COMPONENTS_NAMESPACES.input);
@@ -0,0 +1,44 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { MaskedInput } from './index';
4
+ import { Persistence } from '../Validation/types';
5
+
6
+ describe('MaskedInput PERSISTENCE', () => {
7
+ it('should restore persisted value without console error', async () => {
8
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
9
+
10
+ window.sessionStorage.clear();
11
+
12
+ const { unmount } = render(
13
+ <MaskedInput
14
+ mask="###"
15
+ form="form"
16
+ name="field"
17
+ persistence={Persistence.sessionStorage}
18
+ onChange={jest.fn()}
19
+ />,
20
+ );
21
+
22
+ userEvent.type(screen.getByRole('textbox'), '123');
23
+
24
+ expect(window.sessionStorage.getItem('chili-form-form')).toBe(JSON.stringify({ field: '123' }));
25
+
26
+ unmount();
27
+
28
+ render(
29
+ <MaskedInput
30
+ mask="###"
31
+ form="form"
32
+ name="field"
33
+ persistence={Persistence.sessionStorage}
34
+ onChange={jest.fn()}
35
+ />,
36
+ );
37
+
38
+ expect(await screen.findByDisplayValue('123')).toBeTruthy();
39
+
40
+ expect(consoleErrorSpy.mock.calls.flat()).not.toContain('Persistence prop is for uncontrolled state only');
41
+
42
+ consoleErrorSpy.mockRestore();
43
+ });
44
+ });
@@ -134,3 +134,24 @@ export const createResetHandler = ({
134
134
  props.onChange(customEvent);
135
135
  }
136
136
  };
137
+
138
+ export const createSetValueHandler = ({
139
+ props,
140
+ setValue,
141
+ }: {
142
+ props: MaskedInputProps,
143
+ setValue: SetState<string>,
144
+ }) => (value: unknown) => {
145
+ const newValue = value as string;
146
+ setValue(newValue);
147
+ if (isFunction(props.onChange)) {
148
+ const customEvent = {
149
+ component: {
150
+ name: props.name,
151
+ value: newValue,
152
+ inputValue: maskValue(newValue, props.mask, props.placeholderChar),
153
+ },
154
+ };
155
+ props.onChange(customEvent);
156
+ }
157
+ };
@@ -7,7 +7,7 @@ import type { MaskedInputProps } from './types';
7
7
  import { COMPONENTS_NAMESPACES } from '../../constants';
8
8
  import { useValidation } from '../Validation';
9
9
  import {
10
- createBlurHandler, createChangeHandler, createFocusHandler, createKeyDownHandler, createResetHandler,
10
+ createBlurHandler, createChangeHandler, createFocusHandler, createKeyDownHandler, createResetHandler, createSetValueHandler,
11
11
  } from './handlers';
12
12
  import { useCustomElements } from './hooks';
13
13
  import { getValue, getValueToValidate } from './helpers';
@@ -59,15 +59,16 @@ export const MaskedInput = React.forwardRef((props: MaskedInputProps, ref: React
59
59
 
60
60
  const {
61
61
  isValid, validateCurrent, InvalidMessage,
62
- } = useValidation({
63
- ...props, value: valueToValidate,
64
- }, {
65
- value: valueState,
66
- }, {
67
- reset: createResetHandler({
68
- props, setValue, value: toStringOrEmpty(defaultValue || ''),
69
- }),
70
- });
62
+ } = useValidation(
63
+ props,
64
+ { value: valueToValidate },
65
+ {
66
+ reset: createResetHandler({
67
+ props, setValue, value: toStringOrEmpty(defaultValue || ''),
68
+ }),
69
+ setValue: createSetValueHandler({ props, setValue }),
70
+ },
71
+ );
71
72
 
72
73
  const state = { value: valueState, isFocused, isValid };
73
74
 
@@ -264,3 +264,25 @@ export const createResetHandler = ({
264
264
  props.onChange(customEvent);
265
265
  }
266
266
  };
267
+
268
+ export const createSetValueHandler = ({
269
+ props,
270
+ setValue,
271
+ }: {
272
+ props: MultiSelectProps,
273
+ setValue: SetState<Value[]>,
274
+ }) => (value: unknown) => {
275
+ const newValue = value as Value[];
276
+ setValue(newValue);
277
+ if (isFunction(props.onChange)) {
278
+ const customEvent = {
279
+ component: {
280
+ name: props.name,
281
+ value: newValue,
282
+ deselectedValues: undefined,
283
+ selectedValue: undefined,
284
+ },
285
+ };
286
+ props.onChange(customEvent);
287
+ }
288
+ };
@@ -19,6 +19,7 @@ import {
19
19
  createMouseDownHandler,
20
20
  createResetHandler,
21
21
  createSelectHandler,
22
+ createSetValueHandler,
22
23
  } from './handlers';
23
24
  import { TagsContainer } from './TagsContainer';
24
25
  import { Div } from '../Div';
@@ -110,6 +111,7 @@ export const MultiSelect = React.forwardRef((props: MultiSelectProps, ref: React
110
111
  reset: createResetHandler({
111
112
  props, setValue, value: defaultValue || [],
112
113
  }),
114
+ setValue: createSetValueHandler({ props, setValue }),
113
115
  });
114
116
 
115
117
  const [isFocused, setFocused] = React.useState<boolean>(false);
@@ -297,3 +297,26 @@ export const createResetHandler = ({
297
297
  },
298
298
  });
299
299
  };
300
+
301
+ export const createSetValueHandler = ({
302
+ props,
303
+ setUncontrolledValue,
304
+ format,
305
+ thousandsSeparator,
306
+ }: {
307
+ props: NumericTextBoxProps,
308
+ setUncontrolledValue: SetState<number | null>,
309
+ format: string,
310
+ thousandsSeparator: string,
311
+ }) => (value: unknown) => {
312
+ const newValue = value as number | null;
313
+ setUncontrolledValue(newValue);
314
+
315
+ props.onChange?.({
316
+ component: {
317
+ formattedValue: formatValue({ value: newValue, format, thousandsSeparator }),
318
+ name: props.name,
319
+ value: newValue,
320
+ },
321
+ });
322
+ };
@@ -15,6 +15,7 @@ import {
15
15
  createKeyDownHandler,
16
16
  createPasteHandler,
17
17
  createResetHandler,
18
+ createSetValueHandler,
18
19
  } from './handlers';
19
20
  import {
20
21
  formatInputValue, formatValue, getRestProps, getValue, normalizeValue,
@@ -72,6 +73,9 @@ export const NumericTextBox = React.forwardRef((props: NumericTextBoxProps, ref:
72
73
  reset: createResetHandler({
73
74
  props, setUncontrolledValue, format, thousandsSeparator, value: normalizeValue(normalizeValueParams),
74
75
  }),
76
+ setValue: createSetValueHandler({
77
+ props, setUncontrolledValue, format, thousandsSeparator,
78
+ }),
75
79
  });
76
80
 
77
81
  const wrapperClassNames = getClassNames(
@@ -119,3 +119,18 @@ export const createResetHandler = (
119
119
  },
120
120
  });
121
121
  };
122
+
123
+ export const createSetValueHandler = (
124
+ props: PasswordProps,
125
+ setValue: SetState<string>,
126
+ ) => (value: unknown) => {
127
+ const newValue = value as string;
128
+ setValue(newValue);
129
+
130
+ props.onChange?.({
131
+ component: {
132
+ name: props.name,
133
+ value: newValue,
134
+ },
135
+ });
136
+ };
@@ -13,6 +13,7 @@ import {
13
13
  createFocusHandler,
14
14
  createKeyDownHandler,
15
15
  createResetHandler,
16
+ createSetValueHandler,
16
17
  } from './handlers';
17
18
  import { getValue, rulesToValidators } from './helpers';
18
19
  import { PasswordVisibilityIcon } from './PasswordVisibilityIcon';
@@ -76,6 +77,7 @@ export const Password = React.forwardRef((props: PasswordProps, ref: React.Ref<H
76
77
  value,
77
78
  }, {
78
79
  reset: createResetHandler(props, setValue),
80
+ setValue: createSetValueHandler(props, setValue),
79
81
  });
80
82
 
81
83
  const theme = useTheme(themeProp, COMPONENTS_NAMESPACES.password);
@@ -7,9 +7,13 @@ import {
7
7
  import { Div } from '../Div';
8
8
  import { COMPONENTS_NAMESPACES } from '../../constants';
9
9
  import type {
10
- ChangeEvent, RadioGroupProps, WrapperProps,
10
+ ChangeEvent,
11
+ RadioButtonProps,
12
+ PropsFromParent,
13
+ RadioGroupProps,
14
+ WrapperProps,
11
15
  } from './types';
12
- import { createResetHandler } from './handlers';
16
+ import { createResetHandler, createSetValueHandler } from './handlers';
13
17
  import { useValidation } from '../Validation';
14
18
 
15
19
  export const RadioGroup = React.forwardRef((props: RadioGroupProps, ref?: React.Ref<HTMLElement>): React.ReactElement => {
@@ -35,6 +39,7 @@ export const RadioGroup = React.forwardRef((props: RadioGroupProps, ref?: React.
35
39
  value,
36
40
  }, {
37
41
  reset: createResetHandler(props, setValueState, defaultValue),
42
+ setValue: createSetValueHandler(props, setValueState),
38
43
  });
39
44
 
40
45
  const combinedClassNames = getClassNames(
@@ -46,7 +51,7 @@ export const RadioGroup = React.forwardRef((props: RadioGroupProps, ref?: React.
46
51
  if (isFunction(onChange)) onChange(ev);
47
52
 
48
53
  return setValueState(ev.component.value);
49
- }, [onChange]);
54
+ }, [onChange, setValueState]);
50
55
 
51
56
  const Wrapper = useElement<RadioGroupProps, { value?: string | number | null }, WrapperProps>(
52
57
  'Wrapper',
@@ -62,19 +67,19 @@ export const RadioGroup = React.forwardRef((props: RadioGroupProps, ref?: React.
62
67
  ref={ref}
63
68
  >
64
69
  {React.Children.toArray(children).map((child) => {
65
- if (child
70
+ if (
71
+ child
66
72
  && React.isValidElement(child)
67
73
  && (child.type === RadioButton || (child.type as { name?: string }).name === 'RadioButton')
68
74
  ) {
69
- return React.cloneElement(child, {
75
+ const radioButtonChild = child as React.ReactElement<RadioButtonProps & PropsFromParent>;
76
+ return React.cloneElement(radioButtonChild, {
70
77
  name,
71
78
  onChange: handleChange,
72
- isDisabled: isBoolean(isDisabled) ? isDisabled : child.props.isDisabled,
73
- isChecked: child.props.value === value,
74
- theme: { ...theme, ...child.props.theme },
75
- // todo find a better way to fix TS issue with the name property
76
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
- } as any);
79
+ isDisabled: isBoolean(isDisabled) ? isDisabled : radioButtonChild.props.isDisabled,
80
+ isChecked: radioButtonChild.props.value === value,
81
+ theme: { ...theme, ...radioButtonChild.props.theme },
82
+ });
78
83
  }
79
84
  return child;
80
85
  })}
@@ -16,3 +16,18 @@ export const createResetHandler = (
16
16
  },
17
17
  });
18
18
  };
19
+
20
+ export const createSetValueHandler = (
21
+ props: RadioGroupProps,
22
+ setValue: SetState<string | number | null | undefined>,
23
+ ) => (value: unknown) => {
24
+ const newValue = value as string | number | null;
25
+ setValue(newValue);
26
+
27
+ props.onChange?.({
28
+ component: {
29
+ name: props.name,
30
+ value: newValue,
31
+ },
32
+ });
33
+ };
@@ -41,7 +41,7 @@ export interface RadioGroupProps extends ValidationProps {
41
41
  [x: string]: unknown,
42
42
  }
43
43
 
44
- export interface RadioButtonProps extends React.HTMLAttributes<HTMLInputElement> {
44
+ export interface RadioButtonProps extends Omit<React.HTMLAttributes<HTMLInputElement>, 'onChange'> {
45
45
  /** Radio button id */
46
46
  id?: string,
47
47
  /** Disabled state */
@@ -63,3 +63,19 @@ export const createResetHandler = (
63
63
  },
64
64
  });
65
65
  };
66
+
67
+ export const createSetValueHandler = (
68
+ props: RatingProps,
69
+ setValue: React.Dispatch<React.SetStateAction<RatingValue>>,
70
+ ) => (value: unknown) => {
71
+ const newValue = value as RatingValue;
72
+ setValue(newValue);
73
+
74
+ props.onChange?.({
75
+ component: {
76
+ index: isNil(newValue) ? -1 : newValue - 1,
77
+ name: props.name,
78
+ value: newValue,
79
+ },
80
+ });
81
+ };