@onehat/ui 0.4.114 → 0.4.115
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/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { cloneElement, forwardRef, isValidElement, useRef } from 'react';
|
|
1
|
+
import { cloneElement, forwardRef, isValidElement, useContext, useRef } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Button,
|
|
4
4
|
ButtonText,
|
|
@@ -10,9 +10,12 @@ import addIconProps from '../../Functions/addIconProps.js';
|
|
|
10
10
|
import clsx from 'clsx';
|
|
11
11
|
import withComponent from '../Hoc/withComponent.js';
|
|
12
12
|
import withTooltip from '../Hoc/withTooltip.js';
|
|
13
|
+
import FormContext from '../Form/FormContext.js';
|
|
13
14
|
import _ from 'lodash';
|
|
14
15
|
|
|
15
16
|
const ButtonComponent = forwardRef((props, ref) => {
|
|
17
|
+
|
|
18
|
+
const formContext = useContext(FormContext);
|
|
16
19
|
let {
|
|
17
20
|
self,
|
|
18
21
|
text, // the text to display on the button
|
|
@@ -32,6 +35,16 @@ const ButtonComponent = forwardRef((props, ref) => {
|
|
|
32
35
|
propsToPass.onPress = propsToPass.handler; // alias
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
const {
|
|
39
|
+
disableOnInvalid,
|
|
40
|
+
...propsToPassWithoutDisableOnInvalid
|
|
41
|
+
} = propsToPass;
|
|
42
|
+
propsToPass = propsToPassWithoutDisableOnInvalid;
|
|
43
|
+
|
|
44
|
+
if (_.isNil(propsToPass.isDisabled) && disableOnInvalid && formContext && !formContext.isValid) {
|
|
45
|
+
propsToPass.isDisabled = true;
|
|
46
|
+
}
|
|
47
|
+
|
|
35
48
|
if (icon) {
|
|
36
49
|
if (isValidElement(icon)) {
|
|
37
50
|
if (_icon) {
|
|
@@ -64,8 +77,10 @@ const ButtonComponent = forwardRef((props, ref) => {
|
|
|
64
77
|
'flex',
|
|
65
78
|
'flex-row',
|
|
66
79
|
'items-center',
|
|
67
|
-
'disabled:opacity-40',
|
|
68
|
-
'disabled:cursor-not-allowed',
|
|
80
|
+
'data-[disabled=true]:opacity-40',
|
|
81
|
+
'data-[disabled=true]:cursor-not-allowed',
|
|
82
|
+
'web:disabled:opacity-40',
|
|
83
|
+
'web:disabled:cursor-not-allowed',
|
|
69
84
|
);
|
|
70
85
|
if (isExpandToFillVertical) {
|
|
71
86
|
// IMPORTANT! Otherwise the button will cut off the vertical content due to size classes automatically added by Gluestack (e.g. h-10)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useEffect, useCallback, useState, useRef, isValidElement, } from 'react';
|
|
1
|
+
import { useEffect, useCallback, useState, useRef, isValidElement, cloneElement, Children, } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
Box,
|
|
4
4
|
HStack,
|
|
@@ -59,6 +59,7 @@ import Xmark from '../Icons/Xmark.js';
|
|
|
59
59
|
import Check from '../Icons/Check.js';
|
|
60
60
|
import Footer from '../Layout/Footer.js';
|
|
61
61
|
import Label from '../Form/Label.js';
|
|
62
|
+
import FormContext from '../Form/FormContext.js';
|
|
62
63
|
import _ from 'lodash';
|
|
63
64
|
|
|
64
65
|
// TODO: memoize field Components
|
|
@@ -1119,6 +1120,42 @@ function Form(props) {
|
|
|
1119
1120
|
alert(errors.message);
|
|
1120
1121
|
}
|
|
1121
1122
|
},
|
|
1123
|
+
decorateAdditionalFooterItems = (elements) => {
|
|
1124
|
+
const decorateElement = (element) => {
|
|
1125
|
+
if (!isValidElement(element)) {
|
|
1126
|
+
return element;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
const
|
|
1130
|
+
elementProps = element.props || {},
|
|
1131
|
+
propsToInject = {};
|
|
1132
|
+
|
|
1133
|
+
if (elementProps.disableOnInvalid && !formState.isValid) {
|
|
1134
|
+
propsToInject.isDisabled = true;
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
if (typeof elementProps.onPress === 'function' && (elementProps.disableOnInvalid || elementProps.skipSubmit || elementProps.submitWithForm)) {
|
|
1138
|
+
const originalOnPress = elementProps.onPress;
|
|
1139
|
+
if (elementProps.skipSubmit) {
|
|
1140
|
+
propsToInject.onPress = () => originalOnPress();
|
|
1141
|
+
} else {
|
|
1142
|
+
propsToInject.onPress = (e) => handleSubmit(originalOnPress, onSubmitError)(e);
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
if (elementProps.children) {
|
|
1147
|
+
propsToInject.children = Children.map(elementProps.children, decorateElement);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
if (_.isEmpty(propsToInject)) {
|
|
1151
|
+
return element;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
return cloneElement(element, propsToInject);
|
|
1155
|
+
};
|
|
1156
|
+
|
|
1157
|
+
return Children.map(elements, decorateElement);
|
|
1158
|
+
},
|
|
1122
1159
|
doReset = (values) => {
|
|
1123
1160
|
reset(values);
|
|
1124
1161
|
if (onReset) {
|
|
@@ -1444,7 +1481,7 @@ function Form(props) {
|
|
|
1444
1481
|
}
|
|
1445
1482
|
footerItems =
|
|
1446
1483
|
<>
|
|
1447
|
-
{additionalFooterItems}
|
|
1484
|
+
{decorateAdditionalFooterItems(additionalFooterItems)}
|
|
1448
1485
|
{!additionalFooterItems && additionalFooterButtons && _.map(additionalFooterButtons, (props, ix) => {
|
|
1449
1486
|
let isDisabled = false;
|
|
1450
1487
|
if (props.disableOnInvalid) {
|
|
@@ -1597,7 +1634,8 @@ function Form(props) {
|
|
|
1597
1634
|
className += ' ' + props.className;
|
|
1598
1635
|
}
|
|
1599
1636
|
const scrollToTopAnchor = <Box ref={(el) => (ancillaryItemsRef.current[0] = el)} className="h-0" />;
|
|
1600
|
-
return <
|
|
1637
|
+
return <FormContext.Provider value={{ isValid: formState.isValid }}>
|
|
1638
|
+
<VStackNative
|
|
1601
1639
|
ref={formRef}
|
|
1602
1640
|
{...testProps(self)}
|
|
1603
1641
|
style={style}
|
|
@@ -1639,7 +1677,8 @@ function Form(props) {
|
|
|
1639
1677
|
{isFabVisible && fab}
|
|
1640
1678
|
|
|
1641
1679
|
</>}
|
|
1642
|
-
</VStackNative
|
|
1680
|
+
</VStackNative>
|
|
1681
|
+
</FormContext.Provider>;
|
|
1643
1682
|
}
|
|
1644
1683
|
|
|
1645
1684
|
// helper fns
|