@jasperoosthoek/react-toolbox 0.5.5 → 0.5.7
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/LICENSE +1 -1
- package/change-log.md +7 -0
- package/dist/components/forms/FormFields.d.ts +1 -7
- package/dist/components/forms/FormModal.d.ts +41 -0
- package/dist/components/forms/FormModalProvider.d.ts +42 -0
- package/dist/components/tables/DataTable.d.ts +4 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/package.json +2 -2
- package/src/components/buttons/IconButtons.tsx +2 -2
- package/src/components/forms/FormFields.tsx +0 -4
- package/src/components/forms/{CreateEditModal.tsx → FormModal.tsx} +5 -4
- package/src/components/forms/{CreateEditModalProvider.tsx → FormModalProvider.tsx} +29 -21
- package/src/components/tables/DataTable.tsx +34 -13
- package/src/components/tables/DragAndDropList.tsx +0 -1
- package/src/index.ts +2 -2
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jasperoosthoek/react-toolbox",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
4
4
|
"author": "jasperoosthoek",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/jasperoosthoek/react-toolbox.git"
|
|
9
9
|
},
|
|
10
|
-
"description": "
|
|
10
|
+
"description": "Extensive library of React components that work together with react-bootstrap",
|
|
11
11
|
"files": [
|
|
12
12
|
"src/",
|
|
13
13
|
"dist/",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import { Button, ButtonProps as ReactBootstrapButtonProps,
|
|
1
|
+
import React, { useRef, ChangeEvent } from 'react';
|
|
2
|
+
import { Button, ButtonProps as ReactBootstrapButtonProps, Form } from 'react-bootstrap';
|
|
3
3
|
import {
|
|
4
4
|
AiFillCaretDown,
|
|
5
5
|
AiFillCaretUp,
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { ReactElement, ChangeEvent, KeyboardEvent } from 'react';
|
|
2
2
|
import { Form, FormControl, Badge, Dropdown, BadgeProps, FormControlProps, FormCheckProps } from 'react-bootstrap';
|
|
3
3
|
import { Variant} from 'react-bootstrap/types';
|
|
4
|
-
import PropTypes from 'prop-types';
|
|
5
4
|
import { useLocalization } from '../../localization/LocalizationContext';
|
|
6
5
|
import moment, { Moment } from 'moment';
|
|
7
6
|
|
|
@@ -264,9 +263,6 @@ export const FormSelect = ({
|
|
|
264
263
|
</Form.Group>
|
|
265
264
|
</>;
|
|
266
265
|
}
|
|
267
|
-
FormSelect.propTypes = {
|
|
268
|
-
onChange: PropTypes.func.isRequired,
|
|
269
|
-
}
|
|
270
266
|
|
|
271
267
|
export interface BadgeSelectionProps extends BadgeProps {
|
|
272
268
|
selected: boolean;
|
|
@@ -32,7 +32,7 @@ export type Validate = (state: any) => any
|
|
|
32
32
|
export type ModalTitle = ReactElement | string;
|
|
33
33
|
|
|
34
34
|
export type Width = 25 | 50 | 75 | 100;
|
|
35
|
-
export type
|
|
35
|
+
export type FormModalProps<
|
|
36
36
|
T extends FormFields,
|
|
37
37
|
K extends IncludeData<T>
|
|
38
38
|
> = {
|
|
@@ -49,7 +49,7 @@ export type CreateEditModalProps<
|
|
|
49
49
|
width?: Width;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
export const
|
|
52
|
+
export const FormModal = <
|
|
53
53
|
T extends FormFields,
|
|
54
54
|
K extends IncludeData<T>
|
|
55
55
|
>({
|
|
@@ -65,9 +65,10 @@ export const CreateEditModal = <
|
|
|
65
65
|
dialogClassName='',
|
|
66
66
|
width,
|
|
67
67
|
...restProps
|
|
68
|
-
}:
|
|
68
|
+
}: FormModalProps<T, K>) => {
|
|
69
|
+
|
|
69
70
|
if (Object.values(restProps).length !==0) {
|
|
70
|
-
console.error(`Unrecognised props given to
|
|
71
|
+
console.error(`Unrecognised props given to FormModal:`, restProps);
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
const getInitialFormData = () => ({
|
|
@@ -9,26 +9,28 @@ import {
|
|
|
9
9
|
Validate,
|
|
10
10
|
ModalTitle,
|
|
11
11
|
Width,
|
|
12
|
-
|
|
12
|
+
FormModal,
|
|
13
13
|
|
|
14
|
-
} from './
|
|
14
|
+
} from './FormModal';
|
|
15
15
|
import { FormValue } from './FormFields';
|
|
16
16
|
import { ButtonProps, CreateButton, EditButton } from '../buttons/IconButtons';
|
|
17
|
-
const out_of_context_error = 'The useError hook should only be used in a child of the CreateEditModalProvider component.';
|
|
18
17
|
|
|
19
18
|
export type ShowCreateModal = (show?: boolean) => void;
|
|
20
19
|
export type ShowEditModal<T, K> = (state: { [key in keyof T]: FormValue } & K) => void;
|
|
21
20
|
|
|
22
21
|
export type ShowCreateModalButton = ButtonProps;
|
|
23
22
|
export const ShowCreateModalButton = ({ onClick, ...props }: ButtonProps) => {
|
|
24
|
-
const { showCreateModal } =
|
|
23
|
+
const { showCreateModal, hasProvider } = useFormModal();
|
|
25
24
|
|
|
26
25
|
return (
|
|
27
26
|
<CreateButton
|
|
28
27
|
{...props}
|
|
29
|
-
onClick={(e) => {
|
|
28
|
+
onClick={(e) => {
|
|
29
|
+
// A onClick function was given to CreateButton
|
|
30
30
|
if (onClick) onClick(e);
|
|
31
|
-
|
|
31
|
+
// CreateButton is inside a CreateEditButtonProvider which can handle
|
|
32
|
+
// showCreateModal. Without the provider, showCreateModal will log an error
|
|
33
|
+
if (hasProvider) showCreateModal();
|
|
32
34
|
}}
|
|
33
35
|
/>
|
|
34
36
|
)
|
|
@@ -37,40 +39,45 @@ export interface ShowEditModalButtonProps<T, K> extends ButtonProps {
|
|
|
37
39
|
state: { [key in keyof T]: FormValue } & K;
|
|
38
40
|
}
|
|
39
41
|
export const ShowEditModalButton = ({ state, onClick, ... props }: ShowEditModalButtonProps<T, K>) => {
|
|
40
|
-
const { showEditModal } =
|
|
42
|
+
const { showEditModal, hasProvider } = useFormModal();
|
|
41
43
|
|
|
42
44
|
return (
|
|
43
45
|
<EditButton
|
|
44
46
|
{...props}
|
|
45
47
|
onClick={(e) => {
|
|
48
|
+
// A onClick function was given to CreateButton
|
|
46
49
|
if (onClick) onClick(e);
|
|
47
|
-
|
|
50
|
+
// CreateButton is inside a CreateEditButtonProvider which can handle
|
|
51
|
+
// showEditModal. Without the provider, showEditModal will log an error
|
|
52
|
+
if (hasProvider) showEditModal(state);
|
|
48
53
|
}}
|
|
49
54
|
/>
|
|
50
55
|
)
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
type
|
|
58
|
+
type FormModalContextType<T, K> = {
|
|
54
59
|
showCreateModal: ShowCreateModal;
|
|
55
60
|
showEditModal: ShowEditModal<T, K>;
|
|
61
|
+
hasProvider: boolean;
|
|
56
62
|
}
|
|
57
63
|
|
|
58
64
|
type T = any;
|
|
59
65
|
type K = any;
|
|
60
|
-
const defaultErrorState:
|
|
66
|
+
const defaultErrorState: FormModalContextType<T, K> = {
|
|
61
67
|
showCreateModal: () => {
|
|
62
|
-
console.error(
|
|
68
|
+
console.error('The showCreateModal function should only be used in a child of the FormModalProvider component.');
|
|
63
69
|
},
|
|
64
|
-
showEditModal:
|
|
65
|
-
console.error(
|
|
70
|
+
showEditModal: (state: { [key in keyof T]: FormValue } & K) => {
|
|
71
|
+
console.error('The showEditModal function should only be used in a child of the FormModalProvider component.');
|
|
66
72
|
},
|
|
73
|
+
hasProvider: false,
|
|
67
74
|
};
|
|
68
|
-
export const
|
|
75
|
+
export const FormModalContext = React.createContext(defaultErrorState);
|
|
69
76
|
|
|
70
|
-
export const
|
|
77
|
+
export const useFormModal = () => useContext(FormModalContext);
|
|
71
78
|
|
|
72
79
|
|
|
73
|
-
export type
|
|
80
|
+
export type FormModalProviderProps<
|
|
74
81
|
T extends FormFields,
|
|
75
82
|
K extends IncludeData<T>
|
|
76
83
|
> = {
|
|
@@ -88,7 +95,7 @@ export type CreateEditModalProviderProps<
|
|
|
88
95
|
width?: Width;
|
|
89
96
|
children: ReactNode;
|
|
90
97
|
}
|
|
91
|
-
export const
|
|
98
|
+
export const FormModalProvider: React.FC<FormModalProviderProps<T, K>> = ({
|
|
92
99
|
createModalTitle,
|
|
93
100
|
editModalTitle,
|
|
94
101
|
formFields,
|
|
@@ -104,16 +111,17 @@ export const CreateEditModalProvider: React.FC<CreateEditModalProviderProps<T, K
|
|
|
104
111
|
const [instanceInEditModal, showEditModal] = useState<({ [key in keyof T]: FormValue } & K) | null>(null);
|
|
105
112
|
const { strings } = useLocalization();
|
|
106
113
|
return (
|
|
107
|
-
<
|
|
114
|
+
<FormModalContext.Provider
|
|
108
115
|
value={{
|
|
109
116
|
showCreateModal: (show?: boolean) =>
|
|
110
117
|
showCreateModal(typeof show === 'undefined' ? true : show),
|
|
111
118
|
showEditModal,
|
|
119
|
+
hasProvider: true,
|
|
112
120
|
}}>
|
|
113
121
|
{children}
|
|
114
122
|
|
|
115
123
|
{createModalActive && (onCreate || onSave) && (
|
|
116
|
-
<
|
|
124
|
+
<FormModal
|
|
117
125
|
modalTitle={createModalTitle || strings.getString('modal_create')}
|
|
118
126
|
onHide={() => showCreateModal(false)}
|
|
119
127
|
initialState={initialState}
|
|
@@ -125,7 +133,7 @@ export const CreateEditModalProvider: React.FC<CreateEditModalProviderProps<T, K
|
|
|
125
133
|
/>
|
|
126
134
|
)}
|
|
127
135
|
{instanceInEditModal && (onUpdate || onSave) && (
|
|
128
|
-
<
|
|
136
|
+
<FormModal
|
|
129
137
|
show={!!instanceInEditModal}
|
|
130
138
|
modalTitle={editModalTitle || strings.getString('modal_edit')}
|
|
131
139
|
onHide={() => showEditModal(null)}
|
|
@@ -137,6 +145,6 @@ export const CreateEditModalProvider: React.FC<CreateEditModalProviderProps<T, K
|
|
|
137
145
|
dialogClassName={dialogClassName}
|
|
138
146
|
/>
|
|
139
147
|
)}
|
|
140
|
-
</
|
|
148
|
+
</FormModalContext.Provider>
|
|
141
149
|
);
|
|
142
150
|
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { useDragDropManager } from 'react-dnd';
|
|
2
1
|
import React, {
|
|
3
2
|
useEffect,
|
|
4
3
|
useState,
|
|
@@ -7,6 +6,7 @@ import React, {
|
|
|
7
6
|
ReactElement,
|
|
8
7
|
ReactNode,
|
|
9
8
|
ChangeEvent,
|
|
9
|
+
useMemo,
|
|
10
10
|
Ref,
|
|
11
11
|
} from 'react';
|
|
12
12
|
import { FaSort, FaSortUp, FaSortDown } from 'react-icons/fa';
|
|
@@ -25,16 +25,11 @@ import {
|
|
|
25
25
|
import { CloseButton } from '../buttons/IconButtons';
|
|
26
26
|
import { DragAndDropList, DragAndDropListComponent, DragAndDropListComponentProps } from './DragAndDropList';
|
|
27
27
|
import { useLocalization } from '../../localization/LocalizationContext';
|
|
28
|
-
import {
|
|
28
|
+
import { useFormModal } from '../forms/FormModalProvider';
|
|
29
29
|
|
|
30
|
-
const PaginationButton = (props: ButtonProps) =>
|
|
31
|
-
|
|
32
|
-
const manager = useDragDropManager();
|
|
33
|
-
console.log({ manager })
|
|
34
|
-
return (
|
|
30
|
+
const PaginationButton = (props: ButtonProps) => (
|
|
35
31
|
<Button variant='outline-secondary' size='sm' {...props} />
|
|
36
32
|
)
|
|
37
|
-
}
|
|
38
33
|
|
|
39
34
|
export type OrderByColumn<R> = string | ((row: R) => string | number);
|
|
40
35
|
|
|
@@ -51,6 +46,8 @@ export type DataTableColumn<R> = {
|
|
|
51
46
|
orderBy?: OrderByColumn<R>;
|
|
52
47
|
optionsDropdown?: OptionsDropdown;
|
|
53
48
|
className?: string;
|
|
49
|
+
value?: number | string | ((row: R) => number);
|
|
50
|
+
formatSum?: ((value: number) => ReactElement | string | number) | ReactElement | string | number;
|
|
54
51
|
selector: number | string | ((row: R) => ReactElement | string | number | (ReactElement | string | number)[]);
|
|
55
52
|
onClick?: OnClickRow<R>;
|
|
56
53
|
}
|
|
@@ -93,6 +90,7 @@ export type DataTableProps<D extends any[]> = {
|
|
|
93
90
|
className?: string;
|
|
94
91
|
rowClassName?: string | ((row: D[number]) => string);
|
|
95
92
|
style?: any;
|
|
93
|
+
showSum?: boolean;
|
|
96
94
|
}
|
|
97
95
|
|
|
98
96
|
export const DataTable = <D extends any[]>({
|
|
@@ -113,13 +111,11 @@ export const DataTable = <D extends any[]>({
|
|
|
113
111
|
className,
|
|
114
112
|
rowClassName,
|
|
115
113
|
style,
|
|
114
|
+
showSum,
|
|
116
115
|
...restProps
|
|
117
116
|
}: DataTableProps<D>) => {
|
|
118
|
-
const { showEditModal } =
|
|
117
|
+
const { showEditModal, hasProvider } = useFormModal();
|
|
119
118
|
type R = D[number];
|
|
120
|
-
|
|
121
|
-
const manager = useDragDropManager();
|
|
122
|
-
console.log({ manager })
|
|
123
119
|
|
|
124
120
|
if (Object.keys(restProps).length !== 0) console.error('Unrecognised props:', restProps);
|
|
125
121
|
|
|
@@ -186,7 +182,7 @@ export const DataTable = <D extends any[]>({
|
|
|
186
182
|
{...{ ...(typeof onClickRow === 'function' || showEditModal)
|
|
187
183
|
? { onClick: () => {
|
|
188
184
|
if (onClickRow) onClickRow(row);
|
|
189
|
-
if (
|
|
185
|
+
if (hasProvider) showEditModal(row);
|
|
190
186
|
} }
|
|
191
187
|
: {}
|
|
192
188
|
}}
|
|
@@ -207,6 +203,12 @@ export const DataTable = <D extends any[]>({
|
|
|
207
203
|
)}
|
|
208
204
|
</tr>
|
|
209
205
|
);
|
|
206
|
+
|
|
207
|
+
const sums = useMemo(() => columns.map(({ value }) => (
|
|
208
|
+
value && data.reduce((sum, row) => (
|
|
209
|
+
sum + (typeof value === 'function' ? value(row) : row[value])
|
|
210
|
+
), 0)
|
|
211
|
+
)), [columns])
|
|
210
212
|
|
|
211
213
|
if (!Component) return null;
|
|
212
214
|
return (
|
|
@@ -423,6 +425,25 @@ export const DataTable = <D extends any[]>({
|
|
|
423
425
|
: data.map((row, index) => <Component row={row} key={index} />)
|
|
424
426
|
}
|
|
425
427
|
</tbody>
|
|
428
|
+
{showSum && (
|
|
429
|
+
<tfoot>
|
|
430
|
+
<tr>
|
|
431
|
+
|
|
432
|
+
{columns.map(({ value, formatSum }, index) =>
|
|
433
|
+
<td
|
|
434
|
+
key={index}
|
|
435
|
+
>
|
|
436
|
+
{value
|
|
437
|
+
? (typeof formatSum === 'function'
|
|
438
|
+
? formatSum(sums[index])
|
|
439
|
+
: sums[index]
|
|
440
|
+
)
|
|
441
|
+
: formatSum}
|
|
442
|
+
</td>
|
|
443
|
+
)}
|
|
444
|
+
</tr>
|
|
445
|
+
</tfoot>
|
|
446
|
+
)}
|
|
426
447
|
</Table>
|
|
427
448
|
</div>
|
|
428
449
|
)
|
package/src/index.ts
CHANGED
|
@@ -4,8 +4,8 @@ export { default as ConfirmButton } from './components/buttons/ConfirmButton';
|
|
|
4
4
|
export { default as DeleteConfirmButton } from './components/buttons/DeleteConfirmButton';
|
|
5
5
|
export * from './components/buttons/DeleteConfirmButton';
|
|
6
6
|
|
|
7
|
-
export * from './components/forms/
|
|
8
|
-
export * from './components/forms/
|
|
7
|
+
export * from './components/forms/FormModal';
|
|
8
|
+
export * from './components/forms/FormModalProvider';
|
|
9
9
|
export * from './components/forms/FormFields';
|
|
10
10
|
|
|
11
11
|
export * from './components/indicators/LoadingIndicator';
|