@true-engineering/true-react-common-ui-kit 4.0.0-alpha27 → 4.0.0-alpha29

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": "4.0.0-alpha27",
3
+ "version": "4.0.0-alpha29",
4
4
  "description": "True Engineering React UI Kit with theming support",
5
5
  "author": "True Engineering (https://trueengineering.ru)",
6
6
  "keywords": [
@@ -1,6 +1,10 @@
1
1
  import { useMemo } from 'react';
2
- import { addDataTestId, getTestId } from '@true-engineering/true-react-platform-helpers';
3
- import { addDataAttributes } from '../../helpers';
2
+ import {
3
+ addDataAttributes,
4
+ addDataTestId,
5
+ getTestId,
6
+ isNotEmpty,
7
+ } from '@true-engineering/true-react-platform-helpers';
4
8
  import { useTweakStyles } from '../../hooks';
5
9
  import { ICommonProps } from '../../types';
6
10
  import { Button } from '../Button';
@@ -70,7 +74,7 @@ export function FiltersPane<Values extends Record<string, unknown>, Content = Va
70
74
  const filtersKeys = enabledFilters ?? Object.keys(filtersConfig);
71
75
 
72
76
  const handleClear = () => {
73
- if (onClear !== undefined) {
77
+ if (isNotEmpty(onClear)) {
74
78
  onClear();
75
79
  return;
76
80
  }
@@ -82,8 +86,7 @@ export function FiltersPane<Values extends Record<string, unknown>, Content = Va
82
86
 
83
87
  const shouldShowClearButton =
84
88
  hasClearButton &&
85
- (search !== undefined ||
86
- filtersKeys.filter((key) => filtersConfig[key] !== undefined).length > 0);
89
+ (isNotEmpty(search) || filtersKeys.some((key) => isNotEmpty(filtersConfig[key])));
87
90
 
88
91
  const clearButton = (
89
92
  <div className={classes.clear}>
@@ -101,7 +104,7 @@ export function FiltersPane<Values extends Record<string, unknown>, Content = Va
101
104
  );
102
105
 
103
106
  return (
104
- <div className={classes.root} {...addDataTestId(testId)} {...addDataAttributes(data)}>
107
+ <div className={classes.root} {...addDataAttributes(data, testId)}>
105
108
  {/* Settings */}
106
109
  {onSettingsButtonClick !== undefined && (
107
110
  <div
@@ -1,4 +1,5 @@
1
1
  import { useMemo } from 'react';
2
+ import { getTestId } from '@true-engineering/true-react-platform-helpers';
2
3
  import { getLocale } from '../../helpers';
3
4
  import { FilterInterval } from '../FilterInterval';
4
5
  import { FilterMultiSelect } from '../FilterMultiSelect';
@@ -32,7 +33,7 @@ export function Filter<Values extends Record<string, unknown>, Key extends keyof
32
33
  onClose={onClose}
33
34
  localeKey={translatesLocaleKey}
34
35
  locale={translates}
35
- testId={testId !== undefined ? `${testId}-select` : undefined}
36
+ testId={getTestId(testId, 'select')}
36
37
  {...filter}
37
38
  />
38
39
  );
@@ -48,7 +49,7 @@ export function Filter<Values extends Record<string, unknown>, Key extends keyof
48
49
  onClose={onClose}
49
50
  localeKey={translatesLocaleKey}
50
51
  locale={translates}
51
- testId={testId !== undefined ? `${testId}-period` : undefined}
52
+ testId={getTestId(testId, 'period')}
52
53
  {...filter}
53
54
  />
54
55
  );
@@ -64,14 +65,14 @@ export function Filter<Values extends Record<string, unknown>, Key extends keyof
64
65
  onEndBtnSubmit={() => onChange(undefined)}
65
66
  localeKey={translatesLocaleKey}
66
67
  locale={translates}
67
- testId={testId !== undefined ? `${testId}-dates` : undefined}
68
+ testId={getTestId(testId, 'dates')}
68
69
  {...filter}
69
70
  />
70
71
  );
71
72
  }
72
73
 
73
74
  if (filter.type === 'multiSelect') {
74
- const preparedValue = isMultiSelectValue<any>(value) ? value : undefined;
75
+ const preparedValue = isMultiSelectValue<any>(value) ? value : undefined; // eslint-disable-line @typescript-eslint/no-explicit-any
75
76
 
76
77
  return (
77
78
  <FilterMultiSelect
@@ -80,7 +81,7 @@ export function Filter<Values extends Record<string, unknown>, Key extends keyof
80
81
  onClose={onClose}
81
82
  localeKey={translatesLocaleKey}
82
83
  locale={translates}
83
- testId={testId !== undefined ? `${testId}-multiSelect` : undefined}
84
+ testId={getTestId(testId, 'multiSelect')}
84
85
  {...filter}
85
86
  />
86
87
  );
@@ -96,26 +97,24 @@ export function Filter<Values extends Record<string, unknown>, Key extends keyof
96
97
  localeKey={translatesLocaleKey}
97
98
  locale={translates}
98
99
  labelName={filter.name}
99
- testId={testId !== undefined ? `${testId}-interval` : undefined}
100
+ testId={getTestId(testId, 'interval')}
100
101
  {...filter}
101
102
  />
102
103
  );
103
104
  }
104
105
 
105
- if (filter.type === 'boolean') {
106
- return null;
107
- }
108
-
109
106
  if (filter.type === 'custom' && filter.component) {
110
107
  const Component = filter.component;
111
108
 
112
- return <Component {...props} filter={filter} />;
109
+ return <Component {...props} filter={filter} testId={getTestId(testId, 'dropdown')} />;
113
110
  }
114
111
 
115
- console.warn(
116
- `%cДля фильтра ${filter.name} не задан тип или component`,
117
- 'background: red; color: black',
118
- );
112
+ if (filter.type !== 'boolean') {
113
+ console.warn(
114
+ `%cДля фильтра ${filter.name} не задан тип или component`,
115
+ 'background: red; color: black',
116
+ );
117
+ }
119
118
 
120
119
  return null;
121
120
  }
