@artsy/palette-mobile 14.0.2 → 14.0.4

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.
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { useState } from "react";
2
+ import { useEffect, useState } from "react";
3
3
  import { Image } from "react-native";
4
4
  import Animated, { useAnimatedStyle, useSharedValue, withTiming, Easing, withDelay, } from "react-native-reanimated";
5
5
  import { useColor } from "../../utils/hooks";
@@ -30,13 +30,15 @@ export const Avatar = ({ src, initials, size = DEFAULT_SIZE }) => {
30
30
  const color = useColor();
31
31
  const [loading, setLoading] = useState(true);
32
32
  const opacity = useSharedValue(0);
33
- opacity.value = withDelay(100, withTiming(1, {
34
- duration: 200,
35
- easing: Easing.sin,
36
- }));
33
+ useEffect(() => {
34
+ opacity.set(() => withDelay(100, withTiming(1, {
35
+ duration: 200,
36
+ easing: Easing.sin,
37
+ })));
38
+ }, [loading]);
37
39
  const style = useAnimatedStyle(() => {
38
40
  return {
39
- opacity: loading ? 0 : opacity.value,
41
+ opacity: loading ? 0 : opacity.get(),
40
42
  };
41
43
  }, [loading]);
42
44
  const { diameter, textSize } = VARIANTS[size];
@@ -19,7 +19,7 @@ export const Button = ({ children, disabled: disabledProp, haptic, icon, iconPos
19
19
  useAnimatedReaction(() => {
20
20
  return pressedV.value;
21
21
  }, (pressedVal) => {
22
- return (pressAnimationProgress.value = withTiming(pressedVal, {
22
+ return pressAnimationProgress.set(() => withTiming(pressedVal, {
23
23
  duration: ANIMATION_DURATION,
24
24
  }));
25
25
  });
@@ -59,8 +59,8 @@ export const Button = ({ children, disabled: disabledProp, haptic, icon, iconPos
59
59
  };
60
60
  }
61
61
  return {
62
- backgroundColor: interpolateColor(pressAnimationProgress.value, [0, 1], [colors.active.bg, colors.pressed.bg]),
63
- borderColor: interpolateColor(pressAnimationProgress.value, [0, 1], [colors.active.border, colors.pressed.border]),
62
+ backgroundColor: interpolateColor(pressAnimationProgress.get(), [0, 1], [colors.active.bg, colors.pressed.bg]),
63
+ borderColor: interpolateColor(pressAnimationProgress.get(), [0, 1], [colors.active.border, colors.pressed.border]),
64
64
  };
65
65
  });
66
66
  const textAnim = useAnimatedStyle(() => {
@@ -69,8 +69,8 @@ export const Button = ({ children, disabled: disabledProp, haptic, icon, iconPos
69
69
  return { color: "rgba(0, 0, 0, 0)" };
70
70
  }
71
71
  return {
72
- color: interpolateColor(pressAnimationProgress.value, [0, 1], [colors.active.text, colors.pressed.text]),
73
- textDecorationLine: pressAnimationProgress.value > 0 ? "underline" : "none",
72
+ color: interpolateColor(pressAnimationProgress.get(), [0, 1], [colors.active.text, colors.pressed.text]),
73
+ textDecorationLine: pressAnimationProgress.get() > 0 ? "underline" : "none",
74
74
  };
75
75
  });
76
76
  return (_jsx(Pressable, { disabled: disabled, onPressIn: () => {
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { fireEvent } from "@testing-library/react-native";
2
+ import { fireEvent, screen } from "@testing-library/react-native";
3
3
  import { Button } from "./Button";
4
4
  import { renderWithWrappers } from "../../utils/tests/renderWithWrappers";
5
5
  import { Spinner } from "../Spinner";
@@ -10,20 +10,20 @@ describe("Button", () => {
10
10
  });
11
11
  it("invokes the onClick callback", () => {
12
12
  const onPress = jest.fn();
13
- const { getByTestId } = renderWithWrappers(_jsx(Button, { testID: "the-button", onPress: onPress, children: "wow" }));
14
- fireEvent.press(getByTestId("the-button"));
13
+ renderWithWrappers(_jsx(Button, { testID: "the-button", onPress: onPress, children: "wow" }));
14
+ fireEvent.press(screen.getByTestId("the-button"));
15
15
  expect(onPress).toHaveBeenCalled();
16
16
  });
17
17
  it("does not invoke the onClick callback if loading is true", () => {
18
18
  const onPress = jest.fn();
19
- const { getByTestId } = renderWithWrappers(_jsx(Button, { testID: "the-button", onPress: onPress, loading: true, children: "wow" }));
20
- fireEvent.press(getByTestId("the-button"));
19
+ renderWithWrappers(_jsx(Button, { testID: "the-button", onPress: onPress, loading: true, children: "wow" }));
20
+ fireEvent.press(screen.getByTestId("the-button"));
21
21
  expect(onPress).not.toHaveBeenCalled();
22
22
  });
23
23
  it("does not invoke the onClick callback if disabled is true", () => {
24
24
  const onPress = jest.fn();
25
- const { getByTestId } = renderWithWrappers(_jsx(Button, { testID: "the-button", onPress: onPress, disabled: true, children: "wow" }));
26
- fireEvent.press(getByTestId("the-button"));
25
+ renderWithWrappers(_jsx(Button, { testID: "the-button", onPress: onPress, disabled: true, children: "wow" }));
26
+ fireEvent.press(screen.getByTestId("the-button"));
27
27
  expect(onPress).not.toHaveBeenCalled();
28
28
  });
29
29
  });
@@ -1,54 +1,54 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { fireEvent } from "@testing-library/react-native";
2
+ import { fireEvent, screen } from "@testing-library/react-native";
3
3
  import { Dialog } from "./Dialog";
4
4
  import { renderWithWrappers } from "../../utils/tests/renderWithWrappers";
5
5
  describe("Dialog", () => {
6
6
  it("renders without error", () => {
7
- const { getByText } = renderWithWrappers(_jsx(Dialog, { title: "title", isVisible: true, primaryCta: {
7
+ renderWithWrappers(_jsx(Dialog, { title: "title", isVisible: true, primaryCta: {
8
8
  text: "Primary Action Button",
9
9
  onPress: jest.fn(),
10
10
  } }));
11
- expect(getByText("title")).toBeTruthy();
11
+ expect(screen.getByText("title")).toBeOnTheScreen();
12
12
  });
13
13
  it("should render details if it is passed", () => {
14
- const { getByText } = renderWithWrappers(_jsx(Dialog, { title: "title", detail: "Some unique detail", isVisible: true, primaryCta: {
14
+ renderWithWrappers(_jsx(Dialog, { title: "title", detail: "Some unique detail", isVisible: true, primaryCta: {
15
15
  text: "Primary Action Button",
16
16
  onPress: jest.fn(),
17
17
  } }));
18
- expect(getByText("Some unique detail")).toBeTruthy();
18
+ expect(screen.getByText("Some unique detail")).toBeOnTheScreen();
19
19
  });
20
20
  it("should render the primary action button", () => {
21
21
  const primaryActionMock = jest.fn();
22
- const { getByTestId, getByText } = renderWithWrappers(_jsx(Dialog, { title: "title", isVisible: true, primaryCta: {
22
+ renderWithWrappers(_jsx(Dialog, { title: "title", isVisible: true, primaryCta: {
23
23
  text: "Primary Action Button",
24
24
  onPress: primaryActionMock,
25
25
  } }));
26
- const primaryButton = getByTestId("dialog-primary-action-button");
26
+ const primaryButton = screen.getByTestId("dialog-primary-action-button");
27
27
  fireEvent.press(primaryButton);
28
28
  expect(primaryActionMock).toHaveBeenCalled();
29
- expect(getByText("Primary Action Button")).toBeTruthy();
29
+ expect(screen.getByText("Primary Action Button")).toBeOnTheScreen();
30
30
  });
31
31
  it("should render the secondary action button if it is passed", () => {
32
32
  const secondaryActionMock = jest.fn();
33
- const { getByTestId, getByText } = renderWithWrappers(_jsx(Dialog, { title: "title", isVisible: true, primaryCta: {
33
+ renderWithWrappers(_jsx(Dialog, { title: "title", isVisible: true, primaryCta: {
34
34
  text: "Primary Action Button",
35
35
  onPress: jest.fn(),
36
36
  }, secondaryCta: {
37
37
  text: "Secondary Action Button",
38
38
  onPress: secondaryActionMock,
39
39
  } }));
40
- const secondaryButton = getByTestId("dialog-secondary-action-button");
40
+ const secondaryButton = screen.getByTestId("dialog-secondary-action-button");
41
41
  fireEvent.press(secondaryButton);
42
42
  expect(secondaryActionMock).toHaveBeenCalled();
43
- expect(getByText("Secondary Action Button")).toBeTruthy();
43
+ expect(screen.getByText("Secondary Action Button")).toBeOnTheScreen();
44
44
  });
45
45
  it("should call onBackgroundPress when backdrop is pressed", () => {
46
46
  const onBackgroundPressMock = jest.fn();
47
- const { getByTestId } = renderWithWrappers(_jsx(Dialog, { title: "title", isVisible: true, onBackgroundPress: onBackgroundPressMock, primaryCta: {
47
+ renderWithWrappers(_jsx(Dialog, { title: "title", isVisible: true, onBackgroundPress: onBackgroundPressMock, primaryCta: {
48
48
  text: "Primary Action Button",
49
49
  onPress: jest.fn(),
50
50
  } }));
51
- fireEvent.press(getByTestId("dialog-backdrop"));
51
+ fireEvent.press(screen.getByTestId("dialog-backdrop"));
52
52
  expect(onBackgroundPressMock).toHaveBeenCalled();
53
53
  });
54
54
  });
@@ -15,12 +15,12 @@ export const Image = memo(({ aspectRatio, width, height, performResize = true, s
15
15
  const color = useColor();
16
16
  const animatedStyles = useAnimatedStyle(() => {
17
17
  return {
18
- opacity: withTiming(loading.value ? 0 : 1, { duration: 200, easing: Easing.sin }),
18
+ opacity: withTiming(loading.get() ? 0 : 1, { duration: 200, easing: Easing.sin }),
19
19
  };
20
20
  }, []);
21
21
  const onAnimationEnd = useCallback(() => {
22
22
  "worklet";
23
- loading.value = false;
23
+ loading.set(() => false);
24
24
  // No need to get the js thread involved here
25
25
  // eslint-disable-next-line react-hooks/exhaustive-deps
26
26
  }, []);
@@ -11,6 +11,10 @@ export interface InputProps extends Omit<TextInputProps, "placeholder" | "onChan
11
11
  * These lead to some issues when the parent component wants further control of the value
12
12
  */
13
13
  disabled?: boolean;
14
+ /**
15
+ * Enables the clear button
16
+ * @warning This prop only works if `value` is specified
17
+ */
14
18
  enableClearButton?: boolean;
15
19
  error?: string;
16
20
  fixedRightPlaceholder?: string;
@@ -60,6 +64,13 @@ export interface InputProps extends Omit<TextInputProps, "placeholder" | "onChan
60
64
  * <Input mask="999-99-9999 999-99-9999 999-99-9999" />
61
65
  */
62
66
  mask?: string | string[] | undefined;
67
+ /**
68
+ * @warning This prop affects the performance of the input
69
+ * and should be avoided if possible.
70
+ * Use `defaultValue` instead.
71
+ * See: https://github.com/facebook/react-native-website/pull/4247
72
+ */
73
+ value?: string | undefined;
63
74
  }
64
75
  export declare const HORIZONTAL_PADDING = 15;
65
76
  export declare const INPUT_BORDER_RADIUS = 4;
@@ -148,14 +148,17 @@ export const Input = forwardRef(({ addClearListener = false, defaultValue, disab
148
148
  fontFamily: fontFamily,
149
149
  };
150
150
  }, [fontFamily, space]);
151
- animatedState.value = getInputState({
152
- isFocused: !!focused,
153
- value: value,
154
- });
151
+ useEffect(() => {
152
+ const inputState = getInputState({
153
+ isFocused: !!focused,
154
+ value: value,
155
+ });
156
+ animatedState.set(() => inputState);
157
+ }, [value, focused, animatedState]);
155
158
  const textInputAnimatedStyles = useAnimatedStyle(() => {
156
159
  return {
157
- borderColor: withTiming(INPUT_VARIANTS[variant][animatedState.value].inputBorderColor),
158
- color: withTiming(INPUT_VARIANTS[variant][animatedState.value].inputTextColor),
160
+ borderColor: withTiming(INPUT_VARIANTS[variant][animatedState.get()].inputBorderColor),
161
+ color: withTiming(INPUT_VARIANTS[variant][animatedState.get()].inputTextColor),
159
162
  };
160
163
  });
161
164
  const labelAnimatedStyles = useAnimatedStyle(() => {
@@ -165,15 +168,15 @@ export const Input = forwardRef(({ addClearListener = false, defaultValue, disab
165
168
  ? textInputPaddingLeft - 3
166
169
  : HORIZONTAL_PADDING;
167
170
  return {
168
- color: withTiming(INPUT_VARIANTS[variant][animatedState.value].labelColor),
169
- top: withTiming(INPUT_VARIANTS[variant][animatedState.value].labelTop),
170
- fontSize: withTiming(INPUT_VARIANTS[variant][animatedState.value].labelFontSize),
171
+ color: withTiming(INPUT_VARIANTS[variant][animatedState.get()].labelColor),
172
+ top: withTiming(INPUT_VARIANTS[variant][animatedState.get()].labelTop),
173
+ fontSize: withTiming(INPUT_VARIANTS[variant][animatedState.get()].labelFontSize),
171
174
  marginLeft: withTiming(marginLeft),
172
175
  };
173
176
  });
174
177
  const selectComponentStyles = useAnimatedStyle(() => {
175
178
  return {
176
- borderColor: withTiming(INPUT_VARIANTS[variant][animatedState.value].inputBorderColor),
179
+ borderColor: withTiming(INPUT_VARIANTS[variant][animatedState.get()].inputBorderColor),
177
180
  };
178
181
  });
179
182
  const handleFocus = (e) => {
@@ -349,7 +352,9 @@ export const Input = forwardRef(({ addClearListener = false, defaultValue, disab
349
352
  ...styles,
350
353
  }, children: placeholderString }))) }));
351
354
  }, [placeholder, styles]);
352
- return (_jsxs(Flex, { flexGrow: 1, children: [renderAndroidPlaceholderMeasuringHack(), renderHint(), renderAnimatedTitle(), _jsx(AnimatedStyledInput, { value: value, onChangeText: handleChangeText, style: [styles, textInputAnimatedStyles], onFocus: handleFocus, onBlur: handleBlur, onLayout: (event) => {
355
+ return (_jsxs(Flex, { flexGrow: 1, children: [renderAndroidPlaceholderMeasuringHack(), renderHint(), renderAnimatedTitle(), _jsx(AnimatedStyledInput
356
+ // Only use a controlled input if specified
357
+ , { ...((propValue !== undefined && propValue !== null) || mask ? { value } : {}), onChangeText: handleChangeText, style: [styles, textInputAnimatedStyles], onFocus: handleFocus, onBlur: handleBlur, onLayout: (event) => {
353
358
  setInputWidth(event.nativeEvent.layout.width);
354
359
  }, scrollEnabled: props.multiline, editable: !disabled, textAlignVertical: props.multiline ? "top" : "center", ref: inputRef, placeholderTextColor: color("black60"), placeholder: getPlaceholder(), secureTextEntry: !showPassword, ...props }), renderRightComponent(), renderLeftComponent(), renderBottomComponent()] }));
355
360
  });
@@ -1,50 +1,47 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { fireEvent } from "@testing-library/react-native";
2
+ import { fireEvent, screen } from "@testing-library/react-native";
3
3
  import { Input } from "./Input";
4
4
  import { renderWithWrappers } from "../../utils/tests/renderWithWrappers";
5
5
  describe("Input", () => {
6
6
  const testID = "input";
7
7
  it("renders an instance of native TextInput", () => {
8
- const { getByTestId } = renderWithWrappers(_jsx(Input, { testID: testID }));
9
- expect(getByTestId(testID).type).toEqual("TextInput");
8
+ renderWithWrappers(_jsx(Input, { testID: testID }));
9
+ expect(screen.getByTestId(testID).type).toEqual("TextInput");
10
10
  });
11
11
  it("uses correct font family", () => {
12
- const { getByTestId } = renderWithWrappers(_jsx(Input, { testID: testID }));
13
- expect(getByTestId(testID).props.style[0].fontFamily).toEqual("Unica77LL-Regular");
12
+ renderWithWrappers(_jsx(Input, { testID: testID, placeholder: "input" }));
13
+ expect(screen.getByPlaceholderText("input")).toHaveStyle({ fontFamily: "Unica77LL-Regular" });
14
14
  });
15
15
  it("mutates given text as value", () => {
16
- const { getByTestId, getByDisplayValue } = renderWithWrappers(_jsx(Input, { testID: testID }));
17
- fireEvent.changeText(getByTestId(testID), "mockStr");
18
- getByDisplayValue("mockStr");
16
+ renderWithWrappers(_jsx(Input, { testID: testID }));
17
+ fireEvent.changeText(screen.getByTestId(testID), "mockStr");
18
+ screen.getByDisplayValue("mockStr");
19
19
  });
20
20
  it("Shows an error message when input has an error", () => {
21
- const { getByText } = renderWithWrappers(_jsx(Input, { value: "", error: "input has an error" }));
22
- getByText("input has an error");
21
+ renderWithWrappers(_jsx(Input, { value: "", error: "input has an error" }));
22
+ screen.getByText("input has an error");
23
23
  });
24
- it("should render the clear button when input is not empty and pressing it should clear the input", () => {
25
- const { getByDisplayValue, queryByDisplayValue, getByPlaceholderText, getByLabelText } = renderWithWrappers(_jsx(Input, { placeholder: "USD", enableClearButton: true }));
26
- // placeholder is rendered
27
- getByPlaceholderText("USD");
28
- fireEvent(getByPlaceholderText("USD"), "onChangeText", "Banksy");
29
- getByDisplayValue("Banksy");
30
- getByLabelText("Clear input button");
31
- fireEvent.press(getByLabelText("Clear input button"));
32
- expect(queryByDisplayValue("Banksy")).toBeFalsy();
24
+ it("should render the clear button when input is not empty and pressing it should clear the input", async () => {
25
+ renderWithWrappers(_jsx(Input, { testID: testID, placeholder: "USD", enableClearButton: true }));
26
+ fireEvent(screen.getByTestId(testID), "onChangeText", "Banksy");
27
+ await screen.findByLabelText("Clear input button");
28
+ fireEvent.press(screen.getByLabelText("Clear input button"));
29
+ expect(screen.queryByDisplayValue("Banksy")).toBeFalsy();
33
30
  });
34
31
  it("should show the correct show/hide password icon", () => {
35
- const { getByPlaceholderText, queryByLabelText, getByLabelText } = renderWithWrappers(_jsx(Input, { placeholder: "password", secureTextEntry: true }));
36
- getByPlaceholderText("password");
37
- getByLabelText("show password button");
38
- fireEvent(getByPlaceholderText("password"), "onChangeText", "123456");
39
- fireEvent.press(getByLabelText("show password button"));
40
- expect(queryByLabelText("show password button")).toBeFalsy();
41
- getByLabelText("hide password button");
42
- fireEvent.press(getByLabelText("hide password button"));
43
- expect(queryByLabelText("hide password button")).toBeFalsy();
44
- getByLabelText("show password button");
32
+ renderWithWrappers(_jsx(Input, { placeholder: "password", secureTextEntry: true }));
33
+ screen.getByPlaceholderText("password");
34
+ screen.getByLabelText("show password button");
35
+ fireEvent(screen.getByPlaceholderText("password"), "onChangeText", "123456");
36
+ fireEvent.press(screen.getByLabelText("show password button"));
37
+ expect(screen.queryByLabelText("show password button")).toBeFalsy();
38
+ screen.getByLabelText("hide password button");
39
+ fireEvent.press(screen.getByLabelText("hide password button"));
40
+ expect(screen.queryByLabelText("hide password button")).toBeFalsy();
41
+ screen.getByLabelText("show password button");
45
42
  });
46
43
  it("enables scrolling when multiline is true", () => {
47
- const { getByTestId } = renderWithWrappers(_jsx(Input, { testID: testID, multiline: true }));
48
- expect(getByTestId(testID).props.scrollEnabled).toBe(true);
44
+ renderWithWrappers(_jsx(Input, { testID: testID, multiline: true }));
45
+ expect(screen.getByTestId(testID).props.scrollEnabled).toBe(true);
49
46
  });
50
47
  });
@@ -1,26 +1,25 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { fireEvent } from "@testing-library/react-native";
2
+ import { fireEvent, screen } from "@testing-library/react-native";
3
3
  import { Message } from "./Message";
4
4
  import { renderWithWrappers } from "../../utils/tests/renderWithWrappers";
5
5
  describe("Message", () => {
6
6
  it("it renders", () => {
7
- const MessageComponent = renderWithWrappers(_jsx(Message, { variant: "default", title: "title", text: "text" }));
8
- expect(MessageComponent).toBeTruthy();
9
- expect(MessageComponent.getByText("title")).toBeDefined();
10
- expect(MessageComponent.getByText("text")).toBeDefined();
7
+ renderWithWrappers(_jsx(Message, { variant: "default", title: "title", text: "text" }));
8
+ expect(screen.getByText("title")).toBeOnTheScreen();
9
+ expect(screen.getByText("text")).toBeOnTheScreen();
11
10
  });
12
11
  it("does not show close button when !showCloseButton", () => {
13
- const { getByTestId } = renderWithWrappers(_jsx(Message, { variant: "default", title: "title", text: "text" }));
14
- expect(() => getByTestId("Message-close-button")).toThrow("Unable to find an element with testID: Message-close-button");
12
+ renderWithWrappers(_jsx(Message, { variant: "default", title: "title", text: "text" }));
13
+ expect(screen.queryByTestId("Message-close-button")).not.toBeOnTheScreen();
15
14
  });
16
15
  it("shows close button when showCloseButton", () => {
17
- const { getByTestId } = renderWithWrappers(_jsx(Message, { variant: "default", title: "title", text: "text", showCloseButton: true }));
18
- expect(getByTestId("Message-close-button")).toBeDefined();
16
+ renderWithWrappers(_jsx(Message, { variant: "default", title: "title", text: "text", showCloseButton: true }));
17
+ expect(screen.getByTestId("Message-close-button")).toBeOnTheScreen();
19
18
  });
20
19
  it("fires onClose press event", () => {
21
20
  const onClose = jest.fn();
22
- const { getByTestId } = renderWithWrappers(_jsx(Message, { variant: "default", onClose: onClose, title: "title", text: "text", showCloseButton: true }));
23
- fireEvent.press(getByTestId("Message-close-button"));
21
+ renderWithWrappers(_jsx(Message, { variant: "default", onClose: onClose, title: "title", text: "text", showCloseButton: true }));
22
+ fireEvent.press(screen.getByTestId("Message-close-button"));
24
23
  expect(onClose).toHaveBeenCalled();
25
24
  });
26
25
  });
@@ -1,18 +1,18 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { fireEvent, render } from "@testing-library/react-native";
2
+ import { fireEvent, render, screen } from "@testing-library/react-native";
3
3
  import { Pill } from "./Pill";
4
4
  import { Theme } from "../../Theme";
5
5
  describe("Pill", () => {
6
6
  it("invokes the onClick callback", () => {
7
7
  const onPress = jest.fn();
8
- const { getByText } = render(_jsx(Theme, { children: _jsx(Pill, { onPress: onPress, children: "wow" }) }));
9
- fireEvent.press(getByText("wow"));
8
+ render(_jsx(Theme, { children: _jsx(Pill, { onPress: onPress, children: "wow" }) }));
9
+ fireEvent.press(screen.getByText("wow"));
10
10
  expect(onPress).toHaveBeenCalled();
11
11
  });
12
12
  it("should not be pressable if disabled is passed", () => {
13
13
  const onPress = jest.fn();
14
- const { getByText } = render(_jsx(Theme, { children: _jsx(Pill, { disabled: true, onPress: onPress, children: "Press me" }) }));
15
- fireEvent.press(getByText("Press me"));
14
+ render(_jsx(Theme, { children: _jsx(Pill, { disabled: true, onPress: onPress, children: "Press me" }) }));
15
+ fireEvent.press(screen.getByText("Press me"));
16
16
  expect(onPress).not.toHaveBeenCalled();
17
17
  });
18
18
  });
@@ -11,11 +11,11 @@ export const ProgressBar = ({ animationDuration = 200, backgroundColor = "black3
11
11
  const width = useSharedValue(0);
12
12
  const progress = clamp(unclampedProgress, 0, 100);
13
13
  const progressAnim = useAnimatedStyle(() => {
14
- return { width: `${width.value}%` };
14
+ return { width: `${width.get()}%` };
15
15
  });
16
16
  const [onCompletionCalled, setOnCompletionCalled] = useState(false);
17
17
  useEffect(() => {
18
- width.value = withTiming(progress, { duration: animationDuration });
18
+ width.set(() => withTiming(progress, { duration: animationDuration }));
19
19
  if (progress === 100 && !onCompletionCalled) {
20
20
  onCompletion?.();
21
21
  setOnCompletionCalled(true);
@@ -3,7 +3,7 @@ import { runOnJS, useAnimatedReaction, useSharedValue } from "react-native-reani
3
3
  import { NAVBAR_HEIGHT } from "../constants";
4
4
  export const useAnimatedHeaderScrolling = (scrollY, scrollYOffset = 0) => {
5
5
  const listenForScroll = useSharedValue(true);
6
- const [currScrollY, setCurrScrollY] = useState(scrollY.value);
6
+ const [currScrollY, setCurrScrollY] = useState(scrollY.get());
7
7
  const HEADER_HEIGHT = useMemo(() => NAVBAR_HEIGHT + scrollYOffset, [scrollYOffset]);
8
8
  // Needed to run on JS thread
9
9
  const update = (y) => {
@@ -11,14 +11,14 @@ export const useAnimatedHeaderScrolling = (scrollY, scrollYOffset = 0) => {
11
11
  };
12
12
  useEffect(() => {
13
13
  const timer = setTimeout(() => {
14
- listenForScroll.value = false;
14
+ listenForScroll.set(() => false);
15
15
  }, 1000);
16
16
  return () => {
17
17
  clearTimeout(timer);
18
18
  };
19
- }, [listenForScroll]);
19
+ }, [listenForScroll.get()]);
20
20
  useAnimatedReaction(() => {
21
- return [scrollY.value, listenForScroll.value];
21
+ return [scrollY.get(), listenForScroll.get()];
22
22
  }, ([animatedScrollY, isListeningForScroll], previousScroll) => {
23
23
  const [prevScrollY] = previousScroll ?? [0, false];
24
24
  // Hacky way to avoid some weird header behavior.
@@ -8,7 +8,7 @@ export const useListenForScreenScroll = () => {
8
8
  const scrollY = useAnimatedHeaderScrolling(animatedScrollY, scrollYOffset);
9
9
  const scrollHandler = useAnimatedScrollHandler({
10
10
  onScroll: (event) => {
11
- animatedScrollY.value = event.contentOffset.y;
11
+ animatedScrollY.set(() => event.contentOffset.y);
12
12
  },
13
13
  });
14
14
  useEffect(() => {
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import isArray from "lodash/isArray";
3
3
  import isString from "lodash/isString";
4
4
  import { useCallback, useRef, useState } from "react";
5
- import { LayoutAnimation, TextInput } from "react-native";
5
+ import { TextInput } from "react-native";
6
6
  import { ArrowLeftIcon, MagnifyingGlassIcon } from "../../svgs";
7
7
  import { useColor, useTheme } from "../../utils/hooks";
8
8
  import { Flex } from "../Flex";
@@ -76,7 +76,6 @@ export const RoundSearchInput = ({ value, placeholder, onLeftIconPress, ...rest
76
76
  // anything above that would lead to an error
77
77
  maxLength: 100, clearButtonMode: "always", placeholderTextColor: color("black60"), onFocus: (e) => {
78
78
  setIsFocused(true);
79
- LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
80
79
  rest.onFocus?.(e);
81
80
  }, enterKeyHint: "search", returnKeyType: "search" }), _jsx(Flex, { position: "absolute", height: SEARCH_INPUT_CONTAINER_HEIGHT, justifyContent: "center", alignItems: "center", style: {
82
81
  paddingHorizontal: CONTAINER_HORIZONTAL_PADDING,
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect } from "react";
2
3
  import Animated, { Easing, useAnimatedStyle, useSharedValue, withRepeat, withTiming, } from "react-native-reanimated";
3
4
  import { useColor } from "../../utils/hooks";
4
5
  import { Flex } from "../Flex";
@@ -15,9 +16,11 @@ import { Text } from "../Text";
15
16
  */
16
17
  export const Skeleton = ({ children }) => {
17
18
  const opacity = useSharedValue(0.5);
18
- opacity.value = withRepeat(withTiming(1, { duration: 1000, easing: Easing.ease }), -1, true);
19
+ useEffect(() => {
20
+ opacity.set(() => withRepeat(withTiming(1, { duration: 1000, easing: Easing.ease }), -1, true));
21
+ }, [opacity]);
19
22
  const fadeLoopAnim = useAnimatedStyle(() => {
20
- return { opacity: opacity.value };
23
+ return { opacity: opacity.get() };
21
24
  }, []);
22
25
  return _jsx(Animated.View, { style: fadeLoopAnim, children: children });
23
26
  };
@@ -1,15 +1,16 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { screen } from "@testing-library/react-native";
2
3
  import { ToolTip } from "./ToolTip";
3
4
  import { ScreenDimensionsProvider } from "../../utils/hooks";
4
5
  import { renderWithWrappers } from "../../utils/tests/renderWithWrappers";
5
6
  import { Text } from "../Text";
6
7
  describe("ToolTip", () => {
7
8
  it("shows the flyout when enabled", () => {
8
- const { queryByTestId } = renderWithWrappers(_jsx(ScreenDimensionsProvider, { children: _jsx(ToolTip, { enabled: true, testID: "flyout", initialToolTipText: "Words", children: _jsx(Text, { children: "Text" }) }) }));
9
- expect(queryByTestId("flyout")).not.toBeNull();
9
+ renderWithWrappers(_jsx(ScreenDimensionsProvider, { children: _jsx(ToolTip, { enabled: true, testID: "flyout", initialToolTipText: "Words", children: _jsx(Text, { children: "Text" }) }) }));
10
+ expect(screen.getByTestId("flyout")).toBeOnTheScreen();
10
11
  });
11
12
  it("Does not show the flyout when disabled", () => {
12
- const { queryByTestId } = renderWithWrappers(_jsx(ScreenDimensionsProvider, { children: _jsx(ToolTip, { enabled: false, testID: "flyout", initialToolTipText: "Words", children: _jsx(Text, { children: "Text" }) }) }));
13
- expect(queryByTestId("flyout")).toBeNull();
13
+ renderWithWrappers(_jsx(ScreenDimensionsProvider, { children: _jsx(ToolTip, { enabled: false, testID: "flyout", initialToolTipText: "Words", children: _jsx(Text, { children: "Text" }) }) }));
14
+ expect(screen.queryByTestId("flyout")).not.toBeOnTheScreen();
14
15
  });
15
16
  });
@@ -10,23 +10,23 @@ export const ToolTipFlyout = ({ containerStyle, tapToDismiss, height, width, onC
10
10
  const boxDimensions = useSharedValue(initialBoxDimensions);
11
11
  const animationStyle = useAnimatedStyle(() => {
12
12
  return {
13
- height: withTiming(boxDimensions.value.height, {
13
+ height: withTiming(boxDimensions.get().height, {
14
14
  duration: 500,
15
15
  }),
16
- width: withTiming(boxDimensions.value.width, {
16
+ width: withTiming(boxDimensions.get().width, {
17
17
  duration: 500,
18
18
  }),
19
19
  };
20
20
  });
21
21
  useEffect(() => {
22
22
  if (text) {
23
- boxDimensions.value = {
23
+ boxDimensions.set(() => ({
24
24
  height,
25
25
  width,
26
- };
26
+ }));
27
27
  }
28
28
  else {
29
- boxDimensions.value = initialBoxDimensions;
29
+ boxDimensions.set(() => initialBoxDimensions);
30
30
  }
31
31
  // eslint-disable-next-line react-hooks/exhaustive-deps
32
32
  }, [text, height, width]);
@@ -1 +1 @@
1
- export {};
1
+ import "@testing-library/react-native/extend-expect";
package/dist/setupJest.js CHANGED
@@ -1,9 +1,7 @@
1
1
  // @ts-expect-error
2
2
  global.__TEST__ = true;
3
+ import "@testing-library/react-native/extend-expect";
3
4
  import mockSafeAreaContext from "react-native-safe-area-context/jest/mock";
4
5
  jest.mock("react-native-safe-area-context", () => mockSafeAreaContext);
5
6
  jest.mock("react-native/Libraries/Animated/NativeAnimatedHelper");
6
7
  require("react-native-reanimated").setUpTests();
7
- // @ts-expect-error
8
- global.__reanimatedWorkletInit = () => { };
9
- jest.mock("react-native-reanimated", () => require("react-native-reanimated/mock"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artsy/palette-mobile",
3
- "version": "14.0.2",
3
+ "version": "14.0.4",
4
4
  "description": "Artsy's design system for React Native",
5
5
  "scripts": {
6
6
  "android": "RCT_METRO_PORT=8082 react-native run-android --port 8082 --terminal terminal",
@@ -104,7 +104,7 @@
104
104
  "eslint-plugin-react": "7.32.2",
105
105
  "eslint-plugin-react-hooks": "^4.6.0",
106
106
  "eslint-plugin-storybook": "0.6.10",
107
- "eslint-plugin-testing-library": "^5.10.2",
107
+ "eslint-plugin-testing-library": "6.4.0",
108
108
  "husky": "^8.0.3",
109
109
  "jest": "29.6.3",
110
110
  "jest-environment-jsdom": "29.4.2",