@true-engineering/true-react-common-ui-kit 3.11.0 → 3.12.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@true-engineering/true-react-common-ui-kit",
3
- "version": "3.11.0",
3
+ "version": "3.12.0",
4
4
  "description": "True Engineering React UI Kit with theming support",
5
5
  "author": "True Engineering (https://trueengineering.ru)",
6
6
  "keywords": [
@@ -1,28 +1,54 @@
1
- import { ComponentStory, ComponentMeta } from '@storybook/react';
2
- import { Checkbox } from './Checkbox';
1
+ import { useState, FC } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import { Checkbox as CheckboxComponent, ICheckboxProps } from './Checkbox';
3
4
 
4
- export default {
5
+ const CheckboxComponentWithData: FC<ICheckboxProps<string>> = (props) => {
6
+ const [isChecked, setIsChecked] = useState(false);
7
+ const [isSemiChecked, setIsSemiChecked] = useState(false);
8
+
9
+ return (
10
+ <div style={{ gap: 10, display: 'grid' }}>
11
+ <CheckboxComponent
12
+ isChecked={isChecked}
13
+ isSemiChecked={isSemiChecked}
14
+ onSelect={({ isSelected }) => {
15
+ setIsChecked(isSelected);
16
+ setIsSemiChecked(false);
17
+ }}
18
+ {...props}
19
+ >
20
+ Use wrapping paper
21
+ </CheckboxComponent>
22
+ <CheckboxComponent
23
+ value={undefined}
24
+ isChecked={isSemiChecked}
25
+ onSelect={({ isSelected }) => setIsSemiChecked(isSelected)}
26
+ >
27
+ Is Semi Checked
28
+ </CheckboxComponent>
29
+ </div>
30
+ );
31
+ };
32
+
33
+ const meta: Meta<typeof CheckboxComponentWithData> = {
5
34
  title: 'Controls/Checkbox',
6
- component: Checkbox,
35
+ component: CheckboxComponentWithData,
7
36
  args: {
8
37
  value: 'value',
9
38
  labelPosition: 'right',
10
- isReadonly: false,
11
39
  isInvalid: false,
12
40
  isDisabled: false,
13
- isSemiChecked: false,
41
+ isReadonly: false,
14
42
  },
15
43
  parameters: {
16
44
  controls: {
17
45
  exclude: ['data', 'tweakStyles', 'testId', 'onSelect'],
18
46
  },
19
47
  },
20
- } as ComponentMeta<typeof Checkbox>;
48
+ };
49
+
50
+ export default meta;
51
+
52
+ type Story = StoryObj<typeof CheckboxComponent>;
21
53
 
22
- export const Default: ComponentStory<typeof Checkbox> = (args) => (
23
- <div style={{ width: 200 }}>
24
- <Checkbox {...args} onSelect={(value) => console.log('Value was selected', value)}>
25
- <div>Some text</div>
26
- </Checkbox>
27
- </div>
28
- );
54
+ export const Default: Story = {};
@@ -9,6 +9,10 @@ export const useStyles = createThemedStyles('Checkbox', {
9
9
  width: 'fit-content',
10
10
  },
11
11
 
12
+ checked: {},
13
+
14
+ invalid: {},
15
+
12
16
  disabled: {
13
17
  cursor: 'default',
14
18
  pointerEvents: 'none',
@@ -37,8 +41,6 @@ export const useStyles = createThemedStyles('Checkbox', {
37
41
  boxSizing: 'border-box',
38
42
  },
39
43
 
40
- checked: {},
41
-
42
44
  labelPositionLeft: {
43
45
  flexDirection: 'row-reverse',
44
46
  },
@@ -1,4 +1,4 @@
1
- import { useEffect, useState, ReactNode, ChangeEvent, KeyboardEvent } from 'react';
1
+ import { ReactNode, ChangeEvent, KeyboardEvent } from 'react';
2
2
  import clsx from 'clsx';
3
3
  import {
4
4
  addDataTestId,
@@ -11,57 +11,53 @@ import { Icon } from '../Icon';
11
11
  import { useStyles, ICheckboxStyles } from './Checkbox.styles';
12
12
 
13
13
  export interface ICheckboxProps<V> extends ICommonProps<ICheckboxStyles> {
14
+ value?: V;
14
15
  children?: ReactNode;
15
- isChecked: boolean | undefined;
16
+ /** @default false */
17
+ isChecked?: boolean;
16
18
  /** @default false */
17
19
  isSemiChecked?: boolean;
18
20
  /** @default false */
21
+ isInvalid?: boolean;
22
+ /** @default false */
19
23
  isDisabled?: boolean;
20
24
  /** @default false */
21
25
  isReadonly?: boolean;
22
- /** @default false */
23
- isInvalid?: boolean;
24
- value: V;
25
26
  /** @default 'right' */
26
27
  labelPosition?: 'right' | 'left';
27
- onSelect: (
28
- value: { value: V; isSelected: boolean },
28
+ onSelect?: (
29
+ value: { value?: V; isSelected: boolean },
29
30
  event: ChangeEvent<HTMLInputElement> | KeyboardEvent,
30
31
  ) => void;
31
32
  }
32
33
 
33
34
  export function Checkbox<V>({
35
+ value,
34
36
  children,
37
+ isChecked = false,
38
+ isSemiChecked = false,
39
+ isInvalid = false,
35
40
  isDisabled = false,
36
41
  isReadonly = false,
37
- isChecked = false,
38
- value,
42
+ labelPosition = 'right',
39
43
  data,
40
44
  testId,
41
- isSemiChecked = false,
42
- labelPosition = 'right',
43
45
  tweakStyles,
44
46
  onSelect,
45
47
  }: ICheckboxProps<V>): JSX.Element {
46
48
  const classes = useStyles({ theme: tweakStyles });
47
49
 
48
- const [isSelected, setIsSelected] = useState(false);
49
-
50
50
  const hasAction = !isDisabled && !isReadonly;
51
+ const isSelected = isChecked || isSemiChecked;
51
52
 
52
- const onToggle = (event: ChangeEvent<HTMLInputElement> | KeyboardEvent) => {
53
- const isSelectedNext = !isSelected;
54
- onSelect({ value, isSelected: isSelectedNext }, event);
55
- setIsSelected(isSelectedNext);
56
- };
57
-
58
- useEffect(() => {
59
- setIsSelected(isChecked);
60
- }, [isChecked]);
53
+ const onToggle = (event: ChangeEvent<HTMLInputElement> | KeyboardEvent) =>
54
+ onSelect?.({ value, isSelected: !isSelected }, event);
61
55
 
62
56
  return (
63
57
  <label
64
58
  className={clsx(classes.root, {
59
+ [classes.checked]: isSelected,
60
+ [classes.invalid]: isInvalid,
65
61
  [classes.disabled]: isDisabled,
66
62
  [classes.labelPositionLeft]: labelPosition === 'left',
67
63
  })}
@@ -69,8 +65,8 @@ export function Checkbox<V>({
69
65
  {...addDataAttributes(data)}
70
66
  >
71
67
  <input
72
- type="checkbox"
73
68
  className={classes.input}
69
+ type="checkbox"
74
70
  checked={isSelected}
75
71
  disabled={isDisabled}
76
72
  readOnly={isReadonly}
@@ -79,8 +75,8 @@ export function Checkbox<V>({
79
75
  onKeyDown: getSelectKeyHandler(onToggle),
80
76
  })}
81
77
  />
82
- <div className={clsx(classes.check, isSelected && classes.checked)}>
83
- <Icon type={isSemiChecked ? 'minus' : 'check'} />
78
+ <div className={classes.check}>
79
+ {isSelected && <Icon type={isSemiChecked ? 'minus' : 'check'} />}
84
80
  </div>
85
81
  {isReactNodeNotEmpty(children) && <div className={classes.children}>{children}</div>}
86
82
  </label>
@@ -123,10 +123,11 @@ export const iconsList = checkIcons({
123
123
  check: {
124
124
  paths: [
125
125
  {
126
- d: 'M9.333 11.252l4.96-4.96a1 1 0 011.414 1.415l-5.667 5.667a1 1 0 01-1.414 0L6.293 11.04a1 1 0 111.414-1.414l1.626 1.626z',
126
+ d: 'm7.5 13.086 7.793-7.793a1 1 0 1 1 1.414 1.414l-8.5 8.5a1 1 0 0 1-1.414 0l-3.5-3.5a1 1 0 1 1 1.414-1.414L7.5 13.086Z',
127
127
  },
128
128
  ],
129
129
  },
130
+ /** @deprecated */
130
131
  'check-big': {
131
132
  paths: [
132
133
  {
@@ -138,17 +139,8 @@ export const iconsList = checkIcons({
138
139
  viewBox: '0 0 20 20',
139
140
  paths: [
140
141
  {
141
- d: 'M3 10.5L5.92929 13.4293C5.96834 13.4683 6.03166 13.4683 6.07071 13.4293L13.5 6',
142
- strokeWidth: 2,
143
- strokeLinecap: 'round' as const,
144
- stroke: 'currentColor',
145
- fill: 'none',
146
- },
147
- {
148
- d: 'M10.2071 13.2929L9.5 12.5858L8.08579 14L8.79289 14.7071L10.2071 13.2929ZM18.2071 7.70711C18.5976 7.31658 18.5976 6.68342 18.2071 6.29289C17.8166 5.90237 17.1834 5.90237 16.7929 6.29289L18.2071 7.70711ZM9.92929 14.4293L10.6364 13.7222L9.92929 14.4293ZM10.0707 14.4293L9.3636 13.7222L10.0707 14.4293ZM8.79289 14.7071L9.22218 15.1364L10.6364 13.7222L10.2071 13.2929L8.79289 14.7071ZM10.7778 15.1364L18.2071 7.70711L16.7929 6.29289L9.3636 13.7222L10.7778 15.1364ZM9.22218 15.1364C9.65176 15.566 10.3482 15.566 10.7778 15.1364L9.3636 13.7222C9.71508 13.3707 10.2849 13.3707 10.6364 13.7222L9.22218 15.1364Z',
149
- fill: 'currentColor',
150
- stroke: 'none',
151
- fillRule: undefined,
142
+ d: 'M14.207 6.707a1 1 0 0 0-1.414-1.414L6 12.086 3.707 9.793a1 1 0 0 0-1.414 1.414l2.93 2.93a1.1 1.1 0 0 0 1.555 0l7.43-7.43Zm4 1a1 1 0 0 0-1.414-1.414L10 13.086l-.5-.5L8.086 14l1.136 1.136a1.1 1.1 0 0 0 1.556 0l7.43-7.429Z',
143
+ fillRule: 'evenodd',
152
144
  },
153
145
  ],
154
146
  },
@@ -466,7 +458,7 @@ export const iconsList = checkIcons({
466
458
  minus: {
467
459
  paths: [
468
460
  {
469
- d: 'M16 11H4c-.552 0-1-.448-1-1s.448-1 1-1h12c.552 0 1 .448 1 1s-.448 1-1 1z',
461
+ d: 'M16 11H4a1 1 0 1 1 0-2h12a1 1 0 1 1 0 2Z',
470
462
  },
471
463
  ],
472
464
  },
@@ -1,6 +1,7 @@
1
1
  import { useEffect, useState, useMemo, useRef, useCallback, ReactNode } from 'react';
2
2
  import clsx from 'clsx';
3
3
  import { debounce } from 'ts-debounce';
4
+ import { isNotEmpty } from '@true-engineering/true-react-platform-helpers';
4
5
  import { addDataAttributes } from '../../helpers';
5
6
  import { useIsMounted, useTweakStyles } from '../../hooks';
6
7
  import { ICommonProps } from '../../types';
@@ -167,12 +168,14 @@ export function MultiSelectList<Value extends IMultiSelectListValues<Option>, Op
167
168
  onChange(undefined);
168
169
  };
169
170
 
170
- const onSelect: ICheckboxProps<Option>['onSelect'] = (val) => {
171
- handleSelectValue(
172
- val.isSelected
173
- ? [...(chosenValues ?? []), val.value]
174
- : chosenValues?.filter((v) => getValueId(v) !== getValueId(val.value)) ?? [],
175
- );
171
+ const onSelect: ICheckboxProps<Option>['onSelect'] = ({ value: checkboxValue, isSelected }) => {
172
+ if (isNotEmpty(checkboxValue)) {
173
+ handleSelectValue(
174
+ isSelected
175
+ ? [...(chosenValues ?? []), checkboxValue]
176
+ : chosenValues?.filter((v) => getValueId(v) !== getValueId(checkboxValue)) ?? [],
177
+ );
178
+ }
176
179
  };
177
180
 
178
181
  const handleKeyDown = (event: KeyboardEvent) => {