@etsoo/react 1.5.75 → 1.5.78
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/lib/app/CommonApp.d.ts +2 -2
- package/lib/app/Labels.d.ts +1 -1
- package/lib/app/ServiceApp.d.ts +2 -2
- package/lib/components/GridColumn.d.ts +10 -10
- package/lib/components/GridLoader.d.ts +7 -8
- package/lib/components/ScrollerGrid.d.ts +7 -7
- package/lib/components/ScrollerList.d.ts +2 -2
- package/lib/mu/AutocompleteExtendedProps.d.ts +9 -7
- package/lib/mu/ComboBox.d.ts +10 -8
- package/lib/mu/ComboBox.js +6 -6
- package/lib/mu/DataGridEx.d.ts +6 -5
- package/lib/mu/DataGridRenderers.d.ts +1 -1
- package/lib/mu/DnDList.d.ts +2 -2
- package/lib/mu/ListMoreDisplay.d.ts +2 -2
- package/lib/mu/MUGlobal.d.ts +5 -5
- package/lib/mu/OptionGroup.d.ts +17 -14
- package/lib/mu/ResponsibleContainer.d.ts +5 -5
- package/lib/mu/ScrollerListEx.d.ts +11 -9
- package/lib/mu/ScrollerListEx.js +1 -1
- package/lib/mu/SearchOptionGroup.d.ts +1 -2
- package/lib/mu/SelectBool.d.ts +2 -2
- package/lib/mu/SelectBool.js +1 -1
- package/lib/mu/SelectEx.d.ts +16 -12
- package/lib/mu/SelectEx.js +2 -2
- package/lib/mu/TableEx.d.ts +10 -7
- package/lib/mu/TableEx.js +1 -2
- package/lib/mu/Tiplist.d.ts +4 -5
- package/lib/mu/Tiplist.js +4 -6
- package/lib/mu/pages/CommonPageProps.d.ts +1 -1
- package/lib/mu/pages/DataGridPage.d.ts +1 -1
- package/lib/mu/pages/DataGridPageProps.d.ts +2 -2
- package/lib/mu/pages/FixedListPage.d.ts +1 -1
- package/lib/mu/pages/ListPage.d.ts +1 -1
- package/lib/mu/pages/ListPageProps.d.ts +1 -2
- package/lib/mu/pages/ResponsivePage.d.ts +1 -1
- package/lib/mu/pages/ResponsivePageProps.d.ts +2 -2
- package/lib/mu/pages/SearchPageProps.d.ts +2 -2
- package/lib/mu/pages/TablePage.d.ts +1 -1
- package/lib/mu/pages/TablePageProps.d.ts +1 -2
- package/lib/mu/pages/ViewPage.d.ts +5 -4
- package/lib/states/IState.d.ts +1 -1
- package/lib/uses/useCombinedRefs.d.ts +1 -1
- package/package.json +11 -11
- package/src/app/CommonApp.ts +2 -2
- package/src/app/Labels.ts +1 -1
- package/src/app/ServiceApp.ts +2 -2
- package/src/components/GridColumn.ts +10 -11
- package/src/components/GridLoader.ts +7 -7
- package/src/components/ScrollerGrid.tsx +66 -59
- package/src/components/ScrollerList.tsx +2 -4
- package/src/mu/AutocompleteExtendedProps.ts +15 -12
- package/src/mu/ComboBox.tsx +25 -21
- package/src/mu/DataGridEx.tsx +19 -18
- package/src/mu/DataGridRenderers.tsx +1 -1
- package/src/mu/DnDList.tsx +2 -2
- package/src/mu/ListMoreDisplay.tsx +2 -2
- package/src/mu/MUGlobal.ts +5 -5
- package/src/mu/OptionGroup.tsx +29 -27
- package/src/mu/ResponsibleContainer.tsx +18 -21
- package/src/mu/ScrollerListEx.tsx +24 -20
- package/src/mu/SearchOptionGroup.tsx +2 -3
- package/src/mu/SelectBool.tsx +13 -5
- package/src/mu/SelectEx.tsx +27 -20
- package/src/mu/TableEx.tsx +61 -59
- package/src/mu/Tiplist.tsx +20 -17
- package/src/mu/pages/CommonPageProps.ts +1 -1
- package/src/mu/pages/DataGridPage.tsx +14 -10
- package/src/mu/pages/DataGridPageProps.ts +16 -13
- package/src/mu/pages/FixedListPage.tsx +1 -1
- package/src/mu/pages/ListPage.tsx +1 -1
- package/src/mu/pages/ListPageProps.ts +4 -3
- package/src/mu/pages/ResponsivePage.tsx +5 -4
- package/src/mu/pages/ResponsivePageProps.ts +9 -6
- package/src/mu/pages/SearchPageProps.ts +5 -3
- package/src/mu/pages/TablePage.tsx +1 -1
- package/src/mu/pages/TablePageProps.ts +4 -3
- package/src/mu/pages/ViewPage.tsx +8 -6
- package/src/states/IState.ts +1 -1
- package/src/states/UserState.ts +1 -1
- package/src/uses/useCombinedRefs.ts +3 -3
|
@@ -30,18 +30,14 @@ import { SearchBar } from './SearchBar';
|
|
|
30
30
|
/**
|
|
31
31
|
* ResponsibleContainer props
|
|
32
32
|
*/
|
|
33
|
-
export
|
|
34
|
-
T extends
|
|
35
|
-
F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
| 'mRef'
|
|
42
|
-
| 'onScroll'
|
|
43
|
-
| 'onItemsRendered'
|
|
44
|
-
> {
|
|
33
|
+
export type ResponsibleContainerProps<
|
|
34
|
+
T extends object,
|
|
35
|
+
F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate,
|
|
36
|
+
D extends DataTypes.Keys<T> = DataTypes.Keys<T>
|
|
37
|
+
> = Omit<
|
|
38
|
+
DataGridExProps<T, D>,
|
|
39
|
+
'height' | 'itemKey' | 'loadData' | 'mRef' | 'onScroll' | 'onItemsRendered'
|
|
40
|
+
> & {
|
|
45
41
|
/**
|
|
46
42
|
* Height will be deducted
|
|
47
43
|
* @param height Current calcuated height
|
|
@@ -57,7 +53,7 @@ export interface ResponsibleContainerProps<
|
|
|
57
53
|
* Container box SX (dataGrid determines the case)
|
|
58
54
|
*/
|
|
59
55
|
containerBoxSx?: (
|
|
60
|
-
paddings:
|
|
56
|
+
paddings: Record<string, string | number>,
|
|
61
57
|
hasFields: boolean,
|
|
62
58
|
dataGrid?: boolean
|
|
63
59
|
) => SxProps<Theme>;
|
|
@@ -119,7 +115,7 @@ export interface ResponsibleContainerProps<
|
|
|
119
115
|
/**
|
|
120
116
|
* Paddings
|
|
121
117
|
*/
|
|
122
|
-
paddings?:
|
|
118
|
+
paddings?: Record<string, string | number>;
|
|
123
119
|
|
|
124
120
|
/**
|
|
125
121
|
* Pull to refresh data
|
|
@@ -135,7 +131,7 @@ export interface ResponsibleContainerProps<
|
|
|
135
131
|
* Size ready to read miliseconds span
|
|
136
132
|
*/
|
|
137
133
|
sizeReadyMiliseconds?: number;
|
|
138
|
-
}
|
|
134
|
+
};
|
|
139
135
|
|
|
140
136
|
interface LocalRefs {
|
|
141
137
|
rect?: DOMRect;
|
|
@@ -144,7 +140,7 @@ interface LocalRefs {
|
|
|
144
140
|
}
|
|
145
141
|
|
|
146
142
|
function defaultContainerBoxSx(
|
|
147
|
-
paddings:
|
|
143
|
+
paddings: object,
|
|
148
144
|
hasField: boolean,
|
|
149
145
|
_dataGrid?: boolean
|
|
150
146
|
): SxProps<Theme> {
|
|
@@ -162,9 +158,10 @@ function defaultContainerBoxSx(
|
|
|
162
158
|
* @returns Layout
|
|
163
159
|
*/
|
|
164
160
|
export function ResponsibleContainer<
|
|
165
|
-
T extends
|
|
166
|
-
F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate
|
|
167
|
-
>
|
|
161
|
+
T extends object,
|
|
162
|
+
F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate,
|
|
163
|
+
D extends DataTypes.Keys<T> = DataTypes.Keys<T>
|
|
164
|
+
>(props: ResponsibleContainerProps<T, F, D>) {
|
|
168
165
|
// Destruct
|
|
169
166
|
const {
|
|
170
167
|
adjustHeight,
|
|
@@ -286,7 +283,7 @@ export function ResponsibleContainer<
|
|
|
286
283
|
|
|
287
284
|
return [
|
|
288
285
|
<Box className="DataGridBox">
|
|
289
|
-
<DataGridEx<T>
|
|
286
|
+
<DataGridEx<T, D>
|
|
290
287
|
autoLoad={!hasFields}
|
|
291
288
|
height={heightLocal}
|
|
292
289
|
width={rect.width}
|
|
@@ -319,7 +316,7 @@ export function ResponsibleContainer<
|
|
|
319
316
|
|
|
320
317
|
return [
|
|
321
318
|
<Box className="ListBox" sx={{ height: heightLocal }}>
|
|
322
|
-
<ScrollerListEx<T>
|
|
319
|
+
<ScrollerListEx<T, D>
|
|
323
320
|
autoLoad={!hasFields}
|
|
324
321
|
height={heightLocal}
|
|
325
322
|
loadData={localLoadData}
|
|
@@ -47,7 +47,7 @@ const createGridStyle = (
|
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
// Default margin
|
|
50
|
-
const defaultMargin = (margin:
|
|
50
|
+
const defaultMargin = (margin: object, isNarrow?: boolean) => {
|
|
51
51
|
const half = MUGlobal.half(margin);
|
|
52
52
|
|
|
53
53
|
if (isNarrow == null) {
|
|
@@ -100,7 +100,7 @@ export interface ScrollerListExInnerItemRendererProps<T>
|
|
|
100
100
|
/**
|
|
101
101
|
* Default margins
|
|
102
102
|
*/
|
|
103
|
-
margins:
|
|
103
|
+
margins: object;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
/**
|
|
@@ -110,25 +110,22 @@ export interface ScrollerListExInnerItemRendererProps<T>
|
|
|
110
110
|
* 3. Dynamic calculation
|
|
111
111
|
*/
|
|
112
112
|
export type ScrollerListExItemSize =
|
|
113
|
-
| ((index: number) => [number, number] | [number, number,
|
|
113
|
+
| ((index: number) => [number, number] | [number, number, object])
|
|
114
114
|
| [number, number]
|
|
115
|
-
| [number,
|
|
115
|
+
| [number, object, boolean?];
|
|
116
116
|
|
|
117
117
|
/**
|
|
118
118
|
* Extended ScrollerList Props
|
|
119
119
|
*/
|
|
120
|
-
export
|
|
121
|
-
|
|
120
|
+
export type ScrollerListExProps<
|
|
121
|
+
T extends object,
|
|
122
|
+
D extends DataTypes.Keys<T> = DataTypes.Keys<T>
|
|
123
|
+
> = Omit<ScrollerListProps<T>, 'itemRenderer' | 'itemSize'> & {
|
|
122
124
|
/**
|
|
123
125
|
* Alternating colors for odd/even rows
|
|
124
126
|
*/
|
|
125
127
|
alternatingColors?: [string?, string?];
|
|
126
128
|
|
|
127
|
-
/**
|
|
128
|
-
* Id field
|
|
129
|
-
*/
|
|
130
|
-
idField?: string & keyof T;
|
|
131
|
-
|
|
132
129
|
/**
|
|
133
130
|
* Inner item renderer
|
|
134
131
|
*/
|
|
@@ -141,6 +138,12 @@ export interface ScrollerListExProps<T>
|
|
|
141
138
|
*/
|
|
142
139
|
itemRenderer?: (props: ListChildComponentProps<T>) => React.ReactElement;
|
|
143
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Id field
|
|
143
|
+
* Failed: D extends { id: DataTypes.IdType } ? { idField?: D } : { idField: D }
|
|
144
|
+
*/
|
|
145
|
+
idField?: D;
|
|
146
|
+
|
|
144
147
|
/**
|
|
145
148
|
* Item size, a function indicates its a variable size list
|
|
146
149
|
*/
|
|
@@ -165,7 +168,7 @@ export interface ScrollerListExProps<T>
|
|
|
165
168
|
* Selected color
|
|
166
169
|
*/
|
|
167
170
|
selectedColor?: string;
|
|
168
|
-
}
|
|
171
|
+
};
|
|
169
172
|
|
|
170
173
|
interface defaultItemRendererProps<T> extends ListChildComponentProps<T> {
|
|
171
174
|
/**
|
|
@@ -203,7 +206,7 @@ interface defaultItemRendererProps<T> extends ListChildComponentProps<T> {
|
|
|
203
206
|
/**
|
|
204
207
|
* Default margins
|
|
205
208
|
*/
|
|
206
|
-
margins:
|
|
209
|
+
margins: object;
|
|
207
210
|
|
|
208
211
|
/**
|
|
209
212
|
* Item selected
|
|
@@ -260,9 +263,10 @@ function defaultItemRenderer<T>({
|
|
|
260
263
|
* @param props Props
|
|
261
264
|
* @returns Component
|
|
262
265
|
*/
|
|
263
|
-
export function ScrollerListEx<
|
|
264
|
-
|
|
265
|
-
|
|
266
|
+
export function ScrollerListEx<
|
|
267
|
+
T extends object,
|
|
268
|
+
D extends DataTypes.Keys<T> = DataTypes.Keys<T>
|
|
269
|
+
>(props: ScrollerListExProps<T, D>) {
|
|
266
270
|
// Selected item ref
|
|
267
271
|
const selectedItem = React.useRef<[HTMLDivElement, T]>();
|
|
268
272
|
|
|
@@ -295,11 +299,11 @@ export function ScrollerListEx<T extends Record<string, unknown>>(
|
|
|
295
299
|
const {
|
|
296
300
|
alternatingColors = [undefined, undefined],
|
|
297
301
|
className,
|
|
298
|
-
idField = 'id',
|
|
302
|
+
idField = 'id' as D,
|
|
299
303
|
innerItemRenderer,
|
|
300
304
|
itemSize,
|
|
301
305
|
itemKey = (index: number, data: T) =>
|
|
302
|
-
DataTypes.
|
|
306
|
+
DataTypes.getIdValue1(data, idField) ?? index,
|
|
303
307
|
itemRenderer = (itemProps) => {
|
|
304
308
|
const [itemHeight, space, margins] = calculateItemSize(
|
|
305
309
|
itemProps.index
|
|
@@ -328,7 +332,7 @@ export function ScrollerListEx<T extends Record<string, unknown>>(
|
|
|
328
332
|
|
|
329
333
|
// Cache calculation
|
|
330
334
|
const itemSizeResult = React.useMemo(():
|
|
331
|
-
| [number, number,
|
|
335
|
+
| [number, number, object]
|
|
332
336
|
| undefined => {
|
|
333
337
|
if (typeof itemSize === 'function') return undefined;
|
|
334
338
|
const [size, spaces, isNarrow] = itemSize;
|
|
@@ -347,7 +351,7 @@ export function ScrollerListEx<T extends Record<string, unknown>>(
|
|
|
347
351
|
}, [itemSize]);
|
|
348
352
|
|
|
349
353
|
// Calculate size
|
|
350
|
-
const calculateItemSize = (index: number): [number, number,
|
|
354
|
+
const calculateItemSize = (index: number): [number, number, object] => {
|
|
351
355
|
// Callback function
|
|
352
356
|
if (typeof itemSize === 'function') {
|
|
353
357
|
const result = itemSize(index);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { IdLabelDto } from '@etsoo/appscript';
|
|
2
1
|
import { DataTypes } from '@etsoo/shared';
|
|
3
2
|
import React from 'react';
|
|
4
3
|
import { MUGlobal } from './MUGlobal';
|
|
@@ -10,8 +9,8 @@ import { OptionGroup, OptionGroupProps } from './OptionGroup';
|
|
|
10
9
|
* @returns Component
|
|
11
10
|
*/
|
|
12
11
|
export function SearchOptionGroup<
|
|
13
|
-
T extends
|
|
14
|
-
D extends DataTypes.
|
|
12
|
+
T extends object = DataTypes.IdLabelItem,
|
|
13
|
+
D extends DataTypes.Keys<T> = DataTypes.Keys<T>
|
|
15
14
|
>(props: OptionGroupProps<T, D>) {
|
|
16
15
|
// Destruct
|
|
17
16
|
const {
|
package/src/mu/SelectBool.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Utils } from '@etsoo/shared';
|
|
1
|
+
import { DataTypes, Utils } from '@etsoo/shared';
|
|
3
2
|
import React from 'react';
|
|
4
3
|
import { globalApp } from '..';
|
|
5
4
|
import { SelectEx, SelectExProps } from './SelectEx';
|
|
@@ -8,7 +7,10 @@ import { SelectEx, SelectExProps } from './SelectEx';
|
|
|
8
7
|
* SelectBool props
|
|
9
8
|
*/
|
|
10
9
|
export interface SelectBoolProps
|
|
11
|
-
extends Omit<
|
|
10
|
+
extends Omit<
|
|
11
|
+
SelectExProps<DataTypes.IdLabelItem<string>>,
|
|
12
|
+
'options' | 'loadData'
|
|
13
|
+
> {}
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* SelectBool (yes/no)
|
|
@@ -20,7 +22,7 @@ export function SelectBool(props: SelectBoolProps) {
|
|
|
20
22
|
const { search = true, autoAddBlankItem = search, ...rest } = props;
|
|
21
23
|
|
|
22
24
|
// Options
|
|
23
|
-
const options:
|
|
25
|
+
const options: DataTypes.IdLabelItem<string>[] = [
|
|
24
26
|
{ id: 'false', label: globalApp.get('no')! },
|
|
25
27
|
{ id: 'true', label: globalApp.get('yes')! }
|
|
26
28
|
];
|
|
@@ -28,5 +30,11 @@ export function SelectBool(props: SelectBoolProps) {
|
|
|
28
30
|
if (autoAddBlankItem) Utils.addBlankItem(options);
|
|
29
31
|
|
|
30
32
|
// Layout
|
|
31
|
-
return
|
|
33
|
+
return (
|
|
34
|
+
<SelectEx<DataTypes.IdLabelItem<string>>
|
|
35
|
+
options={options}
|
|
36
|
+
search={search}
|
|
37
|
+
{...rest}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
32
40
|
}
|
package/src/mu/SelectEx.tsx
CHANGED
|
@@ -11,36 +11,27 @@ import {
|
|
|
11
11
|
} from '@mui/material';
|
|
12
12
|
import React from 'react';
|
|
13
13
|
import { MUGlobal } from './MUGlobal';
|
|
14
|
-
import { IdLabelDto } from '@etsoo/appscript';
|
|
15
14
|
import { ListItemRightIcon } from './ListItemRightIcon';
|
|
16
|
-
import { Utils } from '@etsoo/shared';
|
|
15
|
+
import { DataTypes, Utils } from '@etsoo/shared';
|
|
17
16
|
import { ReactUtils } from '../app/ReactUtils';
|
|
18
17
|
|
|
19
18
|
/**
|
|
20
19
|
* Extended select component props
|
|
21
20
|
*/
|
|
22
|
-
export
|
|
23
|
-
extends
|
|
21
|
+
export type SelectExProps<
|
|
22
|
+
T extends object,
|
|
23
|
+
D extends DataTypes.Keys<T> = DataTypes.Keys<T>
|
|
24
|
+
> = Omit<SelectProps, 'labelId' | 'input' | 'native'> & {
|
|
24
25
|
/**
|
|
25
26
|
* Auto add blank item
|
|
26
27
|
*/
|
|
27
28
|
autoAddBlankItem?: boolean;
|
|
28
29
|
|
|
29
|
-
/**
|
|
30
|
-
* Id field, default is id
|
|
31
|
-
*/
|
|
32
|
-
idField?: string & keyof T;
|
|
33
|
-
|
|
34
30
|
/**
|
|
35
31
|
* Item icon renderer
|
|
36
32
|
*/
|
|
37
33
|
itemIconRenderer?: (id: unknown) => React.ReactNode;
|
|
38
34
|
|
|
39
|
-
/**
|
|
40
|
-
* Label field, default is label
|
|
41
|
-
*/
|
|
42
|
-
labelField?: ((option: T) => string) | (string & keyof T);
|
|
43
|
-
|
|
44
35
|
/**
|
|
45
36
|
* Load data callback
|
|
46
37
|
*/
|
|
@@ -65,21 +56,37 @@ export interface SelectExProps<T extends {}>
|
|
|
65
56
|
* Is search case?
|
|
66
57
|
*/
|
|
67
58
|
search?: boolean;
|
|
68
|
-
}
|
|
59
|
+
} & (T extends { id: DataTypes.IdType }
|
|
60
|
+
? {
|
|
61
|
+
idField?: D;
|
|
62
|
+
}
|
|
63
|
+
: {
|
|
64
|
+
idField: D;
|
|
65
|
+
}) &
|
|
66
|
+
(T extends { label: string }
|
|
67
|
+
? {
|
|
68
|
+
labelField?: ((option: T) => string) | D;
|
|
69
|
+
}
|
|
70
|
+
: {
|
|
71
|
+
labelField: ((option: T) => string) | D;
|
|
72
|
+
});
|
|
69
73
|
|
|
70
74
|
/**
|
|
71
75
|
* Extended select component
|
|
72
76
|
* @param props Props
|
|
73
77
|
* @returns Component
|
|
74
78
|
*/
|
|
75
|
-
export function SelectEx<
|
|
79
|
+
export function SelectEx<
|
|
80
|
+
T extends object = DataTypes.IdLabelItem,
|
|
81
|
+
D extends DataTypes.Keys<T> = DataTypes.Keys<T>
|
|
82
|
+
>(props: SelectExProps<T, D>) {
|
|
76
83
|
// Destruct
|
|
77
84
|
const {
|
|
78
85
|
defaultValue,
|
|
79
|
-
idField = 'id',
|
|
86
|
+
idField = 'id' as D,
|
|
80
87
|
itemIconRenderer,
|
|
81
88
|
label,
|
|
82
|
-
labelField = 'label',
|
|
89
|
+
labelField = 'label' as D,
|
|
83
90
|
loadData,
|
|
84
91
|
onItemClick,
|
|
85
92
|
onLoadData,
|
|
@@ -153,14 +160,14 @@ export function SelectEx<T extends {} = IdLabelDto>(props: SelectExProps<T>) {
|
|
|
153
160
|
|
|
154
161
|
// Get option id
|
|
155
162
|
const getId = (option: T) => {
|
|
156
|
-
return
|
|
163
|
+
return option[idField] as unknown as React.Key;
|
|
157
164
|
};
|
|
158
165
|
|
|
159
166
|
// Get option label
|
|
160
167
|
const getLabel = (option: T) => {
|
|
161
168
|
return typeof labelField === 'function'
|
|
162
169
|
? labelField(option)
|
|
163
|
-
:
|
|
170
|
+
: new String(option[labelField]);
|
|
164
171
|
};
|
|
165
172
|
|
|
166
173
|
// Refs
|
package/src/mu/TableEx.tsx
CHANGED
|
@@ -47,68 +47,70 @@ export interface TableExMethodRef extends GridMethodRef {
|
|
|
47
47
|
/**
|
|
48
48
|
* Extended table props
|
|
49
49
|
*/
|
|
50
|
-
export
|
|
51
|
-
extends
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
}
|
|
50
|
+
export type TableExProps<
|
|
51
|
+
T extends object,
|
|
52
|
+
D extends DataTypes.Keys<T> = DataTypes.Keys<T>
|
|
53
|
+
> = TableProps &
|
|
54
|
+
GridLoader<T> & {
|
|
55
|
+
/**
|
|
56
|
+
* Alternating colors for odd/even rows
|
|
57
|
+
*/
|
|
58
|
+
alternatingColors?: [string?, string?];
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Columns
|
|
62
|
+
*/
|
|
63
|
+
columns: GridColumn<T>[];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Header cells background color and font color
|
|
67
|
+
*/
|
|
68
|
+
headerColors?: [string?, string?];
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Max height
|
|
72
|
+
*/
|
|
73
|
+
maxHeight?: number;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Methods
|
|
77
|
+
*/
|
|
78
|
+
mRef?: React.Ref<TableExMethodRef>;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* On items select change
|
|
82
|
+
*/
|
|
83
|
+
onSelectChange?: (selectedItems: T[]) => void;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Row height
|
|
87
|
+
*/
|
|
88
|
+
rowHeight?: number;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Header and bottom height
|
|
92
|
+
*/
|
|
93
|
+
otherHeight?: number;
|
|
94
|
+
} & (T extends { id: DataTypes.IdType }
|
|
95
|
+
? {
|
|
96
|
+
idField?: D;
|
|
97
|
+
}
|
|
98
|
+
: {
|
|
99
|
+
idField: D;
|
|
100
|
+
});
|
|
98
101
|
|
|
99
102
|
/**
|
|
100
103
|
* Extended Table
|
|
101
104
|
* @param props Props
|
|
102
105
|
* @returns Component
|
|
103
106
|
*/
|
|
104
|
-
export function TableEx<
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
export function TableEx<
|
|
108
|
+
T extends object,
|
|
109
|
+
D extends DataTypes.Keys<T> = DataTypes.Keys<T>
|
|
110
|
+
>(props: TableExProps<T, D>) {
|
|
107
111
|
// Theme
|
|
108
112
|
const theme = useTheme();
|
|
109
113
|
|
|
110
|
-
type keyType = string & keyof T;
|
|
111
|
-
|
|
112
114
|
// Destruct
|
|
113
115
|
const {
|
|
114
116
|
alternatingColors = [theme.palette.action.hover, undefined],
|
|
@@ -116,7 +118,7 @@ export function TableEx<T extends Record<string, unknown>>(
|
|
|
116
118
|
columns,
|
|
117
119
|
defaultOrderBy,
|
|
118
120
|
headerColors = [undefined, undefined],
|
|
119
|
-
idField = 'id' as
|
|
121
|
+
idField = 'id' as D,
|
|
120
122
|
loadBatchSize,
|
|
121
123
|
loadData,
|
|
122
124
|
maxHeight,
|
|
@@ -451,7 +453,10 @@ export function TableEx<T extends Record<string, unknown>>(
|
|
|
451
453
|
: false;
|
|
452
454
|
|
|
453
455
|
return (
|
|
454
|
-
<TableRow
|
|
456
|
+
<TableRow
|
|
457
|
+
key={rowId as unknown as React.Key}
|
|
458
|
+
selected={isItemSelected}
|
|
459
|
+
>
|
|
455
460
|
{selectable && (
|
|
456
461
|
<TableCell padding="checkbox">
|
|
457
462
|
{row && (
|
|
@@ -522,10 +527,7 @@ export function TableEx<T extends Record<string, unknown>>(
|
|
|
522
527
|
|
|
523
528
|
return (
|
|
524
529
|
<TableCell
|
|
525
|
-
key={
|
|
526
|
-
rowId.toString() +
|
|
527
|
-
columnIndex
|
|
528
|
-
}
|
|
530
|
+
key={`${rowId}${columnIndex}`}
|
|
529
531
|
{...cellProps}
|
|
530
532
|
>
|
|
531
533
|
{child}
|
package/src/mu/Tiplist.tsx
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { IdLabelDto } from '@etsoo/appscript';
|
|
2
1
|
import { DataTypes } from '@etsoo/shared';
|
|
3
2
|
import { Autocomplete, AutocompleteRenderInputParams } from '@mui/material';
|
|
4
3
|
import React from 'react';
|
|
@@ -11,19 +10,21 @@ import { SearchField } from './SearchField';
|
|
|
11
10
|
/**
|
|
12
11
|
* Tiplist props
|
|
13
12
|
*/
|
|
14
|
-
export
|
|
15
|
-
|
|
13
|
+
export type TiplistProps<T extends object, D extends DataTypes.Keys<T>> = Omit<
|
|
14
|
+
AutocompleteExtendedProps<T, D>,
|
|
15
|
+
'open'
|
|
16
|
+
> & {
|
|
16
17
|
/**
|
|
17
18
|
* Load data callback
|
|
18
19
|
*/
|
|
19
20
|
loadData: (
|
|
20
21
|
keyword?: string,
|
|
21
|
-
id?:
|
|
22
|
+
id?: T[D]
|
|
22
23
|
) => PromiseLike<T[] | null | undefined>;
|
|
23
|
-
}
|
|
24
|
+
};
|
|
24
25
|
|
|
25
26
|
// Multiple states
|
|
26
|
-
interface States<T extends
|
|
27
|
+
interface States<T extends object> {
|
|
27
28
|
open: boolean;
|
|
28
29
|
options: T[];
|
|
29
30
|
value?: T | null;
|
|
@@ -35,11 +36,14 @@ interface States<T extends {}> {
|
|
|
35
36
|
* @param props Props
|
|
36
37
|
* @returns Component
|
|
37
38
|
*/
|
|
38
|
-
export function Tiplist<
|
|
39
|
+
export function Tiplist<
|
|
40
|
+
T extends object = DataTypes.IdLabelItem,
|
|
41
|
+
D extends DataTypes.Keys<T> = DataTypes.Keys<T>
|
|
42
|
+
>(props: TiplistProps<T, D>) {
|
|
39
43
|
// Destruct
|
|
40
44
|
const {
|
|
41
45
|
search = false,
|
|
42
|
-
idField = 'id',
|
|
46
|
+
idField = 'id' as D,
|
|
43
47
|
idValue,
|
|
44
48
|
inputAutoComplete = 'off',
|
|
45
49
|
inputError,
|
|
@@ -65,11 +69,10 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
|
|
|
65
69
|
|
|
66
70
|
// Local value
|
|
67
71
|
let localValue = value ?? defaultValue;
|
|
68
|
-
if (localValue === undefined) localValue = null;
|
|
69
72
|
|
|
70
73
|
// One time calculation for input's default value (uncontrolled)
|
|
71
74
|
const localIdValue =
|
|
72
|
-
idValue ??
|
|
75
|
+
idValue ?? DataTypes.getValue(localValue, idField as any);
|
|
73
76
|
|
|
74
77
|
// Changable states
|
|
75
78
|
const [states, stateUpdate] = React.useReducer(
|
|
@@ -86,7 +89,7 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
|
|
|
86
89
|
|
|
87
90
|
// Input value
|
|
88
91
|
const inputValue = React.useMemo(
|
|
89
|
-
() => states.value &&
|
|
92
|
+
() => states.value && states.value[idField],
|
|
90
93
|
[states.value]
|
|
91
94
|
);
|
|
92
95
|
|
|
@@ -130,7 +133,7 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
|
|
|
130
133
|
};
|
|
131
134
|
|
|
132
135
|
// Directly load data
|
|
133
|
-
const loadDataDirect = (keyword?: string, id?:
|
|
136
|
+
const loadDataDirect = (keyword?: string, id?: T[D]) => {
|
|
134
137
|
// Reset options
|
|
135
138
|
// setOptions([]);
|
|
136
139
|
|
|
@@ -181,7 +184,7 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
|
|
|
181
184
|
}
|
|
182
185
|
};
|
|
183
186
|
|
|
184
|
-
if (localIdValue != null && localIdValue !== '') {
|
|
187
|
+
if (localIdValue != null && (localIdValue as any) !== '') {
|
|
185
188
|
if (state.idLoaded) {
|
|
186
189
|
// Set default
|
|
187
190
|
if (!state.idSet && states.options.length == 1) {
|
|
@@ -211,12 +214,12 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
|
|
|
211
214
|
type="text"
|
|
212
215
|
style={{ display: 'none' }}
|
|
213
216
|
name={name}
|
|
214
|
-
value={inputValue ?? ''}
|
|
217
|
+
value={`${inputValue ?? ''}`}
|
|
215
218
|
readOnly
|
|
216
219
|
onChange={inputOnChange}
|
|
217
220
|
/>
|
|
218
221
|
{/* Previous input will reset first with "disableClearable = false", next input trigger change works */}
|
|
219
|
-
<Autocomplete
|
|
222
|
+
<Autocomplete<T, undefined, false, false>
|
|
220
223
|
filterOptions={(options, _state) => options}
|
|
221
224
|
value={states.value}
|
|
222
225
|
options={states.options}
|
|
@@ -250,7 +253,7 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
|
|
|
250
253
|
undefined,
|
|
251
254
|
states.value == null
|
|
252
255
|
? undefined
|
|
253
|
-
:
|
|
256
|
+
: states.value[idField]
|
|
254
257
|
);
|
|
255
258
|
}}
|
|
256
259
|
onClose={() => {
|
|
@@ -291,7 +294,7 @@ export function Tiplist<T extends {} = IdLabelDto>(props: TiplistProps<T>) {
|
|
|
291
294
|
/>
|
|
292
295
|
)
|
|
293
296
|
}
|
|
294
|
-
isOptionEqualToValue={(option:
|
|
297
|
+
isOptionEqualToValue={(option: T, value: T) =>
|
|
295
298
|
option[idField] === value[idField]
|
|
296
299
|
}
|
|
297
300
|
{...rest}
|