@jobber/components-native 0.20.0 → 0.20.1-test-web-v.8

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.
Files changed (122) hide show
  1. package/dist/src/BottomSheet/BottomSheet.js +52 -0
  2. package/dist/src/BottomSheet/BottomSheet.style.js +28 -0
  3. package/dist/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.js +17 -0
  4. package/dist/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.styles.js +18 -0
  5. package/dist/src/BottomSheet/components/BottomSheetOption/index.js +1 -0
  6. package/dist/src/BottomSheet/index.js +1 -0
  7. package/dist/src/BottomSheet/messages.js +8 -0
  8. package/dist/src/EmptyState/EmptyState.js +24 -0
  9. package/dist/src/EmptyState/EmptyState.style.js +8 -0
  10. package/dist/src/EmptyState/index.js +1 -0
  11. package/dist/src/InputPressable/InputPressable.style.js +3 -3
  12. package/dist/src/InputText/InputText.js +138 -0
  13. package/dist/src/InputText/InputText.style.js +20 -0
  14. package/dist/src/InputText/context/InputAccessoriesContext.js +17 -0
  15. package/dist/src/InputText/context/InputAccessoriesProvider.js +73 -0
  16. package/dist/src/InputText/context/InputAccessoriesProvider.style.js +21 -0
  17. package/dist/src/InputText/context/InputAccessory.style.js +16 -0
  18. package/dist/src/InputText/context/index.js +2 -0
  19. package/dist/src/InputText/context/types.js +1 -0
  20. package/dist/src/InputText/index.js +2 -0
  21. package/dist/src/Switch/Switch.js +16 -0
  22. package/dist/src/Switch/Switch.styles.js +20 -0
  23. package/dist/src/Switch/components/BaseSwitch/BaseSwitch.js +54 -0
  24. package/dist/src/Switch/components/BaseSwitch/index.js +1 -0
  25. package/dist/src/Switch/index.js +1 -0
  26. package/dist/src/Toast/Toast.js +64 -0
  27. package/dist/src/Toast/Toast.styles.js +30 -0
  28. package/dist/src/Toast/index.js +1 -0
  29. package/dist/src/Toast/messages.js +13 -0
  30. package/dist/src/hooks/index.js +2 -0
  31. package/dist/src/hooks/useFormController.js +38 -0
  32. package/dist/src/hooks/useIsScreenReaderEnabled.js +22 -0
  33. package/dist/src/index.js +5 -0
  34. package/dist/src/utils/design/index.js +3 -3
  35. package/dist/src/utils/test/MockSafeAreaProvider.js +10 -0
  36. package/dist/src/utils/test/index.js +1 -0
  37. package/dist/src/utils/test/wait.js +58 -0
  38. package/dist/tsconfig.tsbuildinfo +1 -1
  39. package/dist/types/src/BottomSheet/BottomSheet.d.ts +28 -0
  40. package/dist/types/src/BottomSheet/BottomSheet.style.d.ts +32 -0
  41. package/dist/types/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.d.ts +13 -0
  42. package/dist/types/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.styles.d.ts +16 -0
  43. package/dist/types/src/BottomSheet/components/BottomSheetOption/index.d.ts +1 -0
  44. package/dist/types/src/BottomSheet/index.d.ts +1 -0
  45. package/dist/types/src/BottomSheet/messages.d.ts +7 -0
  46. package/dist/types/src/EmptyState/EmptyState.d.ts +35 -0
  47. package/dist/types/src/EmptyState/EmptyState.style.d.ts +6 -0
  48. package/dist/types/src/EmptyState/index.d.ts +2 -0
  49. package/dist/types/src/InputText/InputText.d.ts +165 -0
  50. package/dist/types/src/InputText/InputText.style.d.ts +16 -0
  51. package/dist/types/src/InputText/context/InputAccessoriesContext.d.ts +4 -0
  52. package/dist/types/src/InputText/context/InputAccessoriesProvider.d.ts +4 -0
  53. package/dist/types/src/InputText/context/InputAccessoriesProvider.style.d.ts +17 -0
  54. package/dist/types/src/InputText/context/InputAccessory.style.d.ts +14 -0
  55. package/dist/types/src/InputText/context/index.d.ts +2 -0
  56. package/dist/types/src/InputText/context/types.d.ts +23 -0
  57. package/dist/types/src/InputText/index.d.ts +3 -0
  58. package/dist/types/src/Switch/Switch.d.ts +16 -0
  59. package/dist/types/src/Switch/Switch.styles.d.ts +18 -0
  60. package/dist/types/src/Switch/components/BaseSwitch/BaseSwitch.d.ts +28 -0
  61. package/dist/types/src/Switch/components/BaseSwitch/index.d.ts +2 -0
  62. package/dist/types/src/Switch/index.d.ts +1 -0
  63. package/dist/types/src/Toast/Toast.d.ts +28 -0
  64. package/dist/types/src/Toast/Toast.styles.d.ts +31 -0
  65. package/dist/types/src/Toast/index.d.ts +2 -0
  66. package/dist/types/src/Toast/messages.d.ts +12 -0
  67. package/dist/types/src/hooks/index.d.ts +2 -0
  68. package/dist/types/src/hooks/useFormController.d.ts +12 -0
  69. package/dist/types/src/hooks/useIsScreenReaderEnabled.d.ts +1 -0
  70. package/dist/types/src/index.d.ts +5 -0
  71. package/dist/types/src/utils/design/index.d.ts +1 -1
  72. package/dist/types/src/utils/test/MockSafeAreaProvider.d.ts +9 -0
  73. package/dist/types/src/utils/test/index.d.ts +1 -0
  74. package/dist/types/src/utils/test/wait.d.ts +36 -0
  75. package/package.json +10 -4
  76. package/src/BottomSheet/BottomSheet.style.ts +35 -0
  77. package/src/BottomSheet/BottomSheet.test.tsx +152 -0
  78. package/src/BottomSheet/BottomSheet.tsx +149 -0
  79. package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.styles.ts +19 -0
  80. package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.test.tsx +34 -0
  81. package/src/BottomSheet/components/BottomSheetOption/BottomSheetOption.tsx +53 -0
  82. package/src/BottomSheet/components/BottomSheetOption/index.ts +1 -0
  83. package/src/BottomSheet/index.ts +1 -0
  84. package/src/BottomSheet/messages.ts +9 -0
  85. package/src/EmptyState/EmptyState.style.ts +9 -0
  86. package/src/EmptyState/EmptyState.test.tsx +108 -0
  87. package/src/EmptyState/EmptyState.tsx +91 -0
  88. package/src/EmptyState/index.ts +2 -0
  89. package/src/Flex/Flex.test.tsx +6 -6
  90. package/src/InputPressable/InputPressable.style.ts +3 -3
  91. package/src/InputText/InputText.style.ts +25 -0
  92. package/src/InputText/InputText.test.tsx +534 -0
  93. package/src/InputText/InputText.tsx +483 -0
  94. package/src/InputText/context/InputAccessoriesContext.ts +21 -0
  95. package/src/InputText/context/InputAccessoriesProvider.style.tsx +23 -0
  96. package/src/InputText/context/InputAccessoriesProvider.test.tsx +84 -0
  97. package/src/InputText/context/InputAccessoriesProvider.tsx +121 -0
  98. package/src/InputText/context/InputAccessory.style.ts +17 -0
  99. package/src/InputText/context/index.ts +2 -0
  100. package/src/InputText/context/types.ts +28 -0
  101. package/src/InputText/index.ts +3 -0
  102. package/src/Switch/Switch.styles.ts +21 -0
  103. package/src/Switch/Switch.test.tsx +98 -0
  104. package/src/Switch/Switch.tsx +58 -0
  105. package/src/Switch/components/BaseSwitch/BaseSwitch.test.tsx +62 -0
  106. package/src/Switch/components/BaseSwitch/BaseSwitch.tsx +107 -0
  107. package/src/Switch/components/BaseSwitch/__snapshots__/BaseSwitch.test.tsx.snap +217 -0
  108. package/src/Switch/components/BaseSwitch/index.ts +2 -0
  109. package/src/Switch/index.ts +1 -0
  110. package/src/Toast/Toast.styles.ts +31 -0
  111. package/src/Toast/Toast.test.tsx +74 -0
  112. package/src/Toast/Toast.tsx +128 -0
  113. package/src/Toast/index.ts +2 -0
  114. package/src/Toast/messages.ts +14 -0
  115. package/src/hooks/index.ts +2 -0
  116. package/src/hooks/useFormController.ts +68 -0
  117. package/src/hooks/useIsScreenReaderEnabled.ts +32 -0
  118. package/src/index.ts +5 -0
  119. package/src/utils/design/index.ts +4 -4
  120. package/src/utils/test/MockSafeAreaProvider.tsx +32 -0
  121. package/src/utils/test/index.ts +1 -0
  122. package/src/utils/test/wait.ts +52 -0