@@ -1,4 +1,5 @@
1
1
  import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { getTestId } from '@true-engineering/true-react-platform-helpers';
2
3
  import { useOnClickOutside, useTweakStyles } from '../../../../hooks';
3
4
  import { ICommonProps } from '../../../../types';
4
5
  import { PERIODS, PERIODS_GETTERS } from '../../constants';
@@ -146,7 +147,7 @@ export const FilterWithPeriod: FC<IFilterWithPeriodProps> = ({
146
147
  locale={translates}
147
148
  tweakStyles={tweakSelectStyles}
148
149
  getValueView={getPeriodTranslate}
149
- testId={testId !== undefined ? `${testId}-select` : undefined}
150
+ testId={getTestId(testId, 'select')}
150
151
  />
151
152
  </div>
152
153
  )}
@@ -168,7 +169,7 @@ export const FilterWithPeriod: FC<IFilterWithPeriodProps> = ({
168
169
  onChange={handleCustomDateChange}
169
170
  localeKey={localeKey}
170
171
  locale={translates}
171
- testId={testId !== undefined ? `${testId}-dates` : undefined}
172
+ testId={getTestId(testId, 'dates')}
172
173
  />
173
174
  </div>
174
175
  )}
@@ -1,7 +1,10 @@
1
1
  import { MouseEventHandler } from 'react';
2
2
  import clsx from 'clsx';
3
- import { addDataTestId, getTestId } from '@true-engineering/true-react-platform-helpers';
4
- import { addDataAttributes } from '../../../../helpers';
3
+ import {
4
+ addDataAttributes,
5
+ getTestId,
6
+ isNotEmpty,
7
+ } from '@true-engineering/true-react-platform-helpers';
5
8
  import { useTweakStyles } from '../../../../hooks';
6
9
  import { ICommonProps } from '../../../../types';
7
10
  import { Icon } from '../../../Icon';
