@true-engineering/true-react-common-ui-kit 4.0.0-alpha6 → 4.0.0-alpha7
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/README.md +64 -4
- package/dist/components/Button/Button.styles.d.ts +1 -1
- package/dist/components/Checkbox/Checkbox.styles.d.ts +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +2 -2
- package/dist/components/DatePicker/helpers.d.ts +3 -0
- package/dist/components/DatePicker/types.d.ts +3 -1
- package/dist/components/FiltersPane/FiltersPane.d.ts +4 -2
- package/dist/components/FiltersPane/FiltersPane.stories.d.ts +3 -3
- package/dist/components/FiltersPane/components/Filter/Filter.d.ts +2 -2
- package/dist/components/FiltersPane/components/Filter/helpers.d.ts +4 -0
- package/dist/components/FiltersPane/components/FilterInterval/FilterInterval.styles.d.ts +1 -1
- package/dist/components/FiltersPane/components/FilterSelect/FilterSelect.styles.d.ts +1 -1
- package/dist/components/FiltersPane/components/FilterValueView/FilterValueView.d.ts +3 -1
- package/dist/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.d.ts +2 -2
- package/dist/components/FiltersPane/components/FilterWrapper/FilterWrapper.d.ts +2 -2
- package/dist/components/FlexibleTable/FlexibleTable.d.ts +4 -2
- package/dist/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.d.ts +2 -3
- package/dist/components/Select/Select.styles.d.ts +2 -2
- package/dist/components/WithMessages/WithMessages.styles.d.ts +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-merge.d.ts +1 -0
- package/dist/hooks/use-mixed-styles.d.ts +3 -1
- package/dist/hooks/use-tweak-styles.d.ts +5 -5
- package/dist/theme/Provider.d.ts +6 -3
- package/dist/theme/create-themed-styles.d.ts +2 -0
- package/dist/theme/helpers.d.ts +9 -3
- package/dist/theme/index.d.ts +2 -0
- package/dist/theme/true-jss/ThemedStylesManager.d.ts +18 -0
- package/dist/theme/true-jss/TweakStylesManager.d.ts +34 -0
- package/dist/theme/true-jss/index.d.ts +2 -0
- package/dist/theme/true-jss/jss-context.d.ts +9 -0
- package/dist/theme/types.d.ts +4 -2
- package/dist/true-react-common-ui-kit.js +6845 -5944
- package/dist/true-react-common-ui-kit.js.map +1 -1
- package/dist/true-react-common-ui-kit.umd.cjs +6649 -5749
- package/dist/true-react-common-ui-kit.umd.cjs.map +1 -1
- package/dist/types.d.ts +2 -1
- package/package.json +1 -1
- package/src/components/DatePicker/DatePicker.tsx +9 -4
- package/src/components/DatePicker/helpers.ts +13 -1
- package/src/components/DatePicker/types.ts +4 -1
- package/src/components/FiltersPane/FiltersPane.stories.tsx +4 -2
- package/src/components/FiltersPane/FiltersPane.tsx +14 -9
- package/src/components/FiltersPane/components/Filter/Filter.tsx +24 -17
- package/src/components/FiltersPane/components/Filter/helpers.ts +18 -0
- package/src/components/FiltersPane/components/FilterValueView/FilterValueView.tsx +8 -5
- package/src/components/FiltersPane/components/FilterWithDates/FilterWithDates.styles.ts +1 -0
- package/src/components/FiltersPane/components/FilterWithPeriod/FilterWithPeriod.tsx +1 -1
- package/src/components/FiltersPane/components/FilterWrapper/FilterWrapper.tsx +7 -5
- package/src/components/FlexibleTable/FlexibleTable.tsx +12 -12
- package/src/components/FlexibleTable/components/FlexibleTableRow/FlexibleTableRow.tsx +3 -5
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-merge.ts +8 -0
- package/src/hooks/use-mixed-styles.ts +9 -11
- package/src/hooks/use-tweak-styles.ts +49 -27
- package/src/theme/Provider.tsx +10 -5
- package/src/theme/create-themed-styles.ts +78 -0
- package/src/theme/helpers.ts +39 -39
- package/src/theme/index.ts +2 -0
- package/src/theme/true-jss/ThemedStylesManager.ts +92 -0
- package/src/theme/true-jss/TweakStylesManager.ts +157 -0
- package/src/theme/true-jss/index.ts +2 -0
- package/src/theme/true-jss/jss-context.tsx +34 -0
- package/src/theme/types.ts +4 -2
- package/src/types.ts +2 -1
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FocusEventHandler, type KeyboardEvent, KeyboardEventHandler, MouseEvent, MouseEventHandler, PointerEventHandler, ReactNode } from 'react';
|
|
2
2
|
import { Modifier, Placement } from 'react-overlays/usePopper';
|
|
3
|
+
import type { IMaybeArray } from './theme';
|
|
3
4
|
export interface ITestIdProps {
|
|
4
5
|
testId?: string;
|
|
5
6
|
}
|
|
@@ -10,7 +11,7 @@ export interface IDataAttributesProps extends ITestIdProps {
|
|
|
10
11
|
data?: IDataAttributes;
|
|
11
12
|
}
|
|
12
13
|
export interface ITweakStylesProps<TweakStyles> {
|
|
13
|
-
tweakStyles?: TweakStyles
|
|
14
|
+
tweakStyles?: IMaybeArray<TweakStyles>;
|
|
14
15
|
}
|
|
15
16
|
export type ICommonProps<TweakStyles> = IDataAttributesProps & ITweakStylesProps<TweakStyles>;
|
|
16
17
|
export interface IDropdownWithPopperOptions {
|
package/package.json
CHANGED
|
@@ -14,13 +14,18 @@ import { ICommonProps } from '../../types';
|
|
|
14
14
|
import { DateInput, EMPTY_DATE_INPUT_VALUE, IDateInputProps } from '../DateInput';
|
|
15
15
|
import { DatePickerHeader, PopperContainer } from './components';
|
|
16
16
|
import { DatePickerComponent, DEFAULT_DATE_FORMAT } from './constants';
|
|
17
|
-
import {
|
|
18
|
-
|
|
17
|
+
import {
|
|
18
|
+
areDatesEquals,
|
|
19
|
+
getDateFormatter,
|
|
20
|
+
getDateValueParser,
|
|
21
|
+
preparateDatePickerLocale,
|
|
22
|
+
} from './helpers';
|
|
23
|
+
import { IDatePickerBaseProps, IDatePickerLocale, IRange } from './types';
|
|
19
24
|
import { IDatePickerStyles, useStyles } from './DatePicker.styles';
|
|
20
25
|
|
|
21
26
|
export interface IDatePickerProps extends IDatePickerBaseProps, ICommonProps<IDatePickerStyles> {
|
|
22
27
|
selectedDate?: Date | null;
|
|
23
|
-
locale:
|
|
28
|
+
locale: IDatePickerLocale;
|
|
24
29
|
months?: string[];
|
|
25
30
|
/** @default 'dd.MM.yyyy' */
|
|
26
31
|
dateFormat?: string;
|
|
@@ -242,7 +247,7 @@ export const DatePicker = forwardRef<ReactDatePicker, IDatePickerProps>(
|
|
|
242
247
|
ref={ref}
|
|
243
248
|
minDate={minDate}
|
|
244
249
|
maxDate={maxDate}
|
|
245
|
-
locale={locale}
|
|
250
|
+
locale={preparateDatePickerLocale(locale)}
|
|
246
251
|
dateFormat={dateFormat}
|
|
247
252
|
placeholderText={placeholder}
|
|
248
253
|
calendarStartDay={calendarStartDay}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { parse, format, isSameDay } from 'date-fns';
|
|
1
|
+
import { parse, format, isSameDay, type Locale } from 'date-fns';
|
|
2
|
+
import { ru as ruLocale, enUS as enLocale } from 'date-fns/locale';
|
|
2
3
|
import {
|
|
3
4
|
isEmpty,
|
|
4
5
|
isNotEmpty,
|
|
5
6
|
isStringNotEmpty,
|
|
6
7
|
} from '@true-engineering/true-react-platform-helpers';
|
|
7
8
|
import { EMPTY_DATE_INPUT_VALUE } from '../DateInput';
|
|
9
|
+
import { IDatePickerLocale } from './types';
|
|
8
10
|
|
|
9
11
|
export const getDateFormatter =
|
|
10
12
|
(dateFormat: string) =>
|
|
@@ -21,3 +23,13 @@ export const getDateValueParser =
|
|
|
21
23
|
export const areDatesEquals = (date1?: Date | null, date2?: Date | null): boolean =>
|
|
22
24
|
(isEmpty(date1) && isEmpty(date2)) ||
|
|
23
25
|
(isNotEmpty(date1) && isNotEmpty(date2) && isSameDay(date1, date2));
|
|
26
|
+
|
|
27
|
+
export const preparateDatePickerLocale = (locale: IDatePickerLocale): Locale => {
|
|
28
|
+
if (locale === 'ru') {
|
|
29
|
+
return ruLocale;
|
|
30
|
+
}
|
|
31
|
+
if (locale === 'en') {
|
|
32
|
+
return enLocale;
|
|
33
|
+
}
|
|
34
|
+
return locale;
|
|
35
|
+
};
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { ReactDatePickerProps } from 'react-datepicker';
|
|
2
|
-
import {
|
|
2
|
+
import { type Locale } from 'date-fns';
|
|
3
|
+
import { type IDateInputProps } from '../DateInput';
|
|
3
4
|
|
|
4
5
|
export type IRange = [Date | null, Date | null] | null;
|
|
5
6
|
|
|
7
|
+
export type IDatePickerLocale = 'ru' | 'en' | Locale;
|
|
8
|
+
|
|
6
9
|
export type IDatePickerBaseProps = Pick<
|
|
7
10
|
ReactDatePickerProps,
|
|
8
11
|
| 'startDate'
|
|
@@ -70,7 +70,8 @@ type ConfigValues = {
|
|
|
70
70
|
custom: string;
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
-
interface IFiltersPaneWithCustomProps<Values
|
|
73
|
+
interface IFiltersPaneWithCustomProps<Values extends Record<string, unknown>, Content>
|
|
74
|
+
extends IFiltersPaneProps<Values, Content> {
|
|
74
75
|
containerWidth: number;
|
|
75
76
|
isSearchDisabled: boolean;
|
|
76
77
|
shouldShowSettingsButton: boolean;
|
|
@@ -80,7 +81,7 @@ interface IFiltersPaneWithCustomProps<Values, Content> extends IFiltersPaneProps
|
|
|
80
81
|
isClearableFields: boolean;
|
|
81
82
|
}
|
|
82
83
|
|
|
83
|
-
function FiltersPaneWithCustomProps<Values, Content>({
|
|
84
|
+
function FiltersPaneWithCustomProps<Values extends Record<string, unknown>, Content>({
|
|
84
85
|
containerWidth,
|
|
85
86
|
isSearchDisabled,
|
|
86
87
|
shouldShowSettingsButton,
|
|
@@ -288,6 +289,7 @@ Default.args = {
|
|
|
288
289
|
hasClearButton: true,
|
|
289
290
|
isClearableFields: false,
|
|
290
291
|
isDisabled: false,
|
|
292
|
+
shouldRenderDataId: false,
|
|
291
293
|
containerWidth: 400,
|
|
292
294
|
withFieldNameInLabel: true,
|
|
293
295
|
isGroupingEnabled: true,
|
|
@@ -10,7 +10,7 @@ import { getLocale } from './helpers';
|
|
|
10
10
|
import { ConfigType, IFilterLocaleKey, IPartialFilterLocale } from './types';
|
|
11
11
|
import { useStyles, IFiltersPaneStyles, clearButtonStyles } from './FiltersPane.styles';
|
|
12
12
|
|
|
13
|
-
export interface IFiltersPaneProps<Values, Content = Values>
|
|
13
|
+
export interface IFiltersPaneProps<Values extends Record<string, unknown>, Content = Values>
|
|
14
14
|
extends ICommonProps<IFiltersPaneStyles> {
|
|
15
15
|
filtersConfig: ConfigType<Values>;
|
|
16
16
|
enabledFilters?: Array<keyof ConfigType<Values>>;
|
|
@@ -23,6 +23,8 @@ export interface IFiltersPaneProps<Values, Content = Values>
|
|
|
23
23
|
isDisabled?: boolean;
|
|
24
24
|
/** @default true */
|
|
25
25
|
hasClearButton?: boolean;
|
|
26
|
+
/** @default false */
|
|
27
|
+
shouldRenderDataId?: boolean;
|
|
26
28
|
onChangeFilters: (values: Partial<Values>) => void;
|
|
27
29
|
onSettingsButtonClick?: () => void;
|
|
28
30
|
onClear?: () => void;
|
|
@@ -39,6 +41,7 @@ export function FiltersPane<Values extends Record<string, unknown>, Content = Va
|
|
|
39
41
|
search,
|
|
40
42
|
isDisabled = false,
|
|
41
43
|
hasClearButton = true,
|
|
44
|
+
shouldRenderDataId = false,
|
|
42
45
|
testId,
|
|
43
46
|
onChangeFilters,
|
|
44
47
|
onSettingsButtonClick,
|
|
@@ -61,7 +64,7 @@ export function FiltersPane<Values extends Record<string, unknown>, Content = Va
|
|
|
61
64
|
|
|
62
65
|
const translates = useMemo(() => getLocale(localeKey, locale), [localeKey, locale]);
|
|
63
66
|
|
|
64
|
-
const filtersKeys = enabledFilters
|
|
67
|
+
const filtersKeys = enabledFilters ?? Object.keys(filtersConfig);
|
|
65
68
|
|
|
66
69
|
const handleClear = () => {
|
|
67
70
|
if (onClear !== undefined) {
|
|
@@ -122,10 +125,11 @@ export function FiltersPane<Values extends Record<string, unknown>, Content = Va
|
|
|
122
125
|
{/* Filters */}
|
|
123
126
|
{filtersKeys.map((key, index) => {
|
|
124
127
|
const isLast = index === filtersKeys.length - 1;
|
|
125
|
-
const
|
|
126
|
-
const
|
|
128
|
+
const filterKey = String(key);
|
|
129
|
+
const currentValue = values[filterKey];
|
|
130
|
+
const filter = filtersConfig[filterKey];
|
|
127
131
|
if (filter === undefined) {
|
|
128
|
-
console.error(`enabledFilters содержит фильтр ${
|
|
132
|
+
console.error(`enabledFilters содержит фильтр ${filterKey}, не описанный в конфиге`);
|
|
129
133
|
if (isLast) {
|
|
130
134
|
return clearButton;
|
|
131
135
|
}
|
|
@@ -137,18 +141,19 @@ export function FiltersPane<Values extends Record<string, unknown>, Content = Va
|
|
|
137
141
|
filter={filter}
|
|
138
142
|
locale={locale}
|
|
139
143
|
localeKey={localeKey}
|
|
140
|
-
onChange={(value) => onChangeFilters({ ...values, [
|
|
144
|
+
onChange={(value) => onChangeFilters({ ...values, [filterKey]: value })}
|
|
141
145
|
value={currentValue}
|
|
142
|
-
key={
|
|
146
|
+
key={filterKey}
|
|
143
147
|
isDisabled={isDisabled || filter?.requiredFilledFilters?.some((item) => !values[item])}
|
|
144
148
|
tweakStyles={tweakFilterWrapperStyles}
|
|
145
|
-
|
|
149
|
+
data={shouldRenderDataId ? { id: filterKey } : undefined}
|
|
150
|
+
testId={getTestId(testId, `filter-${filterKey}`)}
|
|
146
151
|
/>
|
|
147
152
|
);
|
|
148
153
|
|
|
149
154
|
if (isLast) {
|
|
150
155
|
return (
|
|
151
|
-
<div className={classes.filterWithClearButton} key={
|
|
156
|
+
<div className={classes.filterWithClearButton} key={filterKey}>
|
|
152
157
|
{filterWrapper}
|
|
153
158
|
{shouldShowClearButton && <>{clearButton}</>}
|
|
154
159
|
</div>
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
2
|
import { getLocale } from '../../helpers';
|
|
3
|
-
import { IFilterMultiSelectValues, IFilterWithDatesValue, IPeriod } from '../../types';
|
|
4
3
|
import { FilterInterval } from '../FilterInterval';
|
|
5
4
|
import { FilterMultiSelect } from '../FilterMultiSelect';
|
|
6
5
|
import { FilterSelect } from '../FilterSelect';
|
|
7
6
|
import { FilterWithDates } from '../FilterWithDates';
|
|
8
7
|
import { FilterWithPeriod } from '../FilterWithPeriod';
|
|
9
8
|
import type { IFilterWrapperProps } from '../FilterWrapper';
|
|
9
|
+
import { isDatePeriodValue, isMultiSelectValue, isPeriodValue } from './helpers';
|
|
10
10
|
|
|
11
|
-
export interface IFilterProps<Values, Key extends keyof Values>
|
|
11
|
+
export interface IFilterProps<Values extends Record<string, unknown>, Key extends keyof Values>
|
|
12
12
|
extends IFilterWrapperProps<Values, Key> {
|
|
13
13
|
onChange: <V>(v: V) => void;
|
|
14
14
|
onClose?: () => void;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export function Filter<Values, Key extends keyof Values>(
|
|
17
|
+
export function Filter<Values extends Record<string, unknown>, Key extends keyof Values>(
|
|
18
18
|
props: IFilterProps<Values, Key>,
|
|
19
19
|
): JSX.Element | null {
|
|
20
20
|
const { filter, value, onChange, onClose, localeKey, locale, testId } = props;
|
|
@@ -39,9 +39,11 @@ export function Filter<Values, Key extends keyof Values>(
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
if (filter.type === 'dateRange') {
|
|
42
|
+
const preparedValue = isPeriodValue(value) ? { ...value } : undefined;
|
|
43
|
+
|
|
42
44
|
return (
|
|
43
45
|
<FilterWithPeriod
|
|
44
|
-
value={
|
|
46
|
+
value={preparedValue}
|
|
45
47
|
onChange={onChange}
|
|
46
48
|
onClose={onClose}
|
|
47
49
|
localeKey={translatesLocaleKey}
|
|
@@ -53,25 +55,27 @@ export function Filter<Values, Key extends keyof Values>(
|
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
if (filter.type === 'dateRangeWithoutPeriod') {
|
|
58
|
+
const preparedValue = isDatePeriodValue(value) ? value : undefined;
|
|
59
|
+
|
|
56
60
|
return (
|
|
57
|
-
<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
/>
|
|
67
|
-
</div>
|
|
61
|
+
<FilterWithDates
|
|
62
|
+
value={preparedValue}
|
|
63
|
+
onChange={(v) => onChange({ ...v, periodType: 'CUSTOM' })}
|
|
64
|
+
onEndBtnSubmit={() => onChange(undefined)}
|
|
65
|
+
localeKey={translatesLocaleKey}
|
|
66
|
+
locale={translates}
|
|
67
|
+
testId={testId !== undefined ? `${testId}-dates` : undefined}
|
|
68
|
+
{...filter}
|
|
69
|
+
/>
|
|
68
70
|
);
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
if (filter.type === 'multiSelect') {
|
|
74
|
+
const preparedValue = isMultiSelectValue<any>(value) ? value : undefined;
|
|
75
|
+
|
|
72
76
|
return (
|
|
73
77
|
<FilterMultiSelect
|
|
74
|
-
value={
|
|
78
|
+
value={preparedValue}
|
|
75
79
|
onChange={onChange}
|
|
76
80
|
onClose={onClose}
|
|
77
81
|
localeKey={translatesLocaleKey}
|
|
@@ -83,9 +87,11 @@ export function Filter<Values, Key extends keyof Values>(
|
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
if (filter.type === 'interval') {
|
|
90
|
+
const preparedValue = Array.isArray(value) ? (value as number[]) : undefined;
|
|
91
|
+
|
|
86
92
|
return (
|
|
87
93
|
<FilterInterval
|
|
88
|
-
value={
|
|
94
|
+
value={preparedValue}
|
|
89
95
|
onChange={onChange}
|
|
90
96
|
localeKey={translatesLocaleKey}
|
|
91
97
|
locale={translates}
|
|
@@ -102,6 +108,7 @@ export function Filter<Values, Key extends keyof Values>(
|
|
|
102
108
|
|
|
103
109
|
if (filter.type === 'custom' && filter.component) {
|
|
104
110
|
const Component = filter.component;
|
|
111
|
+
|
|
105
112
|
return <Component {...props} filter={filter} />;
|
|
106
113
|
}
|
|
107
114
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { isEmpty, isString } from '@true-engineering/true-react-platform-helpers';
|
|
2
|
+
import { IDatePeriod, IFilterMultiSelectValues, IPeriod } from '../../types';
|
|
3
|
+
|
|
4
|
+
const isDateOrEmpty = (value: unknown): value is Date | null | undefined =>
|
|
5
|
+
isEmpty(value) || value instanceof Date;
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
|
|
8
|
+
export const isDatePeriodValue = (value: any): value is IDatePeriod =>
|
|
9
|
+
isDateOrEmpty(value?.from) && isDateOrEmpty(value?.to);
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
|
|
12
|
+
export const isPeriodValue = (value: any): value is IPeriod =>
|
|
13
|
+
isString(value?.periodType) && isDatePeriodValue(value);
|
|
14
|
+
|
|
15
|
+
export const isMultiSelectValue = <T extends string>(
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any
|
|
17
|
+
value: any,
|
|
18
|
+
): value is IFilterMultiSelectValues<T> => Array.isArray(value?.include);
|
|
@@ -9,14 +9,17 @@ import { IDateRangeConfigItem, IFilterWithDatesValue, IPeriod } from '../../type
|
|
|
9
9
|
import type { IFilterWrapperProps } from '../FilterWrapper';
|
|
10
10
|
import { IFilterValueViewStyles, useStyles } from './FilterValueView.styles';
|
|
11
11
|
|
|
12
|
-
export
|
|
12
|
+
export interface IFilterValueView<Values extends Record<string, unknown>, Key extends keyof Values>
|
|
13
|
+
extends Omit<IFilterWrapperProps<Values, Key>, 'filtersPaneRef' | 'tweakStyles' | 'onChange'>,
|
|
14
|
+
ICommonProps<IFilterValueViewStyles> {}
|
|
15
|
+
|
|
16
|
+
export function FilterValueView<Values extends Record<string, unknown>, Key extends keyof Values>({
|
|
17
|
+
value,
|
|
18
|
+
filter,
|
|
13
19
|
locale,
|
|
14
20
|
localeKey,
|
|
15
|
-
filter,
|
|
16
|
-
value,
|
|
17
21
|
tweakStyles,
|
|
18
|
-
}:
|
|
19
|
-
ICommonProps<IFilterValueViewStyles>): JSX.Element {
|
|
22
|
+
}: IFilterValueView<Values, Key>): JSX.Element {
|
|
20
23
|
const classes = useStyles({ theme: tweakStyles });
|
|
21
24
|
|
|
22
25
|
const translatesLocaleKey = filter.localeKey ?? localeKey;
|
|
@@ -151,7 +151,7 @@ export const FilterWithPeriod: FC<IFilterWithPeriodProps> = ({
|
|
|
151
151
|
</div>
|
|
152
152
|
)}
|
|
153
153
|
{isDatePickerShown && (
|
|
154
|
-
<div className={classes.picker}
|
|
154
|
+
<div className={classes.picker} ref={refDatePicker}>
|
|
155
155
|
<FilterWithDates
|
|
156
156
|
onStartBtnSubmit={() => {
|
|
157
157
|
setIsDatePickerShown(false);
|
|
@@ -12,8 +12,10 @@ import { FilterValueView } from '../FilterValueView';
|
|
|
12
12
|
import { isContentNotEmpty } from './helpers';
|
|
13
13
|
import { useStyles, IFilterWrapperStyles } from './FilterWrapper.styles';
|
|
14
14
|
|
|
15
|
-
export interface IFilterWrapperProps<
|
|
16
|
-
extends
|
|
15
|
+
export interface IFilterWrapperProps<
|
|
16
|
+
Values extends Record<string, unknown>,
|
|
17
|
+
Key extends keyof Values,
|
|
18
|
+
> extends ICommonProps<IFilterWrapperStyles> {
|
|
17
19
|
filter: ConfigItem<Values[Key]>;
|
|
18
20
|
value?: Values[Key];
|
|
19
21
|
isDisabled?: boolean;
|
|
@@ -22,7 +24,7 @@ export interface IFilterWrapperProps<Values, Key extends keyof Values>
|
|
|
22
24
|
onChange: <V>(value: V) => void;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
export function FilterWrapper<Values, Key extends keyof Values>({
|
|
27
|
+
export function FilterWrapper<Values extends Record<string, unknown>, Key extends keyof Values>({
|
|
26
28
|
filter,
|
|
27
29
|
value,
|
|
28
30
|
isDisabled,
|
|
@@ -105,8 +107,8 @@ export function FilterWrapper<Values, Key extends keyof Values>({
|
|
|
105
107
|
<FilterValueView
|
|
106
108
|
value={value}
|
|
107
109
|
filter={filter}
|
|
108
|
-
localeKey={localeKey}
|
|
109
110
|
locale={locale}
|
|
111
|
+
localeKey={localeKey}
|
|
110
112
|
testId={getTestId(testId, 'value')}
|
|
111
113
|
tweakStyles={tweakFilterValueViewStyles}
|
|
112
114
|
/>
|
|
@@ -137,8 +139,8 @@ export function FilterWrapper<Values, Key extends keyof Values>({
|
|
|
137
139
|
<Filter
|
|
138
140
|
value={value}
|
|
139
141
|
filter={filter}
|
|
140
|
-
localeKey={localeKey}
|
|
141
142
|
locale={locale}
|
|
143
|
+
localeKey={localeKey}
|
|
142
144
|
onClose={onClose}
|
|
143
145
|
onChange={onChange}
|
|
144
146
|
testId={testId}
|
|
@@ -34,7 +34,6 @@ export interface IFlexibleTableProps<
|
|
|
34
34
|
| 'uniqueField'
|
|
35
35
|
| 'rowAttributes'
|
|
36
36
|
| 'isFirstColumnSticky'
|
|
37
|
-
| 'isExpandableRowComponentInitiallyOpen'
|
|
38
37
|
| 'expandableRowComponent'
|
|
39
38
|
| 'onRowClick'
|
|
40
39
|
| 'onRowHover'
|
|
@@ -63,6 +62,8 @@ export interface IFlexibleTableProps<
|
|
|
63
62
|
nothingFoundContent?: ReactNode;
|
|
64
63
|
/** @default true */
|
|
65
64
|
shouldRenderHeader?: boolean;
|
|
65
|
+
/** @default false */
|
|
66
|
+
isExpandableRowComponentInitiallyOpen?: boolean | ((row: Row, index: number) => boolean);
|
|
66
67
|
}
|
|
67
68
|
|
|
68
69
|
export function FlexibleTable<
|
|
@@ -89,6 +90,7 @@ export function FlexibleTable<
|
|
|
89
90
|
tweakStyles,
|
|
90
91
|
shouldRenderHeader = true,
|
|
91
92
|
onHeadClick,
|
|
93
|
+
isExpandableRowComponentInitiallyOpen: isRowInitiallyOpen,
|
|
92
94
|
...restProps
|
|
93
95
|
}: IFlexibleTableProps<Row, HeaderContent, UniqueField>): JSX.Element {
|
|
94
96
|
const classes = useStyles({ theme: tweakStyles });
|
|
@@ -106,11 +108,12 @@ export function FlexibleTable<
|
|
|
106
108
|
|
|
107
109
|
const hasInfiniteScroll = isNotEmpty(infinityScrollConfig);
|
|
108
110
|
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
>
|
|
111
|
+
const getTableRowProps = (
|
|
112
|
+
item: Row,
|
|
113
|
+
index: number,
|
|
114
|
+
): IFlexibleTableRowProps<Row, HeaderContent, UniqueField> => ({
|
|
113
115
|
...restProps,
|
|
116
|
+
item,
|
|
114
117
|
renderMode,
|
|
115
118
|
config,
|
|
116
119
|
columns,
|
|
@@ -119,7 +122,8 @@ export function FlexibleTable<
|
|
|
119
122
|
isFirstColumnSticky,
|
|
120
123
|
isFocusable: isRowFocusable,
|
|
121
124
|
tweakStyles: tweakTableRowStyles,
|
|
122
|
-
|
|
125
|
+
isExpandableRowComponentInitiallyOpen: applyAction(isRowInitiallyOpen, item, index),
|
|
126
|
+
});
|
|
123
127
|
|
|
124
128
|
const getDataScrollAttributeSetter = useCallback(
|
|
125
129
|
(key: string, setter: (el: HTMLDivElement) => boolean) => (el?: HTMLDivElement) => {
|
|
@@ -268,9 +272,7 @@ export function FlexibleTable<
|
|
|
268
272
|
)}
|
|
269
273
|
<Table.Body className={classes.body}>
|
|
270
274
|
{isLoading ? (
|
|
271
|
-
indexMap(6, (i) => (
|
|
272
|
-
<FlexibleTableRow {...tableRowProps} key={i} item={{} as Row} index={i} />
|
|
273
|
-
))
|
|
275
|
+
indexMap(6, (i) => <FlexibleTableRow {...getTableRowProps({} as Row, i)} key={i} />)
|
|
274
276
|
) : (
|
|
275
277
|
<>
|
|
276
278
|
{shouldShowNothingFound && (
|
|
@@ -283,11 +285,9 @@ export function FlexibleTable<
|
|
|
283
285
|
|
|
284
286
|
{content.map((item, i) => (
|
|
285
287
|
<FlexibleTableRow
|
|
286
|
-
{...
|
|
288
|
+
{...getTableRowProps(item, i)}
|
|
287
289
|
isActive={activeRowsSet.has(i)}
|
|
288
290
|
key={isNotEmpty(uniqueField) ? item[uniqueField] : i}
|
|
289
|
-
item={item}
|
|
290
|
-
index={i}
|
|
291
291
|
/>
|
|
292
292
|
))}
|
|
293
293
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode, useState, memo, MouseEvent, RefCallback } from 'react';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import {
|
|
3
|
+
import { isEmpty, isNotEmpty } from '@true-engineering/true-react-platform-helpers';
|
|
4
4
|
import { addDataAttributes } from '../../../../helpers';
|
|
5
5
|
import { useTweakStyles } from '../../../../hooks';
|
|
6
6
|
import { IDataAttributes, ITweakStylesProps } from '../../../../types';
|
|
@@ -21,7 +21,6 @@ export interface IFlexibleTableRowProps<
|
|
|
21
21
|
UniqueField extends keyof Row,
|
|
22
22
|
> extends ITweakStylesProps<IFlexibleTableRowStyles> {
|
|
23
23
|
item: Row;
|
|
24
|
-
index: number;
|
|
25
24
|
uniqueField?: UniqueField;
|
|
26
25
|
renderMode: IFlexibleTableRenderMode;
|
|
27
26
|
/** @default false */
|
|
@@ -37,7 +36,7 @@ export interface IFlexibleTableRowProps<
|
|
|
37
36
|
columns: Array<keyof Row & string>;
|
|
38
37
|
rowAttributes?: Array<keyof Row>;
|
|
39
38
|
/** @default false */
|
|
40
|
-
isExpandableRowComponentInitiallyOpen?: boolean
|
|
39
|
+
isExpandableRowComponentInitiallyOpen?: boolean;
|
|
41
40
|
rowRef?: RefCallback<HTMLTableRowElement>;
|
|
42
41
|
/** Возвращает React-элемент, который отрисуется под строкой при нажатии на неё */
|
|
43
42
|
expandableRowComponent?: (item: Row, isOpen: boolean, close: () => void) => ReactNode;
|
|
@@ -51,7 +50,6 @@ function FlexibleTableRowInner<
|
|
|
51
50
|
UniqueField extends keyof Row,
|
|
52
51
|
>({
|
|
53
52
|
item,
|
|
54
|
-
index,
|
|
55
53
|
config,
|
|
56
54
|
columns,
|
|
57
55
|
uniqueField,
|
|
@@ -78,7 +76,7 @@ function FlexibleTableRowInner<
|
|
|
78
76
|
|
|
79
77
|
const [isFocused, setFocused] = useState(false);
|
|
80
78
|
const [nestedComponent, setNestedComponent] = useState<INestedComponent>(() => ({
|
|
81
|
-
isOpen:
|
|
79
|
+
isOpen: isExpandableRowComponentInitiallyOpen,
|
|
82
80
|
}));
|
|
83
81
|
|
|
84
82
|
const isEditable = !isLoading && (isNotEmpty(onRowClick) || isNotEmpty(onRowHover));
|
package/src/hooks/index.ts
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { isNotEmpty, mergeStyles } from '@true-engineering/true-react-platform-helpers';
|
|
3
|
+
|
|
4
|
+
export const useMerge = <T>(one?: T, two?: T): T | undefined =>
|
|
5
|
+
useMemo(
|
|
6
|
+
() => (isNotEmpty(one) && isNotEmpty(two) ? mergeStyles(one, two) : one ?? two),
|
|
7
|
+
[one, two],
|
|
8
|
+
);
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { useMemo } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { isObject } from '@true-engineering/true-react-platform-helpers';
|
|
3
|
+
import type { IMixedStyles } from '../theme';
|
|
4
|
+
|
|
5
|
+
export const mixStyles = <T>(...tweakStyles: Array<IMixedStyles<T>>): Array<NonNullable<T>> =>
|
|
6
|
+
tweakStyles.flat().filter(isObject) as Array<NonNullable<T>>;
|
|
3
7
|
|
|
4
8
|
export const useMixedStyles = <StyleSheet>(
|
|
5
|
-
baseStyles?: StyleSheet
|
|
6
|
-
tweakStyles?: StyleSheet
|
|
7
|
-
): StyleSheet
|
|
8
|
-
useMemo(
|
|
9
|
-
() =>
|
|
10
|
-
isNotEmpty(baseStyles) && isNotEmpty(tweakStyles)
|
|
11
|
-
? mergeStyles(baseStyles, tweakStyles)
|
|
12
|
-
: baseStyles ?? tweakStyles,
|
|
13
|
-
[baseStyles, tweakStyles],
|
|
14
|
-
);
|
|
9
|
+
baseStyles?: IMixedStyles<StyleSheet>,
|
|
10
|
+
tweakStyles?: IMixedStyles<StyleSheet>,
|
|
11
|
+
): Array<NonNullable<StyleSheet>> =>
|
|
12
|
+
useMemo(() => mixStyles(baseStyles, tweakStyles), [baseStyles, tweakStyles]);
|