@@ -0,0 +1,52 @@
1
+ import React, { forwardRef, useState } from "react";
2
+ import { Modalize } from "react-native-modalize";
3
+ import { useSafeAreaInsets } from "react-native-safe-area-context";
4
+ import { Keyboard, View } from "react-native";
5
+ import { useIntl } from "react-intl";
6
+ import { BottomSheetOption } from "./components/BottomSheetOption";
7
+ import { styles } from "./BottomSheet.style";
8
+ import { messages } from "./messages";
9
+ import { useIsScreenReaderEnabled } from "../hooks";
10
+ import { Divider } from "../Divider";
11
+ import { Heading } from "../Heading";
12
+ export const BottomSheet = forwardRef(BottomSheetInternal);
13
+ function BottomSheetInternal({ children, showCancel, loading = false, heading, onOpen, onClose, }, ref) {
14
+ const isScreenReaderEnabled = useIsScreenReaderEnabled();
15
+ const [open, setOpen] = useState(false);
16
+ return (React.createElement(React.Fragment, null,
17
+ open && React.createElement(Overlay, null),
18
+ React.createElement(Modalize, { ref: ref, adjustToContentHeight: true, modalStyle: styles.modal, overlayStyle: styles.overlayModalize, HeaderComponent: heading && React.createElement(Header, { heading: heading }), FooterComponent: React.createElement(Footer, { cancellable: (showCancel && !loading) || isScreenReaderEnabled, onCancel: () => {
19
+ var _a;
20
+ (_a = ref === null || ref === void 0 ? void 0 : ref.current) === null || _a === void 0 ? void 0 : _a.close();
21
+ } }), withHandle: false, withReactModal: isScreenReaderEnabled, onOpen: openModal, onClose: closeModal },
22
+ React.createElement(View, { style: !showCancel && !isScreenReaderEnabled ? styles.children : undefined }, children))));
23
+ function openModal() {
24
+ onOpen === null || onOpen === void 0 ? void 0 : onOpen();
25
+ setOpen(true);
26
+ dismissKeyboard();
27
+ }
28
+ function closeModal() {
29
+ onClose === null || onClose === void 0 ? void 0 : onClose();
30
+ setOpen(false);
31
+ }
32
+ }
33
+ function Header({ heading }) {
34
+ return (React.createElement(View, { style: styles.header },
35
+ React.createElement(Heading, { level: "subtitle" }, heading)));
36
+ }
37
+ function Footer({ cancellable, onCancel, }) {
38
+ const insets = useSafeAreaInsets();
39
+ const { formatMessage } = useIntl();
40
+ return (React.createElement(View, { style: { marginBottom: insets.bottom } }, cancellable && (React.createElement(View, { style: styles.children },
41
+ React.createElement(View, { style: styles.footerDivider },
42
+ React.createElement(Divider, null)),
43
+ React.createElement(BottomSheetOption, { text: formatMessage(messages.cancel), icon: "remove", onPress: onCancel })))));
44
+ }
45
+ function dismissKeyboard() {
46
+ //Dismisses the keyboard before opening the bottom sheet.
47
+ //In the case where an input text field is focused we don't want to show the bottom sheet behind or above keyboard
48
+ Keyboard.dismiss();
49
+ }
50
+ function Overlay() {
51
+ return React.createElement(View, { style: styles.overlay });
52
+ }
@@ -0,0 +1,28 @@
1
+ import { Dimensions, StyleSheet } from "react-native";
2
+ import { tokens } from "../utils/design";
3
+ const { height } = Dimensions.get("window");
4
+ const modalBorderRadius = tokens["radius-larger"];
5
+ export const styles = StyleSheet.create({
6
+ overlayModalize: {
7
+ backgroundColor: "transparent",
8
+ },
9
+ overlay: Object.assign(Object.assign({}, StyleSheet.absoluteFillObject), { backgroundColor: tokens["color-overlay"], height }),
10
+ modal: {
11
+ borderTopLeftRadius: modalBorderRadius,
12
+ borderTopRightRadius: modalBorderRadius,
13
+ paddingTop: tokens["space-small"],
14
+ },
15
+ children: {
16
+ paddingBottom: tokens["space-small"],
17
+ },
18
+ header: {
19
+ paddingHorizontal: tokens["space-base"],
20
+ paddingTop: tokens["space-small"],
21
+ paddingBottom: tokens["space-base"],
22
+ },
23
+ footerDivider: {
24
+ marginHorizontal: tokens["space-base"],
25
+ marginTop: tokens["space-small"],
26
+ marginBottom: tokens["space-smaller"],
27
+ },
28
+ });
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+ import { TouchableOpacity, View } from "react-native";
3
+ import { styles } from "./BottomSheetOption.styles";
4
+ import { capitalize } from "../../../utils/intl";
5
+ import { Text } from "../../../Text";
6
+ import { Icon } from "../../../Icon";
7
+ export function BottomSheetOption({ text, icon, iconColor, textAlign, destructive, textTransform = "capitalize", onPress, }) {
8
+ const destructiveColor = "critical";
9
+ const textVariation = destructive ? destructiveColor : "subdued";
10
+ return (React.createElement(TouchableOpacity, { style: styles.bottomSheetOption, onPress: onPress, accessibilityLabel: text },
11
+ icon && (React.createElement(View, { style: styles.icon },
12
+ React.createElement(Icon, { name: icon, color: destructive ? destructiveColor : iconColor }))),
13
+ React.createElement(View, { style: styles.title },
14
+ React.createElement(Text, { variation: textVariation, emphasis: "strong", align: textAlign }, textTransform === "capitalize"
15
+ ? capitalize(text.toLocaleLowerCase())
16
+ : text))));
17
+ }
@@ -0,0 +1,18 @@
1
+ import { StyleSheet } from "react-native";
2
+ import { tokens } from "../../../utils/design";
3
+ export const styles = StyleSheet.create({
4
+ bottomSheetOption: {
5
+ display: "flex",
6
+ flexDirection: "row",
7
+ alignContent: "center",
8
+ alignItems: "center",
9
+ padding: tokens["space-small"],
10
+ },
11
+ icon: {
12
+ paddingHorizontal: tokens["space-small"],
13
+ },
14
+ title: {
15
+ paddingHorizontal: tokens["space-small"],
16
+ flexShrink: 1,
17
+ },
18
+ });
@@ -0,0 +1 @@
1
+ export { BottomSheetOption } from "./BottomSheetOption";
@@ -0,0 +1 @@
1
+ export { BottomSheet } from "./BottomSheet";
@@ -0,0 +1,8 @@
1
+ import { defineMessages } from "react-intl";
2
+ export const messages = defineMessages({
3
+ cancel: {
4
+ id: "cancel",
5
+ defaultMessage: "Cancel",
6
+ description: "Text for the cancel action",
7
+ },
8
+ });
@@ -0,0 +1,24 @@
1
+ import React from "react";
2
+ import { View } from "react-native";
3
+ import { styles } from "./EmptyState.style";
4
+ import { Text } from "../Text";
5
+ import { Content } from "../Content";
6
+ import { Icon } from "../Icon";
7
+ import { Heading } from "../Heading";
8
+ import { Button } from "../Button";
9
+ function ButtonAction({ action, type }) {
10
+ if (!action)
11
+ return React.createElement(React.Fragment, null);
12
+ return React.createElement(Button, Object.assign({ fullWidth: false, type: type }, action));
13
+ }
14
+ export function EmptyState({ icon, title, description, primaryAction, secondaryAction, iconColor = "blue", }) {
15
+ return (React.createElement(Content, null,
16
+ icon && (React.createElement(View, { style: styles.icon },
17
+ React.createElement(Icon, { name: icon, size: "large", color: iconColor }))),
18
+ React.createElement(Content, { spacing: "none", childSpacing: "small" },
19
+ title && (React.createElement(Heading, { level: "subHeading", align: "center" }, title)),
20
+ description && React.createElement(Text, { align: "center" }, description),
21
+ (primaryAction || secondaryAction) && (React.createElement(Content, { spacing: "none", childSpacing: "small" },
22
+ React.createElement(ButtonAction, { action: primaryAction, type: "primary" }),
23
+ React.createElement(ButtonAction, { action: secondaryAction, type: "tertiary" }))))));
24
+ }
@@ -0,0 +1,8 @@
1
+ import { StyleSheet } from "react-native";
2
+ import { tokens } from "../utils/design";
3
+ export const styles = StyleSheet.create({
4
+ icon: {
5
+ marginVertical: tokens["space-small"],
6
+ alignItems: "center",
7
+ },
8
+ });
@@ -0,0 +1 @@
1
+ export { EmptyState } from "./EmptyState";
@@ -1,8 +1,8 @@
1
- import { JobberStyle } from "@jobber/design/foundation";
1
+ import { tokens } from "@jobber/design/foundation";
2
2
  import { StyleSheet } from "react-native";
