@jobber/components-native 0.62.4 → 0.63.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/dist/package.json +2 -2
- package/dist/src/Glimmer/Glimmer.js +42 -0
- package/dist/src/Glimmer/Glimmer.shape.style.js +16 -0
- package/dist/src/Glimmer/Glimmer.size.style.js +9 -0
- package/dist/src/Glimmer/Glimmer.style.js +20 -0
- package/dist/src/Glimmer/index.js +1 -0
- package/dist/src/InputFieldWrapper/InputFieldWrapper.js +20 -2
- package/dist/src/InputFieldWrapper/InputFieldWrapper.style.js +22 -0
- package/dist/src/InputText/InputText.js +4 -3
- package/dist/src/index.js +6 -5
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/Glimmer/Glimmer.d.ts +31 -0
- package/dist/types/src/Glimmer/Glimmer.shape.style.d.ts +14 -0
- package/dist/types/src/Glimmer/Glimmer.size.style.d.ts +17 -0
- package/dist/types/src/Glimmer/Glimmer.style.d.ts +18 -0
- package/dist/types/src/Glimmer/index.d.ts +1 -0
- package/dist/types/src/InputFieldWrapper/InputFieldWrapper.d.ts +11 -1
- package/dist/types/src/InputFieldWrapper/InputFieldWrapper.style.d.ts +22 -0
- package/dist/types/src/InputText/InputText.d.ts +1 -1
- package/dist/types/src/index.d.ts +6 -5
- package/package.json +2 -2
- package/src/Glimmer/Glimmer.shape.style.ts +17 -0
- package/src/Glimmer/Glimmer.size.style.ts +10 -0
- package/src/Glimmer/Glimmer.style.ts +23 -0
- package/src/Glimmer/Glimmer.test.tsx +73 -0
- package/src/Glimmer/Glimmer.tsx +106 -0
- package/src/Glimmer/index.ts +1 -0
- package/src/InputFieldWrapper/InputFieldWrapper.style.ts +25 -0
- package/src/InputFieldWrapper/InputFieldWrapper.test.tsx +30 -0
- package/src/InputFieldWrapper/InputFieldWrapper.tsx +50 -1
- package/src/InputText/InputText.tsx +10 -1
- package/src/index.ts +6 -5
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React Native implementation of Atlantis",
|
|
6
6
|
"repository": {
|
|
@@ -84,5 +84,5 @@
|
|
|
84
84
|
"react-native-safe-area-context": "^4.5.2",
|
|
85
85
|
"react-native-svg": ">=12.0.0"
|
|
86
86
|
},
|
|
87
|
-
"gitHead": "
|
|
87
|
+
"gitHead": "15034baa004c4a11f17338b96d6f2678f3183d56"
|
|
88
88
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
2
|
+
import { Animated, Easing, View } from "react-native";
|
|
3
|
+
import Svg, { Defs, LinearGradient, Rect, Stop } from "react-native-svg";
|
|
4
|
+
import { shineWidth, styles } from "./Glimmer.style";
|
|
5
|
+
import { sizeStyles } from "./Glimmer.size.style";
|
|
6
|
+
import { shapeStyles } from "./Glimmer.shape.style";
|
|
7
|
+
import { tokens } from "../utils/design";
|
|
8
|
+
export const GLIMMER_TEST_ID = "ATL-Glimmer";
|
|
9
|
+
export const GLIMMER_SHINE_TEST_ID = "ATL-Glimmer-Shine";
|
|
10
|
+
export function Glimmer({ width, shape = "rectangle", size = "base", timing = "base", }) {
|
|
11
|
+
const leftPosition = useRef(new Animated.Value(-shineWidth)).current;
|
|
12
|
+
const [parentWidth, setParentWidth] = useState(0);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const shine = Animated.loop(Animated.timing(leftPosition, {
|
|
15
|
+
toValue: parentWidth + shineWidth,
|
|
16
|
+
duration: timing === "base"
|
|
17
|
+
? tokens["timing-loading--extended"]
|
|
18
|
+
: tokens["timing-loading"],
|
|
19
|
+
easing: Easing.ease,
|
|
20
|
+
useNativeDriver: true,
|
|
21
|
+
}));
|
|
22
|
+
shine.start();
|
|
23
|
+
return shine.stop;
|
|
24
|
+
}, [parentWidth]);
|
|
25
|
+
return (React.createElement(View, { style: [
|
|
26
|
+
styles.container,
|
|
27
|
+
sizeStyles[size],
|
|
28
|
+
shapeStyles[shape],
|
|
29
|
+
{ width },
|
|
30
|
+
], onLayout: getWidth, testID: GLIMMER_TEST_ID },
|
|
31
|
+
React.createElement(Animated.View, { style: [styles.shine, { transform: [{ translateX: leftPosition }] }], testID: GLIMMER_SHINE_TEST_ID },
|
|
32
|
+
React.createElement(Svg, null,
|
|
33
|
+
React.createElement(Defs, null,
|
|
34
|
+
React.createElement(LinearGradient, { id: "gradientShine", x1: 0, y1: 0.5, x2: 1, y2: 0.5 },
|
|
35
|
+
React.createElement(Stop, { offset: "0%", stopColor: tokens["color-surface--background"] }),
|
|
36
|
+
React.createElement(Stop, { offset: "50%", stopColor: tokens["color-surface"] }),
|
|
37
|
+
React.createElement(Stop, { offset: "100%", stopColor: tokens["color-surface--background"] }))),
|
|
38
|
+
React.createElement(Rect, { fill: "url(#gradientShine)", height: "100%", width: "100%" })))));
|
|
39
|
+
function getWidth(event) {
|
|
40
|
+
setParentWidth(event.nativeEvent.layout.width);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { StyleSheet } from "react-native";
|
|
2
|
+
import { tokens } from "../utils/design";
|
|
3
|
+
export const shapeStyles = StyleSheet.create({
|
|
4
|
+
rectangle: {
|
|
5
|
+
width: "100%",
|
|
6
|
+
},
|
|
7
|
+
square: {
|
|
8
|
+
width: "auto",
|
|
9
|
+
aspectRatio: 1 / 1,
|
|
10
|
+
},
|
|
11
|
+
circle: {
|
|
12
|
+
width: "auto",
|
|
13
|
+
aspectRatio: 1 / 1,
|
|
14
|
+
borderRadius: tokens["radius-circle"],
|
|
15
|
+
},
|
|
16
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { StyleSheet } from "react-native";
|
|
2
|
+
import { tokens } from "../utils/design";
|
|
3
|
+
export const sizeStyles = StyleSheet.create({
|
|
4
|
+
small: { height: tokens["space-small"] },
|
|
5
|
+
base: { height: tokens["space-base"] },
|
|
6
|
+
large: { height: tokens["space-large"] },
|
|
7
|
+
larger: { height: tokens["space-larger"] },
|
|
8
|
+
largest: { height: tokens["space-largest"] },
|
|
9
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { StyleSheet } from "react-native";
|
|
2
|
+
import { tokens } from "../utils/design";
|
|
3
|
+
export const shineWidth = tokens["space-largest"];
|
|
4
|
+
export const styles = StyleSheet.create({
|
|
5
|
+
container: {
|
|
6
|
+
backgroundColor: tokens["color-surface--background"],
|
|
7
|
+
overflow: "hidden",
|
|
8
|
+
position: "relative",
|
|
9
|
+
width: "100%",
|
|
10
|
+
height: tokens["space-base"],
|
|
11
|
+
borderRadius: tokens["radius-base"],
|
|
12
|
+
},
|
|
13
|
+
shine: {
|
|
14
|
+
position: "absolute",
|
|
15
|
+
top: 0,
|
|
16
|
+
left: 0,
|
|
17
|
+
width: shineWidth,
|
|
18
|
+
height: "100%",
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Glimmer";
|
|
@@ -6,15 +6,21 @@ import { styles } from "./InputFieldWrapper.style";
|
|
|
6
6
|
import { PrefixIcon, PrefixLabel } from "./components/Prefix/Prefix";
|
|
7
7
|
import { SuffixIcon, SuffixLabel } from "./components/Suffix/Suffix";
|
|
8
8
|
import { ClearAction } from "./components/ClearAction";
|
|
9
|
+
import { Glimmer } from "../Glimmer/Glimmer";
|
|
9
10
|
import { ErrorMessageWrapper } from "../ErrorMessageWrapper";
|
|
10
11
|
import { typographyStyles } from "../Typography";
|
|
11
12
|
import { Text } from "../Text";
|
|
12
|
-
|
|
13
|
+
import { ActivityIndicator } from "../ActivityIndicator";
|
|
14
|
+
export const INPUT_FIELD_WRAPPER_GLIMMERS_TEST_ID = "ATL-InputFieldWrapper-Glimmers";
|
|
15
|
+
export const INPUT_FIELD_WRAPPER_SPINNER_TEST_ID = "ATL-InputFieldWrapper-Spinner";
|
|
16
|
+
export function InputFieldWrapper({ invalid, disabled, placeholder, assistiveText, prefix, suffix, hasMiniLabel = false, hasValue = false, error, focused = false, children, onClear, showClearAction = false, styleOverride, toolbar, toolbarVisibility = "while-editing", loading = false, loadingType = "spinner", }) {
|
|
13
17
|
fieldAffixRequiredPropsCheck([prefix, suffix]);
|
|
14
18
|
const handleClear = onClear !== null && onClear !== void 0 ? onClear : noopClear;
|
|
15
19
|
warnIfClearActionWithNoOnClear(onClear, showClearAction);
|
|
16
20
|
const inputInvalid = Boolean(invalid) || Boolean(error);
|
|
17
21
|
const isToolbarVisible = toolbar && (toolbarVisibility === "always" || focused);
|
|
22
|
+
const showLoadingSpinner = loading && loadingType === "spinner";
|
|
23
|
+
const showLoadingGlimmer = loading && loadingType === "glimmer";
|
|
18
24
|
return (React.createElement(ErrorMessageWrapper, { message: getMessage({ invalid, error }) },
|
|
19
25
|
React.createElement(View, { testID: "ATL-InputFieldWrapper", style: [
|
|
20
26
|
styles.container,
|
|
@@ -37,9 +43,21 @@ export function InputFieldWrapper({ invalid, disabled, placeholder, assistiveTex
|
|
|
37
43
|
React.createElement(Placeholder, { placeholder: placeholder, labelVariation: getLabelVariation(error, invalid, disabled), hasMiniLabel: hasMiniLabel, styleOverride: styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.placeholderText })),
|
|
38
44
|
(prefix === null || prefix === void 0 ? void 0 : prefix.label) && hasValue && (React.createElement(PrefixLabel, { disabled: disabled, focused: focused, hasMiniLabel: hasMiniLabel, inputInvalid: inputInvalid, label: prefix.label, styleOverride: styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.prefixLabel })),
|
|
39
45
|
children,
|
|
40
|
-
|
|
46
|
+
showLoadingGlimmer && (React.createElement(View, { testID: INPUT_FIELD_WRAPPER_GLIMMERS_TEST_ID, style: [
|
|
47
|
+
styles.loadingGlimmers,
|
|
48
|
+
hasValue && styles.loadingGlimmersHasValue,
|
|
49
|
+
] },
|
|
50
|
+
React.createElement(Glimmer, { size: "small", width: "80%" }),
|
|
51
|
+
React.createElement(Glimmer, { size: "small" }),
|
|
52
|
+
React.createElement(Glimmer, { size: "small", width: "70%" }))),
|
|
53
|
+
(showClearAction ||
|
|
54
|
+
(suffix === null || suffix === void 0 ? void 0 : suffix.label) ||
|
|
55
|
+
(suffix === null || suffix === void 0 ? void 0 : suffix.icon) ||
|
|
56
|
+
showLoadingSpinner) && (React.createElement(View, { style: styles.inputEndContainer },
|
|
41
57
|
showClearAction && (React.createElement(ClearAction, { hasMarginRight: !!(suffix === null || suffix === void 0 ? void 0 : suffix.icon) || !!(suffix === null || suffix === void 0 ? void 0 : suffix.label), onPress: handleClear })),
|
|
42
58
|
(suffix === null || suffix === void 0 ? void 0 : suffix.label) && hasValue && (React.createElement(SuffixLabel, { disabled: disabled, focused: focused, hasMiniLabel: hasMiniLabel, inputInvalid: inputInvalid, label: suffix.label, hasLeftMargin: !showClearAction, styleOverride: styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.suffixLabel })),
|
|
59
|
+
showLoadingSpinner && (React.createElement(View, { style: styles.loadingSpinner },
|
|
60
|
+
React.createElement(ActivityIndicator, { testID: INPUT_FIELD_WRAPPER_SPINNER_TEST_ID }))),
|
|
43
61
|
(suffix === null || suffix === void 0 ? void 0 : suffix.icon) && (React.createElement(SuffixIcon, { disabled: disabled, focused: focused, hasMiniLabel: hasMiniLabel, hasLeftMargin: !!(!showClearAction || (suffix === null || suffix === void 0 ? void 0 : suffix.label)), inputInvalid: inputInvalid, icon: suffix.icon, onPress: suffix.onPress })))))),
|
|
44
62
|
isToolbarVisible && React.createElement(View, { style: styles.toolbar }, toolbar)),
|
|
45
63
|
assistiveText && !error && !invalid && (React.createElement(Text, { level: "textSupporting", variation: disabled ? "disabled" : focused ? "interactive" : "subdued" }, assistiveText))));
|
|
@@ -89,8 +89,30 @@ export const styles = StyleSheet.create({
|
|
|
89
89
|
zIndex: 1,
|
|
90
90
|
},
|
|
91
91
|
toolbar: {
|
|
92
|
+
flexBasis: "100%",
|
|
92
93
|
flexDirection: "row",
|
|
93
94
|
gap: tokens["space-small"],
|
|
94
95
|
paddingBottom: tokens["space-small"],
|
|
95
96
|
},
|
|
97
|
+
loadingSpinner: {
|
|
98
|
+
justifyContent: "center",
|
|
99
|
+
paddingRight: tokens["space-small"],
|
|
100
|
+
},
|
|
101
|
+
loadingGlimmers: {
|
|
102
|
+
position: "absolute",
|
|
103
|
+
top: tokens["space-base"],
|
|
104
|
+
bottom: tokens["space-base"],
|
|
105
|
+
left: 0,
|
|
106
|
+
right: 0,
|
|
107
|
+
gap: tokens["space-small"],
|
|
108
|
+
paddingTop: tokens["space-small"],
|
|
109
|
+
paddingRight: tokens["space-large"],
|
|
110
|
+
backgroundColor: tokens["color-surface"],
|
|
111
|
+
overflow: "hidden",
|
|
112
|
+
},
|
|
113
|
+
loadingGlimmersHasValue: {
|
|
114
|
+
top: tokens["space-large"],
|
|
115
|
+
paddingTop: tokens["space-base"] - tokens["space-smaller"],
|
|
116
|
+
bottom: tokens["space-smaller"],
|
|
117
|
+
},
|
|
96
118
|
});
|
|
@@ -9,7 +9,7 @@ import { InputFieldWrapper } from "../InputFieldWrapper";
|
|
|
9
9
|
import { commonInputStyles } from "../InputFieldWrapper/CommonInputStyles.style";
|
|
10
10
|
export const InputText = forwardRef(InputTextInternal);
|
|
11
11
|
// eslint-disable-next-line max-statements
|
|
12
|
-
function InputTextInternal({ invalid, disabled, readonly = false, name, placeholder, assistiveText, keyboard, value: controlledValue, defaultValue, autoFocus, autoComplete = "off", spellCheck, textContentType = "none", validations, onChangeText, onSubmitEditing, onFocus, accessibilityLabel, accessibilityHint, autoCorrect, autoCapitalize, onBlur, multiline = false, prefix, suffix, transform = {}, clearable = multiline ? "never" : "while-editing", testID, secureTextEntry, styleOverride, toolbar, toolbarVisibility, }, ref) {
|
|
12
|
+
function InputTextInternal({ invalid, disabled, readonly = false, name, placeholder, assistiveText, keyboard, value: controlledValue, defaultValue, autoFocus, autoComplete = "off", spellCheck, textContentType = "none", validations, onChangeText, onSubmitEditing, onFocus, accessibilityLabel, accessibilityHint, autoCorrect, autoCapitalize, onBlur, multiline = false, prefix, suffix, transform = {}, clearable = multiline ? "never" : "while-editing", testID, secureTextEntry, styleOverride, toolbar, toolbarVisibility, loading, loadingType, }, ref) {
|
|
13
13
|
var _a;
|
|
14
14
|
const isAndroid = Platform.OS === "android";
|
|
15
15
|
const isIOS = Platform.OS === "ios";
|
|
@@ -72,7 +72,7 @@ function InputTextInternal({ invalid, disabled, readonly = false, name, placehol
|
|
|
72
72
|
}
|
|
73
73
|
onFocusNext();
|
|
74
74
|
}
|
|
75
|
-
return (React.createElement(InputFieldWrapper, { prefix: prefix, suffix: suffix, hasValue: hasValue, hasMiniLabel: hasMiniLabel, assistiveText: assistiveText, focused: focused, error: error, invalid: invalid, placeholder: placeholder, disabled: disabled, onClear: handleClear, showClearAction: showClear, styleOverride: styleOverride, toolbar: toolbar, toolbarVisibility: toolbarVisibility },
|
|
75
|
+
return (React.createElement(InputFieldWrapper, { prefix: prefix, suffix: suffix, hasValue: hasValue, hasMiniLabel: hasMiniLabel, assistiveText: assistiveText, focused: focused, error: error, invalid: invalid, placeholder: placeholder, disabled: disabled, onClear: handleClear, showClearAction: showClear, styleOverride: styleOverride, toolbar: toolbar, toolbarVisibility: toolbarVisibility, loading: loading, loadingType: loadingType },
|
|
76
76
|
React.createElement(TextInput, Object.assign({ inputAccessoryViewID: inputAccessoryID || undefined, testID: testID, autoCapitalize: autoCapitalize, autoCorrect: autoCorrect, spellCheck: spellCheck, style: [
|
|
77
77
|
commonInputStyles.input,
|
|
78
78
|
styles.inputPaddingTop,
|
|
@@ -82,9 +82,10 @@ function InputTextInternal({ invalid, disabled, readonly = false, name, placehol
|
|
|
82
82
|
multiline && Platform.OS === "ios" && styles.multilineInputiOS,
|
|
83
83
|
multiline && hasMiniLabel && styles.multiLineInputWithMini,
|
|
84
84
|
styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.inputText,
|
|
85
|
+
loading && loadingType === "glimmer" && { color: "transparent" },
|
|
85
86
|
],
|
|
86
87
|
// @ts-expect-error - does exist on 0.71 and up https://github.com/facebook/react-native/pull/39281
|
|
87
|
-
readOnly: readonly, editable: !disabled, keyboardType: keyboard, value: inputTransform(internalValue), autoFocus: autoFocus, autoComplete: autoComplete, multiline: multiline, scrollEnabled: false, textContentType: textContentType, onChangeText: handleChangeText, onSubmitEditing: handleOnSubmitEditing, returnKeyType: returnKeyType, blurOnSubmit: shouldBlurOnSubmit, accessibilityLabel: accessibilityLabel || placeholder, accessibilityHint: accessibilityHint, secureTextEntry: secureTextEntry }, androidA11yProps, { onFocus: event => {
|
|
88
|
+
readOnly: readonly, editable: !disabled, keyboardType: keyboard, value: inputTransform(internalValue), autoFocus: autoFocus, autoComplete: autoComplete, multiline: multiline, scrollEnabled: false, textContentType: textContentType, onChangeText: handleChangeText, onSubmitEditing: handleOnSubmitEditing, returnKeyType: returnKeyType, blurOnSubmit: shouldBlurOnSubmit, accessibilityLabel: accessibilityLabel || placeholder, accessibilityHint: accessibilityHint, accessibilityState: { busy: loading }, secureTextEntry: secureTextEntry }, androidA11yProps, { onFocus: event => {
|
|
88
89
|
_name && setFocusedInput(_name);
|
|
89
90
|
setFocused(true);
|
|
90
91
|
onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
|
package/dist/src/index.js
CHANGED
|
@@ -17,29 +17,30 @@ export * from "./Divider";
|
|
|
17
17
|
export * from "./EmptyState";
|
|
18
18
|
export * from "./ErrorMessageWrapper";
|
|
19
19
|
export * from "./Flex";
|
|
20
|
-
export * from "./FormatFile";
|
|
21
20
|
export * from "./Form";
|
|
21
|
+
export * from "./FormatFile";
|
|
22
22
|
export * from "./FormField";
|
|
23
|
+
export * from "./Glimmer";
|
|
23
24
|
export * from "./Heading";
|
|
24
25
|
export * from "./Icon";
|
|
25
26
|
export * from "./IconButton";
|
|
26
|
-
export * from "./InputFieldWrapper";
|
|
27
27
|
export * from "./InputCurrency";
|
|
28
28
|
export * from "./InputDate";
|
|
29
29
|
export * from "./InputEmail";
|
|
30
|
+
export * from "./InputFieldWrapper";
|
|
30
31
|
export * from "./InputNumber";
|
|
31
32
|
export * from "./InputPassword";
|
|
32
33
|
export * from "./InputPressable";
|
|
33
34
|
export * from "./InputSearch";
|
|
34
|
-
export * from "./InputTime";
|
|
35
35
|
export * from "./InputText";
|
|
36
|
+
export * from "./InputTime";
|
|
36
37
|
export * from "./Menu";
|
|
37
|
-
export * from "./TextList";
|
|
38
|
-
export * from "./ThumbnailList";
|
|
39
38
|
export * from "./ProgressBar";
|
|
40
39
|
export * from "./Select";
|
|
41
40
|
export * from "./StatusLabel";
|
|
42
41
|
export * from "./Switch";
|
|
43
42
|
export * from "./Text";
|
|
43
|
+
export * from "./TextList";
|
|
44
|
+
export * from "./ThumbnailList";
|
|
44
45
|
export * from "./Toast";
|
|
45
46
|
export * from "./Typography";
|