@wq/material-native 2.0.0-alpha.0
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 +29 -0
- package/babel.config.cjs +10 -0
- package/jest.config.js +9 -0
- package/package.json +58 -0
- package/setup-jest.js +5 -0
- package/src/App.js +48 -0
- package/src/components/Breadcrumbs.js +3 -0
- package/src/components/Button.js +46 -0
- package/src/components/ButtonLink.js +14 -0
- package/src/components/CancelButton.js +3 -0
- package/src/components/CheckboxButton.js +3 -0
- package/src/components/Chip.js +67 -0
- package/src/components/Container.js +3 -0
- package/src/components/DeleteForm.js +64 -0
- package/src/components/Divider.js +3 -0
- package/src/components/ExpandableListItem.js +46 -0
- package/src/components/ExpansionPanel.js +22 -0
- package/src/components/Fab.js +29 -0
- package/src/components/Fieldset.js +3 -0
- package/src/components/FieldsetArray.js +21 -0
- package/src/components/FileArray.js +3 -0
- package/src/components/FlatFieldset.js +3 -0
- package/src/components/Footer.js +3 -0
- package/src/components/FooterContent.js +3 -0
- package/src/components/FormError.js +15 -0
- package/src/components/FormRoot.js +3 -0
- package/src/components/FormatJson.js +15 -0
- package/src/components/Header.js +22 -0
- package/src/components/HomeLink.js +3 -0
- package/src/components/HorizontalView.js +22 -0
- package/src/components/IconButton.js +32 -0
- package/src/components/IconSubmitButton.js +12 -0
- package/src/components/Link.js +15 -0
- package/src/components/List.js +3 -0
- package/src/components/ListItem.js +22 -0
- package/src/components/ListItemLink.js +13 -0
- package/src/components/ListSubheader.js +3 -0
- package/src/components/Main.js +3 -0
- package/src/components/Pagination.js +3 -0
- package/src/components/Popup.js +3 -0
- package/src/components/RadioButton.js +3 -0
- package/src/components/ScrollView.js +22 -0
- package/src/components/SidePanel.js +3 -0
- package/src/components/Spinner.js +16 -0
- package/src/components/SubmitButton.js +17 -0
- package/src/components/Switch.js +3 -0
- package/src/components/Table.js +3 -0
- package/src/components/TableBody.js +3 -0
- package/src/components/TableCell.js +3 -0
- package/src/components/TableContainer.js +2 -0
- package/src/components/TableHead.js +3 -0
- package/src/components/TablePagination.js +3 -0
- package/src/components/TableRow.js +3 -0
- package/src/components/TableTitle.js +3 -0
- package/src/components/Text.js +3 -0
- package/src/components/Typography.js +39 -0
- package/src/components/View.js +3 -0
- package/src/components/index.js +119 -0
- package/src/hooks.js +6 -0
- package/src/icons.js +9 -0
- package/src/index.js +45 -0
- package/src/inputs/Checkbox.js +38 -0
- package/src/inputs/DateTime.js +61 -0
- package/src/inputs/File.js +3 -0
- package/src/inputs/HelperText.js +3 -0
- package/src/inputs/Hidden.js +22 -0
- package/src/inputs/Image.js +3 -0
- package/src/inputs/Input.js +72 -0
- package/src/inputs/Radio.js +3 -0
- package/src/inputs/Select.js +52 -0
- package/src/inputs/Toggle.js +3 -0
- package/src/inputs/date-utils.js +21 -0
- package/src/inputs/index.js +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[![@wq/material][logo]][docs]
|
|
2
|
+
|
|
3
|
+
**@wq/material-native** provides [React Native] and [Expo] bindings for [@wq/material], via the [React Native Paper] library.
|
|
4
|
+
|
|
5
|
+
### [Documentation][docs]
|
|
6
|
+
|
|
7
|
+
[**Installation**][installation]
|
|
8
|
+
•
|
|
9
|
+
[**API**][api]
|
|
10
|
+
•
|
|
11
|
+
[**Components**][components]
|
|
12
|
+
•
|
|
13
|
+
[Icons][icons]
|
|
14
|
+
•
|
|
15
|
+
[Inputs][inputs]
|
|
16
|
+
|
|
17
|
+
[logo]: https://wq.io/images/@wq/material.svg
|
|
18
|
+
[docs]: https://wq.io/@wq/material
|
|
19
|
+
[installation]: https://wq.io/@wq/material#installation
|
|
20
|
+
[api]: https://wq.io/@wq/material#api
|
|
21
|
+
[components]: https://wq.io/components/
|
|
22
|
+
[icons]: https://wq.io/icons
|
|
23
|
+
[inputs]: https://wq.io/inputs/
|
|
24
|
+
|
|
25
|
+
[@wq/material]: https://wq.io/@wq/material
|
|
26
|
+
[React]: https://reactjs.org/
|
|
27
|
+
[React Native]: https://reactnative.dev/
|
|
28
|
+
[Expo]: https://expo.io/
|
|
29
|
+
[React Native Paper]: https://callstack.github.io/react-native-paper/
|
package/babel.config.cjs
ADDED
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wq/material-native",
|
|
3
|
+
"version": "2.0.0-alpha.0",
|
|
4
|
+
"description": "React Native and Expo bindings for @wq/material",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "cd ../../ && npm run jest packages/material-native -- --config packages/material-native/jest.config.js --moduleDirectories node_modules/ packages/material-native/node_modules/",
|
|
9
|
+
"build": "npm run prettier",
|
|
10
|
+
"prettier": "cd ../../ && npm run prettier -- --write packages/material-native/",
|
|
11
|
+
"lint": "cd ../../ && npm run eslint packages/material-native/{,src/,src/*/,src/*/*/}*.js"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/wq/wq.app.git",
|
|
16
|
+
"directory": "packages/material-native"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"wq",
|
|
20
|
+
"react",
|
|
21
|
+
"material",
|
|
22
|
+
"material-ui"
|
|
23
|
+
],
|
|
24
|
+
"author": "S. Andrew Sheppard",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/wq/wq.app/issues"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://wq.io/@wq/material",
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@wq/react": "^2.0.0-alpha.0",
|
|
32
|
+
"date-fns": "^2.29.3"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@react-native-async-storage/async-storage": "*",
|
|
36
|
+
"@react-native-community/datetimepicker": "*",
|
|
37
|
+
"@react-native-community/masked-view": "*",
|
|
38
|
+
"@react-native-community/netinfo": "*",
|
|
39
|
+
"@react-navigation/native": "*",
|
|
40
|
+
"@react-navigation/stack": "*",
|
|
41
|
+
"react-native-modal-datetime-picker": "*",
|
|
42
|
+
"react-native-paper": "*",
|
|
43
|
+
"react-native-picker-select": "*"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@react-native-async-storage/async-storage": "^1.17.11",
|
|
47
|
+
"@react-native-community/datetimepicker": "^6.7.1",
|
|
48
|
+
"@react-native-community/masked-view": "^0.1.11",
|
|
49
|
+
"@react-native-community/netinfo": "^9.3.7",
|
|
50
|
+
"@react-navigation/native": "^6.1.2",
|
|
51
|
+
"@react-navigation/stack": "^6.3.11",
|
|
52
|
+
"@wq/model": "^2.0.0-alpha.0",
|
|
53
|
+
"@wq/store": "^2.0.0-alpha.0",
|
|
54
|
+
"react-native-modal-datetime-picker": "^14.0.1",
|
|
55
|
+
"react-native-paper": "^5.1.3",
|
|
56
|
+
"react-native-picker-select": "^8.0.4"
|
|
57
|
+
}
|
|
58
|
+
}
|
package/setup-jest.js
ADDED
package/src/App.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React, { useMemo } from "react";
|
|
2
|
+
import { App as DefaultApp, usePlugin } from "@wq/react";
|
|
3
|
+
import {
|
|
4
|
+
DefaultTheme,
|
|
5
|
+
DarkTheme,
|
|
6
|
+
Provider as PaperProvider,
|
|
7
|
+
} from "react-native-paper";
|
|
8
|
+
|
|
9
|
+
export default function App() {
|
|
10
|
+
const { theme: configTheme } = usePlugin("material").config,
|
|
11
|
+
theme = useMemo(() => createTheme(configTheme), [configTheme]),
|
|
12
|
+
options = useMemo(
|
|
13
|
+
() => ({
|
|
14
|
+
navigator: { theme },
|
|
15
|
+
screen: {
|
|
16
|
+
cardStyle: { backgroundColor: theme.colors.background },
|
|
17
|
+
},
|
|
18
|
+
}),
|
|
19
|
+
[theme]
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<PaperProvider theme={theme}>
|
|
24
|
+
<DefaultApp options={options} />
|
|
25
|
+
</PaperProvider>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function createTheme({ type, primary, secondary, background }) {
|
|
30
|
+
const colors = {},
|
|
31
|
+
base = type === "dark" ? DarkTheme : DefaultTheme;
|
|
32
|
+
if (primary) {
|
|
33
|
+
colors.primary = primary;
|
|
34
|
+
}
|
|
35
|
+
if (secondary) {
|
|
36
|
+
colors.accent = secondary;
|
|
37
|
+
}
|
|
38
|
+
if (background) {
|
|
39
|
+
colors.background = background;
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
...base,
|
|
43
|
+
colors: {
|
|
44
|
+
...base.colors,
|
|
45
|
+
...colors,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useIcon } from "@wq/react";
|
|
3
|
+
import { Button as PaperButton, useTheme } from "react-native-paper";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
export default function Button({
|
|
7
|
+
onClick,
|
|
8
|
+
onPress,
|
|
9
|
+
variant,
|
|
10
|
+
mode,
|
|
11
|
+
icon,
|
|
12
|
+
color,
|
|
13
|
+
...rest
|
|
14
|
+
}) {
|
|
15
|
+
const Icon = useIcon(icon),
|
|
16
|
+
theme = useTheme();
|
|
17
|
+
if (!onPress) {
|
|
18
|
+
onPress = onClick;
|
|
19
|
+
}
|
|
20
|
+
if (!mode) {
|
|
21
|
+
mode = variant;
|
|
22
|
+
}
|
|
23
|
+
if (color === "primary") {
|
|
24
|
+
color = theme.colors.primary;
|
|
25
|
+
} else if (color === "secondary") {
|
|
26
|
+
color = theme.colors.accent;
|
|
27
|
+
}
|
|
28
|
+
return (
|
|
29
|
+
<PaperButton
|
|
30
|
+
onPress={onPress}
|
|
31
|
+
mode={mode}
|
|
32
|
+
icon={Icon}
|
|
33
|
+
color={color}
|
|
34
|
+
{...rest}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
Button.propTypes = {
|
|
40
|
+
onClick: PropTypes.func,
|
|
41
|
+
onPress: PropTypes.func,
|
|
42
|
+
variant: PropTypes.string,
|
|
43
|
+
mode: PropTypes.string,
|
|
44
|
+
icon: PropTypes.string,
|
|
45
|
+
color: PropTypes.string,
|
|
46
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Button } from "react-native-paper";
|
|
3
|
+
import { useNav } from "@wq/react";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
export default function ButtonLink({ to, children }) {
|
|
7
|
+
const onPress = useNav(to);
|
|
8
|
+
return <Button onPress={onPress}>{children}</Button>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
ButtonLink.propTypes = {
|
|
12
|
+
to: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
|
13
|
+
children: PropTypes.node,
|
|
14
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useIcon } from "@wq/react";
|
|
3
|
+
import { Chip as PaperChip, useTheme } from "react-native-paper";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
export default function Chip({
|
|
7
|
+
label,
|
|
8
|
+
icon,
|
|
9
|
+
color,
|
|
10
|
+
onClick,
|
|
11
|
+
onPress,
|
|
12
|
+
onDelete,
|
|
13
|
+
onClose,
|
|
14
|
+
...rest
|
|
15
|
+
}) {
|
|
16
|
+
const theme = useTheme(),
|
|
17
|
+
Icon = useIcon(icon);
|
|
18
|
+
|
|
19
|
+
if (color === "primary") {
|
|
20
|
+
color = theme.colors.primary;
|
|
21
|
+
} else if (color === "secondary") {
|
|
22
|
+
color = theme.colors.accent;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let style, chipTheme;
|
|
26
|
+
if (color) {
|
|
27
|
+
style = {
|
|
28
|
+
backgroundColor: color,
|
|
29
|
+
};
|
|
30
|
+
chipTheme = {
|
|
31
|
+
colors: {
|
|
32
|
+
text: "#ffffff",
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (!onPress) {
|
|
38
|
+
onPress = onClick;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (!onClose) {
|
|
42
|
+
onClose = onDelete;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<PaperChip
|
|
47
|
+
icon={Icon}
|
|
48
|
+
style={style}
|
|
49
|
+
theme={chipTheme}
|
|
50
|
+
onPress={onPress}
|
|
51
|
+
onClose={onClose}
|
|
52
|
+
{...rest}
|
|
53
|
+
>
|
|
54
|
+
{label}
|
|
55
|
+
</PaperChip>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
Chip.propTypes = {
|
|
60
|
+
label: PropTypes.node,
|
|
61
|
+
icon: PropTypes.string,
|
|
62
|
+
color: PropTypes.string,
|
|
63
|
+
onClick: PropTypes.func,
|
|
64
|
+
onPress: PropTypes.func,
|
|
65
|
+
onDelete: PropTypes.func,
|
|
66
|
+
onClose: PropTypes.func,
|
|
67
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import Alert from "react-native";
|
|
3
|
+
import { useComponents, useMessages } from "@wq/react";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
export default function DeleteForm({ action }) {
|
|
7
|
+
const { Form, SubmitButton, View, HorizontalView } = useComponents(),
|
|
8
|
+
{
|
|
9
|
+
CONFIRM_DELETE,
|
|
10
|
+
CONFIRM_DELETE_TITLE,
|
|
11
|
+
CONFIRM_DELETE_OK,
|
|
12
|
+
CONFIRM_DELETE_CANCEL,
|
|
13
|
+
} = useMessages();
|
|
14
|
+
|
|
15
|
+
async function confirmSubmit() {
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
Alert.alert(
|
|
18
|
+
CONFIRM_DELETE_TITLE,
|
|
19
|
+
CONFIRM_DELETE,
|
|
20
|
+
[
|
|
21
|
+
{
|
|
22
|
+
text: CONFIRM_DELETE_CANCEL,
|
|
23
|
+
onPress() {
|
|
24
|
+
resolve(false);
|
|
25
|
+
},
|
|
26
|
+
style: "cancel",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
text: CONFIRM_DELETE_OK,
|
|
30
|
+
onPress() {
|
|
31
|
+
resolve(true);
|
|
32
|
+
},
|
|
33
|
+
style: "destructive",
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
{
|
|
37
|
+
onDismiss() {
|
|
38
|
+
resolve(false);
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<Form
|
|
47
|
+
action={action}
|
|
48
|
+
method="DELETE"
|
|
49
|
+
backgroundSync={false}
|
|
50
|
+
onSubmit={confirmSubmit}
|
|
51
|
+
>
|
|
52
|
+
<HorizontalView>
|
|
53
|
+
<View />
|
|
54
|
+
<SubmitButton icon="delete" variant="text" color="secondary">
|
|
55
|
+
Delete
|
|
56
|
+
</SubmitButton>
|
|
57
|
+
</HorizontalView>
|
|
58
|
+
</Form>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
DeleteForm.propTypes = {
|
|
63
|
+
action: PropTypes.string,
|
|
64
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { useIcon } from "@wq/react";
|
|
3
|
+
import { List } from "react-native-paper";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
export default function ExpandableListItem({
|
|
7
|
+
children,
|
|
8
|
+
description,
|
|
9
|
+
icon,
|
|
10
|
+
open,
|
|
11
|
+
onToggle,
|
|
12
|
+
...rest
|
|
13
|
+
}) {
|
|
14
|
+
const Icon = useIcon(icon),
|
|
15
|
+
[summary, ...details] = React.Children.toArray(children),
|
|
16
|
+
[internalOpen, setOpen] = useState(false);
|
|
17
|
+
|
|
18
|
+
let toggleOpen;
|
|
19
|
+
if (open === false || open || onToggle) {
|
|
20
|
+
toggleOpen = () => onToggle(!open);
|
|
21
|
+
} else {
|
|
22
|
+
open = internalOpen;
|
|
23
|
+
toggleOpen = () => setOpen(!open);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<List.Accordion
|
|
28
|
+
title={summary}
|
|
29
|
+
description={description}
|
|
30
|
+
left={Icon ? (props) => <List.Icon icon={Icon} {...props} /> : null}
|
|
31
|
+
expanded={open}
|
|
32
|
+
onPress={toggleOpen}
|
|
33
|
+
{...rest}
|
|
34
|
+
>
|
|
35
|
+
{details}
|
|
36
|
+
</List.Accordion>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
ExpandableListItem.propTypes = {
|
|
41
|
+
children: PropTypes.node,
|
|
42
|
+
description: PropTypes.node,
|
|
43
|
+
icon: PropTypes.string,
|
|
44
|
+
open: PropTypes.bool,
|
|
45
|
+
onToggle: PropTypes.func,
|
|
46
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { List } from "react-native-paper";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
|
|
5
|
+
export default function ExpansionPanel({ summary, children, open, onToggle }) {
|
|
6
|
+
let handleToggle;
|
|
7
|
+
if (onToggle) {
|
|
8
|
+
handleToggle = () => onToggle(!open);
|
|
9
|
+
}
|
|
10
|
+
return (
|
|
11
|
+
<List.Accordion title={summary} expanded={open} onPress={handleToggle}>
|
|
12
|
+
{children}
|
|
13
|
+
</List.Accordion>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
ExpansionPanel.propTypes = {
|
|
18
|
+
summary: PropTypes.node,
|
|
19
|
+
children: PropTypes.node,
|
|
20
|
+
open: PropTypes.bool,
|
|
21
|
+
onToggle: PropTypes.func,
|
|
22
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { FAB } from "react-native-paper";
|
|
3
|
+
import { useNav, useIcon } from "@wq/react";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
export default function Fab({ icon, to, ...rest }) {
|
|
7
|
+
const onPress = useNav(to),
|
|
8
|
+
Icon = useIcon(icon);
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<FAB
|
|
12
|
+
onPress={onPress}
|
|
13
|
+
icon={Icon}
|
|
14
|
+
color="white"
|
|
15
|
+
style={{
|
|
16
|
+
position: "absolute",
|
|
17
|
+
margin: 16,
|
|
18
|
+
right: 0,
|
|
19
|
+
bottom: 0,
|
|
20
|
+
}}
|
|
21
|
+
{...rest}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
Fab.propTypes = {
|
|
27
|
+
icon: PropTypes.string,
|
|
28
|
+
to: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
|
29
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useComponents } from "@wq/react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
|
|
5
|
+
export default function FieldsetArray({ label, children, addRow }) {
|
|
6
|
+
const { View, Button } = useComponents();
|
|
7
|
+
return (
|
|
8
|
+
<View>
|
|
9
|
+
{children}
|
|
10
|
+
{addRow && (
|
|
11
|
+
<Button onClick={() => addRow()}>{`Add ${label}`}</Button>
|
|
12
|
+
)}
|
|
13
|
+
</View>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
FieldsetArray.propTypes = {
|
|
18
|
+
label: PropTypes.string,
|
|
19
|
+
children: PropTypes.node,
|
|
20
|
+
addRow: PropTypes.func,
|
|
21
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useField } from "formik";
|
|
3
|
+
import { HelperText } from "react-native-paper";
|
|
4
|
+
|
|
5
|
+
export default function FormError(props) {
|
|
6
|
+
const [, { error }] = useField("__other__");
|
|
7
|
+
if (!error) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return (
|
|
11
|
+
<HelperText type="error" {...props}>
|
|
12
|
+
{error}
|
|
13
|
+
</HelperText>
|
|
14
|
+
);
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Text, ScrollView } from "react-native";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
|
|
5
|
+
export default function FormatJson({ json }) {
|
|
6
|
+
return (
|
|
7
|
+
<ScrollView style={{ height: 128 }}>
|
|
8
|
+
<Text>{JSON.stringify(json, null, 4)}</Text>
|
|
9
|
+
</ScrollView>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
FormatJson.propTypes = {
|
|
14
|
+
json: PropTypes.object,
|
|
15
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Appbar } from "react-native-paper";
|
|
3
|
+
import { useBreadcrumbs, useNav } from "@wq/react";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
export default function Header({ options, route }) {
|
|
7
|
+
const title = options.title || route.name,
|
|
8
|
+
breadcrumbs = useBreadcrumbs() || [],
|
|
9
|
+
previous = breadcrumbs[breadcrumbs.length - 2],
|
|
10
|
+
nav = useNav(previous?.url);
|
|
11
|
+
return (
|
|
12
|
+
<Appbar.Header>
|
|
13
|
+
{previous && <Appbar.BackAction onPress={nav} />}
|
|
14
|
+
<Appbar.Content title={title} />
|
|
15
|
+
</Appbar.Header>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Header.propTypes = {
|
|
20
|
+
options: PropTypes.object,
|
|
21
|
+
route: PropTypes.object,
|
|
22
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View } from "react-native";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
|
|
5
|
+
export default function HorizontalView({ style, ...rest }) {
|
|
6
|
+
return (
|
|
7
|
+
<View
|
|
8
|
+
style={{
|
|
9
|
+
flexDirection: "row",
|
|
10
|
+
justifyContent: "space-between",
|
|
11
|
+
alignItems: "center",
|
|
12
|
+
padding: 8,
|
|
13
|
+
...style,
|
|
14
|
+
}}
|
|
15
|
+
{...rest}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
HorizontalView.propTypes = {
|
|
21
|
+
style: PropTypes.object,
|
|
22
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useIcon } from "@wq/react";
|
|
3
|
+
import { IconButton as PaperIconButton, useTheme } from "react-native-paper";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
|
|
6
|
+
export default function IconButton({ icon, onClick, onPress, color, ...rest }) {
|
|
7
|
+
const Icon = useIcon(icon),
|
|
8
|
+
theme = useTheme();
|
|
9
|
+
if (!onPress) {
|
|
10
|
+
onPress = onClick;
|
|
11
|
+
}
|
|
12
|
+
if (color === "primary") {
|
|
13
|
+
color = theme.colors.primary;
|
|
14
|
+
} else if (color === "secondary") {
|
|
15
|
+
color = theme.colors.accent;
|
|
16
|
+
}
|
|
17
|
+
return (
|
|
18
|
+
<PaperIconButton
|
|
19
|
+
icon={Icon}
|
|
20
|
+
onPress={onPress}
|
|
21
|
+
color={color}
|
|
22
|
+
{...rest}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
IconButton.propTypes = {
|
|
28
|
+
icon: PropTypes.string,
|
|
29
|
+
onClick: PropTypes.func,
|
|
30
|
+
onPress: PropTypes.func,
|
|
31
|
+
color: PropTypes.string,
|
|
32
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { useComponents } from "@wq/react";
|
|
3
|
+
import { useFormikContext } from "formik";
|
|
4
|
+
|
|
5
|
+
export default function IconSubmitButton(props) {
|
|
6
|
+
const { IconButton } = useComponents(),
|
|
7
|
+
{ isSubmitting, submitForm } = useFormikContext();
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<IconButton disabled={isSubmitting} onPress={submitForm} {...props} />
|
|
11
|
+
);
|
|
12
|
+
}
|