@etsoo/materialui 1.0.1
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/.eslintignore +3 -0
- package/.eslintrc.json +38 -0
- package/.gitattributes +2 -0
- package/.github/workflows/main.yml +48 -0
- package/.prettierignore +5 -0
- package/.prettierrc +6 -0
- package/LICENSE +21 -0
- package/README.md +16 -0
- package/__tests__/ComboBox.tsx +30 -0
- package/__tests__/MUGlobalTests.tsx +58 -0
- package/__tests__/NotifierMUTests.tsx +217 -0
- package/__tests__/SelectEx.tsx +26 -0
- package/__tests__/tsconfig.json +19 -0
- package/babel.config.json +11 -0
- package/lib/AuditDisplay.d.ts +33 -0
- package/lib/AuditDisplay.js +52 -0
- package/lib/AutocompleteExtendedProps.d.ts +64 -0
- package/lib/AutocompleteExtendedProps.js +1 -0
- package/lib/BackButton.d.ts +13 -0
- package/lib/BackButton.js +33 -0
- package/lib/BridgeCloseButton.d.ts +23 -0
- package/lib/BridgeCloseButton.js +32 -0
- package/lib/ButtonLink.d.ts +17 -0
- package/lib/ButtonLink.js +19 -0
- package/lib/ComboBox.d.ts +38 -0
- package/lib/ComboBox.js +108 -0
- package/lib/CountdownButton.d.ts +23 -0
- package/lib/CountdownButton.js +81 -0
- package/lib/CustomFabProps.d.ts +27 -0
- package/lib/CustomFabProps.js +1 -0
- package/lib/DataGridEx.d.ts +94 -0
- package/lib/DataGridEx.js +329 -0
- package/lib/DataGridRenderers.d.ts +22 -0
- package/lib/DataGridRenderers.js +99 -0
- package/lib/DialogButton.d.ts +54 -0
- package/lib/DialogButton.js +45 -0
- package/lib/DnDList.d.ts +87 -0
- package/lib/DnDList.js +153 -0
- package/lib/DraggablePaperComponent.d.ts +8 -0
- package/lib/DraggablePaperComponent.js +12 -0
- package/lib/EmailInput.d.ts +11 -0
- package/lib/EmailInput.js +15 -0
- package/lib/FabBox.d.ts +21 -0
- package/lib/FabBox.js +31 -0
- package/lib/FlexBox.d.ts +14 -0
- package/lib/FlexBox.js +18 -0
- package/lib/GridDataFormat.d.ts +10 -0
- package/lib/GridDataFormat.js +43 -0
- package/lib/IconButtonLink.d.ts +17 -0
- package/lib/IconButtonLink.js +16 -0
- package/lib/InputField.d.ts +21 -0
- package/lib/InputField.js +39 -0
- package/lib/ItemList.d.ts +56 -0
- package/lib/ItemList.js +69 -0
- package/lib/ListItemRightIcon.d.ts +4 -0
- package/lib/ListItemRightIcon.js +8 -0
- package/lib/ListMoreDisplay.d.ts +35 -0
- package/lib/ListMoreDisplay.js +99 -0
- package/lib/LoadingButton.d.ts +16 -0
- package/lib/LoadingButton.js +41 -0
- package/lib/MUGlobal.d.ts +102 -0
- package/lib/MUGlobal.js +184 -0
- package/lib/MaskInput.d.ts +34 -0
- package/lib/MaskInput.js +43 -0
- package/lib/MobileListItemRenderer.d.ts +17 -0
- package/lib/MobileListItemRenderer.js +35 -0
- package/lib/MoreFab.d.ts +45 -0
- package/lib/MoreFab.js +95 -0
- package/lib/NotifierMU.d.ts +47 -0
- package/lib/NotifierMU.js +387 -0
- package/lib/NotifierPromptProps.d.ts +22 -0
- package/lib/NotifierPromptProps.js +1 -0
- package/lib/OptionGroup.d.ts +58 -0
- package/lib/OptionGroup.js +81 -0
- package/lib/PList.d.ts +15 -0
- package/lib/PList.js +12 -0
- package/lib/ProgressCount.d.ts +44 -0
- package/lib/ProgressCount.js +79 -0
- package/lib/PullToRefreshUI.d.ts +9 -0
- package/lib/PullToRefreshUI.js +18 -0
- package/lib/RLink.d.ts +14 -0
- package/lib/RLink.js +37 -0
- package/lib/ResponsibleContainer.d.ts +87 -0
- package/lib/ResponsibleContainer.js +156 -0
- package/lib/ScrollTopFab.d.ts +7 -0
- package/lib/ScrollTopFab.js +25 -0
- package/lib/ScrollerListEx.d.ts +81 -0
- package/lib/ScrollerListEx.js +167 -0
- package/lib/SearchBar.d.ts +29 -0
- package/lib/SearchBar.js +260 -0
- package/lib/SearchField.d.ts +21 -0
- package/lib/SearchField.js +39 -0
- package/lib/SearchOptionGroup.d.ts +9 -0
- package/lib/SearchOptionGroup.js +14 -0
- package/lib/SelectBool.d.ts +13 -0
- package/lib/SelectBool.js +22 -0
- package/lib/SelectEx.d.ts +50 -0
- package/lib/SelectEx.js +156 -0
- package/lib/ShowDataComparison.d.ts +20 -0
- package/lib/ShowDataComparison.js +58 -0
- package/lib/Switch.d.ts +29 -0
- package/lib/Switch.js +34 -0
- package/lib/SwitchAnt.d.ts +25 -0
- package/lib/SwitchAnt.js +40 -0
- package/lib/TabBox.d.ts +54 -0
- package/lib/TabBox.js +31 -0
- package/lib/TableEx.d.ts +65 -0
- package/lib/TableEx.js +270 -0
- package/lib/TextFieldEx.d.ts +101 -0
- package/lib/TextFieldEx.js +126 -0
- package/lib/Tiplist.d.ts +18 -0
- package/lib/Tiplist.js +157 -0
- package/lib/TooltipClick.d.ts +15 -0
- package/lib/TooltipClick.js +40 -0
- package/lib/UserAvatar.d.ts +24 -0
- package/lib/UserAvatar.js +25 -0
- package/lib/UserAvatarEditor.d.ts +53 -0
- package/lib/UserAvatarEditor.js +129 -0
- package/lib/app/CommonApp.d.ts +38 -0
- package/lib/app/CommonApp.js +149 -0
- package/lib/app/IServiceAppSettings.d.ts +11 -0
- package/lib/app/IServiceAppSettings.js +1 -0
- package/lib/app/IServicePage.d.ts +6 -0
- package/lib/app/IServicePage.js +1 -0
- package/lib/app/IServiceUser.d.ts +14 -0
- package/lib/app/IServiceUser.js +1 -0
- package/lib/app/ISmartERPUser.d.ts +14 -0
- package/lib/app/ISmartERPUser.js +1 -0
- package/lib/app/Labels.d.ts +65 -0
- package/lib/app/Labels.js +62 -0
- package/lib/app/ReactApp.d.ts +195 -0
- package/lib/app/ReactApp.js +296 -0
- package/lib/app/ServiceApp.d.ts +78 -0
- package/lib/app/ServiceApp.js +244 -0
- package/lib/index.d.ts +74 -0
- package/lib/index.js +74 -0
- package/lib/pages/CommonPage.d.ts +11 -0
- package/lib/pages/CommonPage.js +60 -0
- package/lib/pages/CommonPageProps.d.ts +59 -0
- package/lib/pages/CommonPageProps.js +1 -0
- package/lib/pages/DataGridPage.d.ts +9 -0
- package/lib/pages/DataGridPage.js +79 -0
- package/lib/pages/DataGridPageProps.d.ts +17 -0
- package/lib/pages/DataGridPageProps.js +1 -0
- package/lib/pages/EditPage.d.ts +33 -0
- package/lib/pages/EditPage.js +29 -0
- package/lib/pages/FixedListPage.d.ts +15 -0
- package/lib/pages/FixedListPage.js +70 -0
- package/lib/pages/ListPage.d.ts +9 -0
- package/lib/pages/ListPage.js +50 -0
- package/lib/pages/ListPageProps.d.ts +7 -0
- package/lib/pages/ListPageProps.js +1 -0
- package/lib/pages/ResponsivePage.d.ts +9 -0
- package/lib/pages/ResponsivePage.js +45 -0
- package/lib/pages/ResponsivePageProps.d.ts +39 -0
- package/lib/pages/ResponsivePageProps.js +1 -0
- package/lib/pages/SearchPageProps.d.ts +30 -0
- package/lib/pages/SearchPageProps.js +1 -0
- package/lib/pages/TablePage.d.ts +9 -0
- package/lib/pages/TablePage.js +69 -0
- package/lib/pages/TablePageProps.d.ts +7 -0
- package/lib/pages/TablePageProps.js +1 -0
- package/lib/pages/ViewPage.d.ts +66 -0
- package/lib/pages/ViewPage.js +105 -0
- package/lib/texts/DateText.d.ts +34 -0
- package/lib/texts/DateText.js +25 -0
- package/lib/texts/MoneyText.d.ts +21 -0
- package/lib/texts/MoneyText.js +14 -0
- package/lib/texts/NumberText.d.ts +25 -0
- package/lib/texts/NumberText.js +14 -0
- package/package.json +97 -0
- package/src/AuditDisplay.tsx +114 -0
- package/src/AutocompleteExtendedProps.ts +83 -0
- package/src/BackButton.tsx +55 -0
- package/src/BridgeCloseButton.tsx +69 -0
- package/src/ButtonLink.tsx +32 -0
- package/src/ComboBox.tsx +251 -0
- package/src/CountdownButton.tsx +119 -0
- package/src/CustomFabProps.ts +32 -0
- package/src/DataGridEx.tsx +713 -0
- package/src/DataGridRenderers.tsx +140 -0
- package/src/DialogButton.tsx +163 -0
- package/src/DnDList.tsx +344 -0
- package/src/DraggablePaperComponent.tsx +19 -0
- package/src/EmailInput.tsx +24 -0
- package/src/FabBox.tsx +51 -0
- package/src/FlexBox.tsx +20 -0
- package/src/GridDataFormat.tsx +77 -0
- package/src/IconButtonLink.tsx +29 -0
- package/src/InputField.tsx +82 -0
- package/src/ItemList.tsx +204 -0
- package/src/ListItemRightIcon.tsx +9 -0
- package/src/ListMoreDisplay.tsx +205 -0
- package/src/LoadingButton.tsx +75 -0
- package/src/MUGlobal.ts +220 -0
- package/src/MaskInput.tsx +107 -0
- package/src/MobileListItemRenderer.tsx +79 -0
- package/src/MoreFab.tsx +211 -0
- package/src/NotifierMU.tsx +654 -0
- package/src/NotifierPromptProps.ts +24 -0
- package/src/OptionGroup.tsx +223 -0
- package/src/PList.tsx +27 -0
- package/src/ProgressCount.tsx +166 -0
- package/src/PullToRefreshUI.tsx +21 -0
- package/src/RLink.tsx +64 -0
- package/src/ResponsibleContainer.tsx +394 -0
- package/src/ScrollTopFab.tsx +34 -0
- package/src/ScrollerListEx.tsx +387 -0
- package/src/SearchBar.tsx +396 -0
- package/src/SearchField.tsx +82 -0
- package/src/SearchOptionGroup.tsx +31 -0
- package/src/SelectBool.tsx +33 -0
- package/src/SelectEx.tsx +290 -0
- package/src/ShowDataComparison.tsx +106 -0
- package/src/Switch.tsx +94 -0
- package/src/SwitchAnt.tsx +95 -0
- package/src/TabBox.tsx +118 -0
- package/src/TableEx.tsx +558 -0
- package/src/TextFieldEx.tsx +249 -0
- package/src/Tiplist.tsx +303 -0
- package/src/TooltipClick.tsx +84 -0
- package/src/UserAvatar.tsx +64 -0
- package/src/UserAvatarEditor.tsx +287 -0
- package/src/app/CommonApp.ts +223 -0
- package/src/app/IServiceAppSettings.ts +13 -0
- package/src/app/IServicePage.ts +6 -0
- package/src/app/IServiceUser.ts +17 -0
- package/src/app/ISmartERPUser.ts +16 -0
- package/src/app/Labels.ts +77 -0
- package/src/app/ReactApp.ts +504 -0
- package/src/app/ServiceApp.ts +352 -0
- package/src/index.ts +77 -0
- package/src/pages/CommonPage.tsx +128 -0
- package/src/pages/CommonPageProps.ts +70 -0
- package/src/pages/DataGridPage.tsx +140 -0
- package/src/pages/DataGridPageProps.ts +24 -0
- package/src/pages/EditPage.tsx +114 -0
- package/src/pages/FixedListPage.tsx +141 -0
- package/src/pages/ListPage.tsx +90 -0
- package/src/pages/ListPageProps.ts +12 -0
- package/src/pages/ResponsivePage.tsx +68 -0
- package/src/pages/ResponsivePageProps.ts +57 -0
- package/src/pages/SearchPageProps.ts +39 -0
- package/src/pages/TablePage.tsx +126 -0
- package/src/pages/TablePageProps.ts +12 -0
- package/src/pages/ViewPage.tsx +282 -0
- package/src/texts/DateText.tsx +74 -0
- package/src/texts/MoneyText.tsx +49 -0
- package/src/texts/NumberText.tsx +40 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Card, CardActions, CardContent, CardHeader, CircularProgress } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { GridDataGet } from '@etsoo/react';
|
|
4
|
+
import { LoadingButton } from './LoadingButton';
|
|
5
|
+
import { globalApp } from './app/ReactApp';
|
|
6
|
+
/**
|
|
7
|
+
* ListMoreDisplay
|
|
8
|
+
* @param props Props
|
|
9
|
+
* @returns Component
|
|
10
|
+
*/
|
|
11
|
+
export function ListMoreDisplay(props) {
|
|
12
|
+
// Destruct
|
|
13
|
+
const { children, defaultOrderBy, headerRenderer, autoLoad = headerRenderer == null, headerTitle, loadBatchSize, loadData, moreLabel = typeof globalApp === 'undefined'
|
|
14
|
+
? undefined
|
|
15
|
+
: globalApp.get('more') + '...', fieldTemplate, threshold, ...rest } = props;
|
|
16
|
+
// Refs
|
|
17
|
+
const refs = React.useRef({
|
|
18
|
+
autoLoad,
|
|
19
|
+
currentPage: 0,
|
|
20
|
+
hasNextPage: true,
|
|
21
|
+
isNextPageLoading: false,
|
|
22
|
+
orderBy: defaultOrderBy,
|
|
23
|
+
batchSize: 10,
|
|
24
|
+
loadedItems: 0,
|
|
25
|
+
selectedItems: []
|
|
26
|
+
});
|
|
27
|
+
const ref = refs.current;
|
|
28
|
+
// States
|
|
29
|
+
const [states, setStates] = React.useReducer((currentStates, newStates) => {
|
|
30
|
+
return { ...currentStates, ...newStates };
|
|
31
|
+
}, { completed: false });
|
|
32
|
+
// Load data
|
|
33
|
+
const loadDataLocal = async (reset = false) => {
|
|
34
|
+
// Prevent multiple loadings
|
|
35
|
+
if (!ref.hasNextPage || ref.isNextPageLoading)
|
|
36
|
+
return;
|
|
37
|
+
// Update state
|
|
38
|
+
ref.isNextPageLoading = true;
|
|
39
|
+
// Parameters
|
|
40
|
+
const { currentPage, batchSize, orderBy, orderByAsc, data } = ref;
|
|
41
|
+
const loadProps = {
|
|
42
|
+
currentPage,
|
|
43
|
+
batchSize,
|
|
44
|
+
orderBy,
|
|
45
|
+
orderByAsc,
|
|
46
|
+
data
|
|
47
|
+
};
|
|
48
|
+
const mergedData = GridDataGet(loadProps, fieldTemplate);
|
|
49
|
+
const items = await loadData(mergedData);
|
|
50
|
+
if (items == null || ref.isMounted === false) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
ref.isMounted = true;
|
|
54
|
+
const newItems = items.length;
|
|
55
|
+
const hasNextPage = newItems >= batchSize;
|
|
56
|
+
ref.lastLoadedItems = newItems;
|
|
57
|
+
ref.isNextPageLoading = false;
|
|
58
|
+
ref.hasNextPage = hasNextPage;
|
|
59
|
+
// Next page
|
|
60
|
+
ref.currentPage = currentPage + 1;
|
|
61
|
+
// Update rows
|
|
62
|
+
if (states.items == null || reset)
|
|
63
|
+
setStates({ items, completed: !hasNextPage });
|
|
64
|
+
else
|
|
65
|
+
setStates({
|
|
66
|
+
items: [...states.items, ...items],
|
|
67
|
+
completed: !hasNextPage
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const reset = (data) => {
|
|
71
|
+
// Update the form data
|
|
72
|
+
ref.data = data;
|
|
73
|
+
// Reset page number
|
|
74
|
+
ref.isNextPageLoading = false;
|
|
75
|
+
ref.currentPage = 0;
|
|
76
|
+
ref.hasNextPage = true;
|
|
77
|
+
// Load data
|
|
78
|
+
loadDataLocal(true);
|
|
79
|
+
};
|
|
80
|
+
React.useEffect(() => {
|
|
81
|
+
if (autoLoad)
|
|
82
|
+
loadDataLocal();
|
|
83
|
+
}, [autoLoad]);
|
|
84
|
+
React.useEffect(() => {
|
|
85
|
+
return () => {
|
|
86
|
+
ref.isMounted = false;
|
|
87
|
+
};
|
|
88
|
+
}, []);
|
|
89
|
+
return (React.createElement(React.Fragment, null,
|
|
90
|
+
headerRenderer && headerRenderer(reset),
|
|
91
|
+
React.createElement(Card, { ...rest },
|
|
92
|
+
React.createElement(CardHeader, { title: headerTitle }),
|
|
93
|
+
React.createElement(CardContent, { sx: {
|
|
94
|
+
paddingTop: 0,
|
|
95
|
+
paddingBottom: states.completed ? 0 : 'inherit'
|
|
96
|
+
} }, states.items == null ? (React.createElement(CircularProgress, { size: 20 })) : (states.items.map((item, index) => children(item, index)))),
|
|
97
|
+
!states.completed && (React.createElement(CardActions, { sx: { justifyContent: 'flex-end' } },
|
|
98
|
+
React.createElement(LoadingButton, { onClick: async () => await loadDataLocal() }, moreLabel))))));
|
|
99
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { ButtonProps, CircularProgressProps } from '@mui/material';
|
|
3
|
+
/**
|
|
4
|
+
* Loading button props
|
|
5
|
+
*/
|
|
6
|
+
export declare type LoadingButtonProps = ButtonProps & {
|
|
7
|
+
/**
|
|
8
|
+
* Loading icon props
|
|
9
|
+
*/
|
|
10
|
+
loadingIconProps?: CircularProgressProps;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Loading button
|
|
14
|
+
* @param props Props
|
|
15
|
+
*/
|
|
16
|
+
export declare function LoadingButton(props: LoadingButtonProps): JSX.Element;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Button, CircularProgress } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Loading button
|
|
5
|
+
* @param props Props
|
|
6
|
+
*/
|
|
7
|
+
export function LoadingButton(props) {
|
|
8
|
+
var _a;
|
|
9
|
+
// Destruct
|
|
10
|
+
const { endIcon, loadingIconProps = {}, onClick, ...rest } = props;
|
|
11
|
+
// Default size
|
|
12
|
+
(_a = loadingIconProps.size) !== null && _a !== void 0 ? _a : (loadingIconProps.size = 12);
|
|
13
|
+
// State
|
|
14
|
+
// https://stackoverflow.com/questions/55265255/react-usestate-hook-event-handler-using-initial-state
|
|
15
|
+
const [loading, setLoading] = React.useState(false);
|
|
16
|
+
// Icon
|
|
17
|
+
const localEndIcon = loading ? (React.createElement(CircularProgress, { ...loadingIconProps })) : (endIcon);
|
|
18
|
+
// Check if the component is mounted
|
|
19
|
+
const isMounted = React.useRef(true);
|
|
20
|
+
React.useEffect(() => {
|
|
21
|
+
return () => {
|
|
22
|
+
isMounted.current = false;
|
|
23
|
+
};
|
|
24
|
+
}, []);
|
|
25
|
+
// Layout
|
|
26
|
+
return (React.createElement(Button, { disabled: loading, endIcon: localEndIcon, onClick: async (event) => {
|
|
27
|
+
if (onClick) {
|
|
28
|
+
// Update state
|
|
29
|
+
setLoading(true);
|
|
30
|
+
// https://stackoverflow.com/questions/38508420/how-to-know-if-a-function-is-async
|
|
31
|
+
// const AsyncFunction = (async () => {}).constructor;
|
|
32
|
+
// onClick instanceof AsyncFunction
|
|
33
|
+
await onClick(event);
|
|
34
|
+
// Warning: Can't perform a React state update on an unmounted component
|
|
35
|
+
// It's necessary to check the component is mounted now
|
|
36
|
+
if (isMounted.current) {
|
|
37
|
+
setLoading(false);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}, ...rest }));
|
|
41
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { ListItemButtonProps, Theme } from '@mui/material';
|
|
3
|
+
/**
|
|
4
|
+
* Mouse event handler with data
|
|
5
|
+
*/
|
|
6
|
+
export declare type MouseEventWithDataHandler<T> = (event: React.MouseEvent<HTMLDivElement>, data: T) => void;
|
|
7
|
+
/**
|
|
8
|
+
* MUGlobal for global configurations
|
|
9
|
+
*/
|
|
10
|
+
export declare class MUGlobal {
|
|
11
|
+
/**
|
|
12
|
+
* Search field shrink
|
|
13
|
+
*/
|
|
14
|
+
static searchFieldShrink: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Search field size
|
|
17
|
+
*/
|
|
18
|
+
static searchFieldSize: 'small' | 'medium';
|
|
19
|
+
/**
|
|
20
|
+
* Search field variant
|
|
21
|
+
*/
|
|
22
|
+
static searchFieldVariant: 'standard' | 'filled' | 'outlined';
|
|
23
|
+
/**
|
|
24
|
+
* Input field shrink
|
|
25
|
+
*/
|
|
26
|
+
static inputFieldShrink: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* Input field size
|
|
29
|
+
*/
|
|
30
|
+
static inputFieldSize: 'small' | 'medium';
|
|
31
|
+
/**
|
|
32
|
+
* Input field variant
|
|
33
|
+
*/
|
|
34
|
+
static inputFieldVariant: 'standard' | 'filled' | 'outlined';
|
|
35
|
+
/**
|
|
36
|
+
* TextField variant
|
|
37
|
+
*/
|
|
38
|
+
static textFieldVariant: 'standard' | 'filled' | 'outlined';
|
|
39
|
+
/**
|
|
40
|
+
* Page default paddings
|
|
41
|
+
*/
|
|
42
|
+
static pagePaddings: {
|
|
43
|
+
xs: number;
|
|
44
|
+
sm: number;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Get menu item props
|
|
48
|
+
* @param path Current path
|
|
49
|
+
* @param href Item's href
|
|
50
|
+
* @returns Props
|
|
51
|
+
*/
|
|
52
|
+
static getMenuItem(path: string, href: string): ListItemButtonProps<"div", {}>;
|
|
53
|
+
/**
|
|
54
|
+
* Update object number properties with half of it
|
|
55
|
+
* @param input Input object
|
|
56
|
+
* @returns Updated object
|
|
57
|
+
*/
|
|
58
|
+
static half(input: object): {};
|
|
59
|
+
/**
|
|
60
|
+
* Reverse object number properties, like 5 to -5
|
|
61
|
+
* @param input Input object
|
|
62
|
+
* @returns Updated object
|
|
63
|
+
*/
|
|
64
|
+
static reverse(input: object): {};
|
|
65
|
+
/**
|
|
66
|
+
* Update object number properties with adjustment
|
|
67
|
+
* @param input Input object
|
|
68
|
+
* @param adjust Adjust value or new size object
|
|
69
|
+
* @param field Specific field
|
|
70
|
+
* @returns Updated object
|
|
71
|
+
*/
|
|
72
|
+
static increase(input: object, adjust: number | object, field?: string): {};
|
|
73
|
+
/**
|
|
74
|
+
* Adjust size with theme update
|
|
75
|
+
* @param size Base size
|
|
76
|
+
* @param adjust Adjustment
|
|
77
|
+
* @param updateFunc Theme update function
|
|
78
|
+
* @returns Updated object
|
|
79
|
+
*/
|
|
80
|
+
static adjustWithTheme(size: number, adjust: object, updateFunc: (value: number) => string): {};
|
|
81
|
+
/**
|
|
82
|
+
* Break points defined
|
|
83
|
+
*/
|
|
84
|
+
static breakpoints: readonly ["xs", "sm", "md", "lg", "xl"];
|
|
85
|
+
/**
|
|
86
|
+
* Get multple medias theme space
|
|
87
|
+
* Responsive values and Breakpoints as an object
|
|
88
|
+
* xs = theme.breakpoints.up('xs')
|
|
89
|
+
* https://mui.com/system/basics/
|
|
90
|
+
* @param spaces Spaces
|
|
91
|
+
* @param theme Theme
|
|
92
|
+
* @returns Result
|
|
93
|
+
*/
|
|
94
|
+
static getSpace(spaces: object, theme: Theme): number;
|
|
95
|
+
/**
|
|
96
|
+
* Update object number properties with theme
|
|
97
|
+
* @param input Input object
|
|
98
|
+
* @param updateFunc Theme update function
|
|
99
|
+
* @returns Updated object
|
|
100
|
+
*/
|
|
101
|
+
static updateWithTheme(input: {}, updateFunc: (value: number) => string): {};
|
|
102
|
+
}
|
package/lib/MUGlobal.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { NumberUtils } from '@etsoo/shared';
|
|
2
|
+
import { RLink } from './RLink';
|
|
3
|
+
/**
|
|
4
|
+
* MUGlobal for global configurations
|
|
5
|
+
*/
|
|
6
|
+
export class MUGlobal {
|
|
7
|
+
/**
|
|
8
|
+
* Get menu item props
|
|
9
|
+
* @param path Current path
|
|
10
|
+
* @param href Item's href
|
|
11
|
+
* @returns Props
|
|
12
|
+
*/
|
|
13
|
+
static getMenuItem(path, href) {
|
|
14
|
+
let selected = false;
|
|
15
|
+
if (path === href) {
|
|
16
|
+
// Exact match, most common case
|
|
17
|
+
selected = true;
|
|
18
|
+
}
|
|
19
|
+
else if (href.endsWith('*')) {
|
|
20
|
+
href = href.slice(0, -1);
|
|
21
|
+
selected = path.startsWith(href);
|
|
22
|
+
}
|
|
23
|
+
else if (href.endsWith('/all')) {
|
|
24
|
+
selected = path.startsWith(href.slice(0, -3));
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
component: RLink,
|
|
28
|
+
selected,
|
|
29
|
+
href,
|
|
30
|
+
sx: {
|
|
31
|
+
...(selected && {
|
|
32
|
+
'.MuiListItemIcon-root': {
|
|
33
|
+
color: (theme) => theme.palette.primary.main
|
|
34
|
+
}
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Update object number properties with half of it
|
|
41
|
+
* @param input Input object
|
|
42
|
+
* @returns Updated object
|
|
43
|
+
*/
|
|
44
|
+
static half(input) {
|
|
45
|
+
const newObj = { ...input };
|
|
46
|
+
Object.entries(newObj).forEach(([key, value]) => {
|
|
47
|
+
if (typeof value === 'number') {
|
|
48
|
+
Reflect.set(newObj, key, value / 2.0);
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
return newObj;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Reverse object number properties, like 5 to -5
|
|
55
|
+
* @param input Input object
|
|
56
|
+
* @returns Updated object
|
|
57
|
+
*/
|
|
58
|
+
static reverse(input) {
|
|
59
|
+
const newObj = { ...input };
|
|
60
|
+
Object.entries(newObj).forEach(([key, value]) => {
|
|
61
|
+
if (typeof value === 'number') {
|
|
62
|
+
Reflect.set(newObj, key, -value);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return newObj;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Update object number properties with adjustment
|
|
69
|
+
* @param input Input object
|
|
70
|
+
* @param adjust Adjust value or new size object
|
|
71
|
+
* @param field Specific field
|
|
72
|
+
* @returns Updated object
|
|
73
|
+
*/
|
|
74
|
+
static increase(input, adjust, field) {
|
|
75
|
+
const newObj = { ...input };
|
|
76
|
+
Object.entries(newObj).forEach(([key, value]) => {
|
|
77
|
+
if (typeof value === 'number') {
|
|
78
|
+
if (field == null || field === key) {
|
|
79
|
+
const adjustValue = typeof adjust === 'number'
|
|
80
|
+
? adjust
|
|
81
|
+
: Reflect.get(adjust, key);
|
|
82
|
+
if (adjustValue == null || typeof adjustValue !== 'number')
|
|
83
|
+
return;
|
|
84
|
+
Reflect.set(newObj, key, value + adjustValue);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return newObj;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Adjust size with theme update
|
|
92
|
+
* @param size Base size
|
|
93
|
+
* @param adjust Adjustment
|
|
94
|
+
* @param updateFunc Theme update function
|
|
95
|
+
* @returns Updated object
|
|
96
|
+
*/
|
|
97
|
+
static adjustWithTheme(size, adjust, updateFunc) {
|
|
98
|
+
const newObj = { ...adjust };
|
|
99
|
+
Object.entries(newObj).forEach(([key, value]) => {
|
|
100
|
+
if (typeof value === 'number') {
|
|
101
|
+
const newValue = NumberUtils.parseWithUnit(updateFunc(value));
|
|
102
|
+
if (newValue != null) {
|
|
103
|
+
Reflect.set(newObj, key, `${size - newValue[0]}${newValue[1]}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
return newObj;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get multple medias theme space
|
|
111
|
+
* Responsive values and Breakpoints as an object
|
|
112
|
+
* xs = theme.breakpoints.up('xs')
|
|
113
|
+
* https://mui.com/system/basics/
|
|
114
|
+
* @param spaces Spaces
|
|
115
|
+
* @param theme Theme
|
|
116
|
+
* @returns Result
|
|
117
|
+
*/
|
|
118
|
+
static getSpace(spaces, theme) {
|
|
119
|
+
const start = this.breakpoints.length - 1;
|
|
120
|
+
for (let i = start; i >= 0; i--) {
|
|
121
|
+
const key = this.breakpoints[i];
|
|
122
|
+
const value = Reflect.get(spaces, key);
|
|
123
|
+
if (typeof value === 'number') {
|
|
124
|
+
const mediaRaw = theme.breakpoints.up(key);
|
|
125
|
+
const mediaQuery = mediaRaw.substring(mediaRaw.indexOf('('));
|
|
126
|
+
if (window.matchMedia(mediaQuery).matches) {
|
|
127
|
+
return parseInt(theme.spacing(value), 10);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return 0;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Update object number properties with theme
|
|
135
|
+
* @param input Input object
|
|
136
|
+
* @param updateFunc Theme update function
|
|
137
|
+
* @returns Updated object
|
|
138
|
+
*/
|
|
139
|
+
static updateWithTheme(input, updateFunc) {
|
|
140
|
+
const newObj = { ...input };
|
|
141
|
+
Object.entries(newObj).forEach(([key, value]) => {
|
|
142
|
+
if (typeof value === 'number') {
|
|
143
|
+
Reflect.set(newObj, key, updateFunc(value));
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
return newObj;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Search field shrink
|
|
151
|
+
*/
|
|
152
|
+
MUGlobal.searchFieldShrink = true;
|
|
153
|
+
/**
|
|
154
|
+
* Search field size
|
|
155
|
+
*/
|
|
156
|
+
MUGlobal.searchFieldSize = 'small';
|
|
157
|
+
/**
|
|
158
|
+
* Search field variant
|
|
159
|
+
*/
|
|
160
|
+
MUGlobal.searchFieldVariant = 'outlined';
|
|
161
|
+
/**
|
|
162
|
+
* Input field shrink
|
|
163
|
+
*/
|
|
164
|
+
MUGlobal.inputFieldShrink = true;
|
|
165
|
+
/**
|
|
166
|
+
* Input field size
|
|
167
|
+
*/
|
|
168
|
+
MUGlobal.inputFieldSize = 'medium';
|
|
169
|
+
/**
|
|
170
|
+
* Input field variant
|
|
171
|
+
*/
|
|
172
|
+
MUGlobal.inputFieldVariant = 'outlined';
|
|
173
|
+
/**
|
|
174
|
+
* TextField variant
|
|
175
|
+
*/
|
|
176
|
+
MUGlobal.textFieldVariant = 'filled';
|
|
177
|
+
/**
|
|
178
|
+
* Page default paddings
|
|
179
|
+
*/
|
|
180
|
+
MUGlobal.pagePaddings = { xs: 2, sm: 3 };
|
|
181
|
+
/**
|
|
182
|
+
* Break points defined
|
|
183
|
+
*/
|
|
184
|
+
MUGlobal.breakpoints = ['xs', 'sm', 'md', 'lg', 'xl'];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { TextFieldProps } from '@mui/material';
|
|
3
|
+
/**
|
|
4
|
+
* Mask input props
|
|
5
|
+
*/
|
|
6
|
+
export declare type MaskInputProps<T extends IMask.AnyMaskedOptions> = TextFieldProps & {
|
|
7
|
+
/**
|
|
8
|
+
* Mask props
|
|
9
|
+
*/
|
|
10
|
+
mask: T;
|
|
11
|
+
/**
|
|
12
|
+
* Accept hanlder
|
|
13
|
+
*/
|
|
14
|
+
onAccept?: (value: unknown, maskRef: IMask.InputMask<T>, e?: InputEvent) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Complete handler
|
|
17
|
+
*/
|
|
18
|
+
onComplete?: (value: unknown, maskRef: IMask.InputMask<T>, e?: InputEvent) => void;
|
|
19
|
+
/**
|
|
20
|
+
* Is the field read only?
|
|
21
|
+
*/
|
|
22
|
+
readOnly?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Search case
|
|
25
|
+
*/
|
|
26
|
+
search?: boolean;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Mask input
|
|
30
|
+
* https://imask.js.org/
|
|
31
|
+
* @param props Props
|
|
32
|
+
* @returns Component
|
|
33
|
+
*/
|
|
34
|
+
export declare function MaskInput<T extends IMask.AnyMaskedOptions = IMask.AnyMaskedOptions>(props: MaskInputProps<T>): JSX.Element;
|
package/lib/MaskInput.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { TextField } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { MUGlobal } from './MUGlobal';
|
|
4
|
+
import { useIMask } from 'react-imask';
|
|
5
|
+
/**
|
|
6
|
+
* Mask input
|
|
7
|
+
* https://imask.js.org/
|
|
8
|
+
* @param props Props
|
|
9
|
+
* @returns Component
|
|
10
|
+
*/
|
|
11
|
+
export function MaskInput(props) {
|
|
12
|
+
// Destruct
|
|
13
|
+
const { defaultValue, mask, InputLabelProps = {}, InputProps = {}, onAccept, onComplete, readOnly, search = false, size = search ? MUGlobal.searchFieldSize : MUGlobal.inputFieldSize, value, variant = search
|
|
14
|
+
? MUGlobal.searchFieldVariant
|
|
15
|
+
: MUGlobal.inputFieldVariant, ...rest } = props;
|
|
16
|
+
const { ref, maskRef } = useIMask(mask, {
|
|
17
|
+
onAccept: (value, maskRef, event) => {
|
|
18
|
+
if (onAccept)
|
|
19
|
+
onAccept(value, maskRef, event);
|
|
20
|
+
},
|
|
21
|
+
onComplete: (value, maskRef, event) => {
|
|
22
|
+
if (onComplete)
|
|
23
|
+
onComplete(value, maskRef, event);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
const localValue = defaultValue !== null && defaultValue !== void 0 ? defaultValue : value;
|
|
27
|
+
// Shrink
|
|
28
|
+
InputLabelProps.shrink = search
|
|
29
|
+
? MUGlobal.searchFieldShrink
|
|
30
|
+
: MUGlobal.inputFieldShrink;
|
|
31
|
+
// Read only
|
|
32
|
+
if (readOnly != null)
|
|
33
|
+
InputProps.readOnly = readOnly;
|
|
34
|
+
InputProps.inputRef = ref;
|
|
35
|
+
React.useEffect(() => {
|
|
36
|
+
if (maskRef.current == null || localValue == null)
|
|
37
|
+
return;
|
|
38
|
+
maskRef.current.value = String(localValue);
|
|
39
|
+
maskRef.current.updateValue();
|
|
40
|
+
}, [maskRef.current, localValue]);
|
|
41
|
+
// Layout
|
|
42
|
+
return (React.createElement(TextField, { InputLabelProps: InputLabelProps, InputProps: InputProps, size: size, variant: variant, ...rest }));
|
|
43
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ListItemReact } from '@etsoo/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { ScrollerListExInnerItemRendererProps } from './ScrollerListEx';
|
|
4
|
+
/**
|
|
5
|
+
* Default mobile list item renderer
|
|
6
|
+
* @param param0 List renderer props
|
|
7
|
+
* @param margin Margin
|
|
8
|
+
* @param renderer Renderer for card content
|
|
9
|
+
* @returns Component
|
|
10
|
+
*/
|
|
11
|
+
export declare function MobileListItemRenderer<T>({ data, itemHeight, margins }: ScrollerListExInnerItemRendererProps<T>, renderer: (data: T) => [
|
|
12
|
+
string,
|
|
13
|
+
string | undefined,
|
|
14
|
+
React.ReactNode | (ListItemReact | boolean)[],
|
|
15
|
+
React.ReactNode,
|
|
16
|
+
React.ReactNode?
|
|
17
|
+
]): JSX.Element;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Card, CardContent, CardHeader, LinearProgress } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { MoreFab } from './MoreFab';
|
|
4
|
+
/**
|
|
5
|
+
* Default mobile list item renderer
|
|
6
|
+
* @param param0 List renderer props
|
|
7
|
+
* @param margin Margin
|
|
8
|
+
* @param renderer Renderer for card content
|
|
9
|
+
* @returns Component
|
|
10
|
+
*/
|
|
11
|
+
export function MobileListItemRenderer({ data, itemHeight, margins }, renderer) {
|
|
12
|
+
// Loading
|
|
13
|
+
if (data == null)
|
|
14
|
+
return React.createElement(LinearProgress, null);
|
|
15
|
+
// Elements
|
|
16
|
+
const [title, subheader, actions, children, cardActions] = renderer(data);
|
|
17
|
+
return (React.createElement(Card, { sx: {
|
|
18
|
+
height: itemHeight,
|
|
19
|
+
...margins
|
|
20
|
+
} },
|
|
21
|
+
React.createElement(CardHeader, { sx: { paddingBottom: 0.5 }, action: Array.isArray(actions) ? (React.createElement(MoreFab, { iconButton: true, size: "small", anchorOrigin: {
|
|
22
|
+
vertical: 'bottom',
|
|
23
|
+
horizontal: 'right'
|
|
24
|
+
}, transformOrigin: {
|
|
25
|
+
vertical: 'top',
|
|
26
|
+
horizontal: 'right'
|
|
27
|
+
}, actions: actions })) : (actions), title: title, titleTypographyProps: { variant: 'body2' }, subheader: subheader, subheaderTypographyProps: { variant: 'caption' } }),
|
|
28
|
+
React.createElement(CardContent, { sx: {
|
|
29
|
+
paddingTop: 0,
|
|
30
|
+
paddingBottom: cardActions == null
|
|
31
|
+
? Reflect.get(margins, 'marginBottom')
|
|
32
|
+
: 0
|
|
33
|
+
} }, children),
|
|
34
|
+
cardActions));
|
|
35
|
+
}
|
package/lib/MoreFab.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { CustomFabProps } from './CustomFabProps';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { PaperProps, PopoverOrigin } from '@mui/material';
|
|
4
|
+
import { ListItemReact } from '@etsoo/react';
|
|
5
|
+
/**
|
|
6
|
+
* More fab props
|
|
7
|
+
*/
|
|
8
|
+
export interface MoreFabProps extends CustomFabProps {
|
|
9
|
+
/**
|
|
10
|
+
* Actions
|
|
11
|
+
*/
|
|
12
|
+
actions?: (ListItemReact | boolean)[];
|
|
13
|
+
/**
|
|
14
|
+
* Dray arrow
|
|
15
|
+
*/
|
|
16
|
+
drawArrow?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Main icon
|
|
19
|
+
*/
|
|
20
|
+
icon?: React.ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* Show as icon button
|
|
23
|
+
*/
|
|
24
|
+
iconButton?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* This is the point on the anchor where the popover's
|
|
27
|
+
* `anchorEl` will attach to
|
|
28
|
+
*/
|
|
29
|
+
anchorOrigin?: PopoverOrigin;
|
|
30
|
+
/**
|
|
31
|
+
* Props applied to the [`Paper`](/api/paper/) element.
|
|
32
|
+
* @default {}
|
|
33
|
+
*/
|
|
34
|
+
PaperProps?: Partial<PaperProps>;
|
|
35
|
+
/**
|
|
36
|
+
* This is the point on the popover which
|
|
37
|
+
* will attach to the anchor's origin
|
|
38
|
+
*/
|
|
39
|
+
transformOrigin?: PopoverOrigin;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* More fab
|
|
43
|
+
* @returns Component
|
|
44
|
+
*/
|
|
45
|
+
export declare function MoreFab(props: MoreFabProps): JSX.Element;
|