3
3
  import { typographyStyles } from "../Typography/Typography.style";
4
4
  const miniLabelFontSize = typographyStyles.smallSize.fontSize || 0;
5
- const miniLabelPadding = JobberStyle["space-small"];
5
+ const miniLabelPadding = tokens["space-small"];
6
6
  export const styles = StyleSheet.create({
7
7
  pressable: {
8
8
  flex: 1,
@@ -18,6 +18,6 @@ export const styles = StyleSheet.create({
18
18
  color: typographyStyles.disabled.color,
19
19
  },
20
20
  inputInvalid: {
21
- borderColor: JobberStyle["color-critical"],
21
+ borderColor: tokens["color-critical"],
22
22
  },
23
23
  });
@@ -0,0 +1,138 @@
1
+ import React, { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState, } from "react";
2
+ import { Platform, TextInput, } from "react-native";
3
+ import identity from "lodash.identity";
4
+ import { styles } from "./InputText.style";
5
+ import { useInputAccessoriesContext } from "./context";
6
+ import { useFormController } from "../hooks";
7
+ import { InputFieldWrapper, useShowClear, } from "../InputFieldWrapper";
8
+ import { commonInputStyles } from "../InputFieldWrapper/CommonInputStyles.style";
9
+ export const InputText = forwardRef(InputTextInternal);
10
+ // eslint-disable-next-line max-statements
11
+ function InputTextInternal({ invalid, disabled, 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, }, ref) {
12
+ var _a;
13
+ const isAndroid = Platform.OS === "android";
14
+ const { input: inputTransform = identity, output: outputTransform = identity, } = transform;
15
+ const { error, field } = useFormController({
16
+ name,
17
+ value: controlledValue !== null && controlledValue !== void 0 ? controlledValue : defaultValue,
18
+ validations,
19
+ });
20
+ const internalValue = controlledValue !== null && controlledValue !== void 0 ? controlledValue : (_a = field.value) === null || _a === void 0 ? void 0 : _a.toString();
21
+ const hasValue = internalValue !== "" && internalValue !== undefined;
22
+ const [focused, setFocused] = useState(false);
23
+ const { hasMiniLabel, setHasMiniLabel } = useMiniLabel(internalValue);
24
+ const textInputRef = useTextInputRef({ ref, onClear: handleClear });
25
+ const showClear = useShowClear({
26
+ clearable,
27
+ multiline,
28
+ focused,
29
+ hasValue,
30
+ disabled,
31
+ });
32
+ // Android doesn't have an accessibility label like iOS does. By adding
33
+ // it as a placeholder it readds it like a label. However we don't want to
34
+ // add a placeholder on iOS.
35
+ const androidA11yProps = Object.assign({}, (isAndroid && {
36
+ placeholder: accessibilityLabel || placeholder,
37
+ placeholderTextColor: "transparent",
38
+ }));
39
+ const _name = name !== null && name !== void 0 ? name : field.name;
40
+ const { inputAccessoryID, register, unregister, setFocusedInput, canFocusNext, onFocusNext, } = useInputAccessoriesContext();
41
+ useEffect(() => {
42
+ _name &&
43
+ register(_name, () => {
44
+ var _a;
45
+ (_a = textInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
46
+ });
47
+ return () => {
48
+ _name && unregister(_name);
49
+ };
50
+ }, [_name, register, textInputRef, unregister]);
51
+ const returnKeyType = useMemo(() => {
52
+ if (!multiline) {
53
+ if (inputAccessoryID && isAndroid) {
54
+ return "next";
55
+ }
56
+ else {
57
+ return "done";
58
+ }
59
+ }
60
+ else {
61
+ return undefined;
62
+ }
63
+ }, [multiline, inputAccessoryID, isAndroid]);
64
+ // If it's not inside an inputAcessoriesContext or cannot focus next,
65
+ // then hide the keyboard when the return key is pressed.
66
+ const shouldBlurOnSubmit = !multiline && (!inputAccessoryID || !canFocusNext || !isAndroid);
67
+ function handleOnFocusNext() {
68
+ if (multiline) {
69
+ return;
70
+ }
71
+ onFocusNext();
72
+ }
73
+ 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 },
74
+ React.createElement(TextInput, Object.assign({ inputAccessoryViewID: inputAccessoryID || undefined, testID: testID, autoCapitalize: autoCapitalize, autoCorrect: autoCorrect, spellCheck: spellCheck, style: [
75
+ commonInputStyles.input,
76
+ styles.inputPaddingTop,
77
+ !hasMiniLabel && commonInputStyles.inputEmpty,
78
+ disabled && commonInputStyles.inputDisabled,
79
+ multiline && Platform.OS === "ios" && styles.multilineInputiOS,
80
+ multiline && styles.multiLineInput,
81
+ multiline && hasMiniLabel && styles.multiLineInputWithMini,
82
+ styleOverride === null || styleOverride === void 0 ? void 0 : styleOverride.inputText,
83
+ ], 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 => {
84
+ _name && setFocusedInput(_name);
85
+ setFocused(true);
86
+ onFocus === null || onFocus === void 0 ? void 0 : onFocus(event);
87
+ }, onBlur: () => {
88
+ _name && setFocusedInput("");
89
+ setFocused(false);
90
+ onBlur === null || onBlur === void 0 ? void 0 : onBlur();
91
+ field.onBlur();
92
+ trimWhitespace(field, onChangeText);
93
+ }, ref: (instance) => {
94
+ // RHF wants us to do it this way
95
+ // https://react-hook-form.com/faqs#Howtosharerefusage
96
+ textInputRef.current = instance;
97
+ field.ref(instance);
98
+ } }))));
99
+ function handleChangeText(value) {
100
+ const newValue = outputTransform(value);
101
+ setHasMiniLabel(Boolean(newValue));
102
+ onChangeText === null || onChangeText === void 0 ? void 0 : onChangeText(newValue);
103
+ field.onChange(newValue);
104
+ }
105
+ function handleClear() {
106
+ handleChangeText("");
107
+ }
108
+ function handleOnSubmitEditing() {
109
+ onSubmitEditing === null || onSubmitEditing === void 0 ? void 0 : onSubmitEditing();
110
+ if (isAndroid) {
111
+ handleOnFocusNext();
112
+ }
113
+ }
114
+ }
115
+ function trimWhitespace(field, onChangeText) {
116
+ if (!field.value || !field.value.trim) {
117
+ return;
118
+ }
119
+ const trimmedInput = field.value.trim();
120
+ onChangeText === null || onChangeText === void 0 ? void 0 : onChangeText(trimmedInput);
121
+ field.onChange(trimmedInput);
122
+ }
123
+ function useTextInputRef({ ref, onClear }) {
124
+ const textInputRef = useRef(null);
125
+ useImperativeHandle(ref, () => ({
126
+ focus: () => { var _a; return (_a = textInputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); },
127
+ blur: () => { var _a; return (_a = textInputRef.current) === null || _a === void 0 ? void 0 : _a.blur(); },
128
+ clear: onClear,
129
+ }), [onClear]);
130
+ return textInputRef;
131
+ }
132
+ function useMiniLabel(internalValue) {
133
+ const [hasMiniLabel, setHasMiniLabel] = useState(Boolean(internalValue));
134
+ useEffect(() => {
135
+ setHasMiniLabel(Boolean(internalValue));
136
+ }, [internalValue]);
137
+ return { hasMiniLabel, setHasMiniLabel };
138
+ }
@@ -0,0 +1,20 @@
1
+ import { StyleSheet } from "react-native";
2
+ import { tokens } from "../utils/design";
3
+ import { typographyStyles } from "../Typography";
4
+ export const styles = StyleSheet.create({
5
+ inputPaddingTop: {
6
+ paddingTop: typographyStyles.smallSize.fontSize,
7
+ },
8
+ multiLineInput: {
9
+ paddingTop: tokens["space-base"] - tokens["space-smallest"],
10
+ paddingBottom: tokens["space-smaller"],
11
+ lineHeight: typographyStyles.defaultSize.lineHeight,
12
+ },
13
+ multiLineInputWithMini: {
14
+ paddingTop: tokens["space-large"],
15
+ },
16
+ multilineInputiOS: {
17
+ // for placeholder
18
+ paddingTop: (typographyStyles.smallSize.fontSize || 0) + tokens["space-smallest"],
19
+ },
20
+ });
@@ -0,0 +1,17 @@
1
+ import { createContext, useContext } from "react";
2
+ const defaultValues = {
3
+ elements: {},
4
+ focusedInput: "",
5
+ canFocusNext: false,
6
+ canFocusPrevious: false,
7
+ inputAccessoryID: undefined,
8
+ register: () => undefined,
9
+ unregister: () => undefined,
10
+ onFocusNext: () => undefined,
11
+ onFocusPrevious: () => undefined,
12
+ setFocusedInput: () => undefined,
13
+ };
14
+ export const InputAccessoriesContext = createContext(defaultValues);
15
+ export function useInputAccessoriesContext() {
16
+ return useContext(InputAccessoriesContext);
17
+ }
@@ -0,0 +1,73 @@
1
+ import React, { useEffect, useRef, useState } from "react";
2
+ import { InputAccessoryView, Keyboard, Platform,
3
+ // eslint-disable-next-line no-restricted-imports
4
+ Button as RNButton, View, useColorScheme, } from "react-native";
5
+ import { v4 } from "react-native-uuid";
6
+ import { InputAccessoriesContext } from "./InputAccessoriesContext";
7
+ import { styles } from "./InputAccessoriesProvider.style";
8
+ export function InputAccessoriesProvider({ children, }) {
9
+ const inputAccessoryID = useRef(v4()).current;
10
+ const { focusedInput, setFocusedInput, canFocusNext, canFocusPrevious, elements, setElements, previousKey, nextKey, } = useInputAccessoriesProviderState();
11
+ const colorScheme = useColorScheme();
12
+ return (React.createElement(InputAccessoriesContext.Provider, { value: {
13
+ elements,
14
+ focusedInput,
15
+ canFocusNext,
16
+ canFocusPrevious,
17
+ inputAccessoryID,
18
+ register,
19
+ unregister,
20
+ onFocusNext,
21
+ onFocusPrevious,
22
+ setFocusedInput,
23
+ } },
24
+ children,
25
+ Platform.OS === "ios" && (React.createElement(InputAccessoryView, { nativeID: inputAccessoryID },
26
+ React.createElement(View, { testID: "ATL-InputAccessory", style: [
27
+ styles.container,
28
+ colorScheme === "dark" ? styles.darkTheme : styles.lightTheme,
29
+ ] },
30
+ React.createElement(RNButton, { onPress: Keyboard.dismiss, title: "Done", testID: "ATL-InputAccessory-Done", color: colorScheme === "dark" ? "white" : undefined }))))));
31
+ function register(name, onFocus) {
32
+ elements[name] = onFocus;
33
+ setElements(elements);
34
+ }
35
+ function unregister(name) {
36
+ delete elements[name];
37
+ setElements(elements);
38
+ }
39
+ function onFocusNext() {
40
+ const nextElement = elements[nextKey];
41
+ nextElement === null || nextElement === void 0 ? void 0 : nextElement();
42
+ }
43
+ function onFocusPrevious() {
44
+ const previousElement = elements[previousKey];
45
+ previousElement === null || previousElement === void 0 ? void 0 : previousElement();
46
+ }
47
+ }
48
+ function useInputAccessoriesProviderState() {
49
+ const [focusedInput, setFocusedInput] = useState("");
50
+ const [canFocusNext, setCanFocusNext] = useState(false);
51
+ const [canFocusPrevious, setCanFocusPrevious] = useState(false);
52
+ const [elements, setElements] = useState({});
53
+ const keys = Object.keys(elements);
54
+ const selectedIndex = keys.findIndex(key => key === focusedInput);
55
+ const nextKey = keys[selectedIndex + 1];
56
+ const previousKey = keys[selectedIndex - 1];
57
+ useEffect(() => {
58
+ setCanFocusNext(Boolean(nextKey));
59
+ setCanFocusPrevious(Boolean(previousKey));
60
+ }, [previousKey, nextKey]);
61
+ return {
62
+ previousKey,
63
+ nextKey,
64
+ focusedInput,
65
+ setFocusedInput,
66
+ canFocusNext,
67
+ setCanFocusNext,
68
+ canFocusPrevious,
69
+ setCanFocusPrevious,
70
+ elements,
71
+ setElements,
72
+ };
73
+ }
@@ -0,0 +1,21 @@
1
+ import { PlatformColor, StyleSheet } from "react-native";
2
+ import { tokens } from "../../utils/design";
3
+ const BAR_HEIGHT = 44;
4
+ export const styles = StyleSheet.create({
5
+ container: {
6
+ flexDirection: "row",
7
+ justifyContent: "flex-end",
8
+ alignItems: "center",
9
+ paddingHorizontal: tokens["space-small"],
10
+ borderTopWidth: tokens["space-minuscule"],
11
+ borderTopColor: tokens["color-border"],
12
+ height: BAR_HEIGHT,
13
+ },
14
+ lightTheme: {
15
+ backgroundColor: tokens["color-surface--background"],
16
+ },
17
+ darkTheme: {
18
+ // PlatformColor has to be conditional for Storybook to run without error
19
+ backgroundColor: PlatformColor === null || PlatformColor === void 0 ? void 0 : PlatformColor("systemGray3"),
20
+ },
21
+ });
@@ -0,0 +1,16 @@
1
+ import { StyleSheet } from "react-native";
2
+ import { tokens } from "../../utils/design";
3
+ export const styles = StyleSheet.create({
4
+ container: {
5
+ flexDirection: "row",
6
+ justifyContent: "space-between",
7
+ alignItems: "center",
8
+ paddingHorizontal: tokens["space-small"],
9
+ backgroundColor: tokens["color-surface--background"],
10
+ borderTopWidth: tokens["space-minuscule"],
11
+ borderTopColor: tokens["color-border"],
12
+ },
13
+ buttonContainer: {
14
+ flexDirection: "row",
15
+ },
16
+ });
@@ -0,0 +1,2 @@
1
+ export * from "./InputAccessoriesContext";
2
+ export * from "./InputAccessoriesProvider";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export { InputText } from "./InputText";
2
+ export * from "./context";
@@ -0,0 +1,16 @@
1
+ import React, { useState } from "react";
2
+ import { View } from "react-native";
3
+ import { BaseSwitch } from "./components/BaseSwitch";
4
+ import { styles } from "./Switch.styles";
5
+ import { Text } from "../Text";
6
+ export function Switch(props) {
7
+ const switchProps = Object.assign(Object.assign({}, props), { accessibilityLabel: props.accessibilityLabel || props.label });
8
+ const [labelWidth, setLabelWidth] = useState();
9
+ return (React.createElement(View, { style: styles.container },
10
+ React.createElement(View, { style: styles.row },
11
+ props.label && (React.createElement(View, { style: styles.label, onLayout: event => setLabelWidth(event.nativeEvent.layout.width), testID: "switch-label-view" },
12
+ React.createElement(Text, { variation: props.disabled ? "disabled" : "base" }, props.label))),
13
+ React.createElement(BaseSwitch, Object.assign({}, switchProps))),
14
+ props.description && (React.createElement(View, { style: [styles.description, { maxWidth: labelWidth }], testID: "switch-description-view" },
15
+ React.createElement(Text, { level: "textSupporting", variation: "subdued" }, props.description)))));
16
+ }
@@ -0,0 +1,20 @@
1
+ import { StyleSheet } from "react-native";
2
+ import { tokens } from "../utils/design";
3
+ export const styles = StyleSheet.create({
4
+ container: {
5
+ marginTop: tokens["space-base"],
6
+ marginBottom: tokens["space-base"],
7
+ },
8
+ row: {
9
+ flexDirection: "row",
10
+ width: "100%",
11
+ },
12
+ label: {
13
+ flex: 1,
14
+ justifyContent: "center",
15
+ marginRight: tokens["space-small"],
16
+ },
17
+ description: {
18
+ marginTop: tokens["space-smaller"],
19
+ },
20
+ });
@@ -0,0 +1,54 @@
1
+ import React from "react";
2
+ import { Platform } from "react-native";
3
+ import { Switch } from "react-native-gesture-handler";
4
+ import { useFormController } from "../../../hooks";
5
+ import { tokens } from "../../../utils/design";
6
+ export function BaseSwitch({ value, defaultValue, onValueChange, disabled = false, accessibilityLabel, name, }) {
7
+ const { field } = useFormController({
8
+ name,
9
+ value: value !== null && value !== void 0 ? value : defaultValue,
10
+ });
11
+ const internalValue = value !== null && value !== void 0 ? value : field.value;
12
+ function getThumbColor() {
13
+ if (Platform.OS === "android") {
14
+ if (disabled) {
15
+ return tokens["color-disabled"];
16
+ }
17
+ else if (internalValue) {
18
+ return tokens["color-interactive"];
19
+ }
20
+ else {
21
+ return tokens["color-surface--background"];
22
+ }
23
+ }
24
+ return undefined; //use default iOS
25
+ }
26
+ function getTrackColors() {
27
+ if (Platform.OS === "android") {
28
+ return {
29
+ true: disabled
30
+ ? tokens["color-disabled--secondary"]
31
+ : tokens["color-green--lighter"],
32
+ false: disabled
33
+ ? tokens["color-disabled--secondary"]
34
+ : tokens["color-disabled"],
35
+ };
36
+ }
37
+ else {
38
+ //iOS
39
+ return {
40
+ true: tokens["color-interactive"],
41
+ false: tokens["color-surface--background"],
42
+ };
43
+ }
44
+ }
45
+ return (React.createElement(Switch, { value: internalValue, onValueChange: (val) => {
46
+ if (!disabled) {
47
+ onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(val);
48
+ field.onChange(val);
49
+ }
50
+ }, disabled: disabled, thumbColor: getThumbColor(), trackColor: getTrackColors(), ios_backgroundColor: tokens["color-surface--background"], accessibilityLabel: accessibilityLabel, accessibilityRole: "switch", accessibilityState: {
51
+ disabled: disabled,
52
+ checked: internalValue,
53
+ } }));
54
+ }
@@ -0,0 +1 @@
1
+ export { BaseSwitch } from "./BaseSwitch";
@@ -0,0 +1 @@
1
+ export { Switch } from "./Switch";