@@ -93,8 +96,7 @@ export function FilterWrapper<Values extends Record<string, unknown>, Key extend
93
96
  [classes.boolean]: isBoolean,
94
97
  [classes.disabled]: isDisabled,
95
98
  })}
96
- {...addDataTestId(testId)}
97
- {...addDataAttributes(data)}
99
+ {...addDataAttributes(data, testId)}
98
100
  {...referenceProps}
99
101
  >
100
102
  <div
@@ -102,7 +104,7 @@ export function FilterWrapper<Values extends Record<string, unknown>, Key extend
102
104
  className={clsx(classes.item, { [classes.booleanItem]: isBoolean })}
103
105
  >
104
106
  <div className={classes.name}>{filter.name}</div>
105
- {!isBoolean && value !== undefined && value !== null && (
107
+ {!isBoolean && isNotEmpty(value) && (
106
108
  <div className={classes.value}>
107
109
  <FilterValueView
108
110
  value={value}
@@ -33,6 +33,11 @@ export const useStyles = createThemedStyles('FiltersPaneSearch', {
33
33
  },
34
34
  },
35
35
 
36
+ hasValue: {
37
+ backgroundColor: colors.CLASSIC_WHITE,
38
+ borderColor: colors.BORDER_MAIN,
39
+ },
40
+
36
41
  selectWrapper: {
37
42
  position: 'relative',
38
43
  display: 'flex',
@@ -1,6 +1,13 @@
1
1
  import { ReactNode, useMemo, useRef, useState } from 'react';
2
2
  import clsx from 'clsx';
3
- import { addDataAttributes } from '../../../../helpers';
3
+ import {
4
+ addDataAttributes,
5
+ addDataTestId,
6
+ getTestId,
7
+ isArrayLikeNotEmpty,
8
+ isArrayNotEmpty,
9
+ isNotEmpty,
10
+ } from '@true-engineering/true-react-platform-helpers';
4
11
  import { useOnClickOutside, useTweakStyles } from '../../../../hooks';
5
12
  import { ICommonProps } from '../../../../types';
6
13
  import { Icon } from '../../../Icon';
@@ -89,20 +96,15 @@ export function FiltersPaneSearch<Value>({
89
96
  setIsOpen(false);
90
97
  };
91
98
 
92
- const selectedFieldLabel = useMemo(
93
- () => (field !== undefined && getValueView !== undefined ? getValueView(field) : undefined),
94
- [field],
95
- );
96
-
97
99
  return (
98
100
  <div
99
101
  className={clsx(classes.root, {
100
102
  [classes.focused]: isInputFocused,
101
103
  [classes.disabled]: isDisabled,
104
+ [classes.hasValue]: isArrayLikeNotEmpty(value),
102
105
  })}
103
106
  ref={refRoot}
104
- data-testid={testId}
105
- {...addDataAttributes(data)}
107
+ {...addDataAttributes(data, testId)}
106
108
  >
107
109
  <SearchInput
108
110
  value={value}
@@ -111,26 +113,21 @@ export function FiltersPaneSearch<Value>({
111
113
  tweakStyles={tweakSearchInputStyles}
112
114
  onFocus={() => setIsInputFocused(true)}
113
115
  onBlur={() => setIsInputFocused(false)}
114
- testId={testId !== undefined ? `${testId}-input` : undefined}
116
+ testId={getTestId(testId, 'input')}
115
117
  maxLength={maxLength}
116
118
  isDisabled={isDisabled}
117
119
  />
118
120
 
119
121
  <div className={classes.selectWrapper}>
120
122
  {/* Select block */}
121
- {fields.length > 0 && (
123
+ {isArrayNotEmpty(fields) && (
122
124
  <div
123
125
  className={classes.selectBlock}
124
126
  onClick={!isDisabled ? () => setIsOpen(!isOpen) : undefined}
125
- data-testid={testId !== undefined ? `${testId}-select` : undefined}
127
+ {...addDataTestId(testId, 'select')}
126
128
  >
127
- <div
128
- className={clsx(
129
- classes.selectLabel,
130
- selectedFieldLabel !== undefined && classes.active,
131
- )}
132
- >
133
- {selectedFieldLabel ?? translates.displayedFields}
129
+ <div className={clsx(classes.selectLabel, { [classes.active]: isNotEmpty(field) })}>
130
+ {isNotEmpty(field) ? getValueView?.(field) : translates.displayedFields}
134
131
  </div>
135
132
  <div className={clsx(classes.chevronIcon, isOpen && classes.open)}>
136
133
  <Icon type="chevron-down" />
@@ -152,7 +149,7 @@ export function FiltersPaneSearch<Value>({
152
149
  onChange={handleFieldsChange}
153
150
  isSearchEnabled={isSelectSearchEnabled}
154
151
  hasClearButton={hasClearSelectButton}
155
- testId={testId !== undefined ? `${testId}-dropdown` : undefined}
152
+ testId={getTestId(testId, 'dropdown')}
156
153
  />
157
154
  </div>
158
155
  )}
@@ -1,4 +1,5 @@
1
1
  import { FC, ReactNode } from 'react';
2
+ import { ITestIdProps } from '../../types';
2
3
  import { IDatePickerProps } from '../DatePicker';
3
4
  import { IMultiSelectListValues } from '../MultiSelectList';
4
5
  import type {
@@ -84,7 +85,7 @@ export type IDateRangeConfigItem<Value> = IConfigItemBasicBase<Value> & {
84
85
  dateFormat?: string;
85
86
  } & Omit<IFilterWithPeriodProps, 'value' | 'onChange' | 'setIsOpen'>;
86
87
 
87
- export interface ICustomComponentProps<Value> {
88
+ export interface ICustomComponentProps<Value> extends ITestIdProps {
88
89
  value?: Value;
89
90
  onChange: (v?: Value) => void;
90
91
  onClose?: () => void;
@@ -116,13 +116,14 @@ export const WithPopup: FC<IWithPopupProps> = ({
116
116
  const classes = useStyles({ theme: tweakStyles });
117
117
 
118
118
  const [isOpen, setIsOpen] = useState(false);
119
+ const isActive = isOpen && !isDisabled;
119
120
 
120
121
  const arrowRef = useRef<SVGSVGElement>(null);
121
122
 
122
- const handleToggle = (isActive: boolean, event?: IWithPopupToggleEvent) => {
123
+ const handleToggle = (next: boolean, event?: IWithPopupToggleEvent) => {
123
124
  event?.stopPropagation();
124
- onToggle?.(isActive, event);
125
- setIsOpen(isActive);
125
+ onToggle?.(next, event);
126
+ setIsOpen(next);
126
127
  };
127
128
 
128
129
  const handleClose = (event?: IWithPopupToggleEvent) => {
@@ -130,7 +131,7 @@ export const WithPopup: FC<IWithPopupProps> = ({
130
131
  };
131
132
 
132
133
  const { refs, floatingStyles, context } = useFloating({
133
- open: isOpen && !isDisabled,
134
+ open: isActive,
134
135
  middleware: [
135
136
  offset(popupOffset),
136
137
  canBeFlipped && flip({ fallbackAxisSideDirection: 'start' }),
@@ -177,7 +178,7 @@ export const WithPopup: FC<IWithPopupProps> = ({
177
178
  const triggerElement = applyAction(trigger, {
178
179
  referenceProps: !isTriggerWrapped ? referenceProps : undefined,
179
180
  triggerProps: {
180
- isActive: isOpen,
181
+ isActive,
181
182
  isDisabled,
182
183
  ...(!isTriggerWrapped && { data, testId, ...referenceProps }),
183
184
  },
@@ -190,7 +191,7 @@ export const WithPopup: FC<IWithPopupProps> = ({
190
191
  className={clsx(classes.trigger, {
191
192
  [classes.clickable]: eventType === 'click',
192
193
  [classes.disabled]: isDisabled,
193
- [classes.active]: isOpen,
194
+ [classes.active]: isActive,
194
195
  })}
195
196
  {...referenceProps}
196
197
  {...addDataAttributes(data, testId)}