@artsy/palette-mobile 11.0.18 → 11.0.20

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/CHANGELOG.md CHANGED
@@ -1,3 +1,27 @@
1
+ # v11.0.20 (Mon May 01 2023)
2
+
3
+ #### 🐛 Bug Fix
4
+
5
+ - feat(old-button): Copy old Eigen button over to palette-mobile [#94](https://github.com/artsy/palette-mobile/pull/94) ([@damassi](https://github.com/damassi))
6
+
7
+ #### Authors: 1
8
+
9
+ - Christopher Pappas ([@damassi](https://github.com/damassi))
10
+
11
+ ---
12
+
13
+ # v11.0.19 (Tue Apr 25 2023)
14
+
15
+ #### 🐛 Bug Fix
16
+
17
+ - build(deps): followup on rn upgrade [#92](https://github.com/artsy/palette-mobile/pull/92) ([@gkartalis](https://github.com/gkartalis))
18
+
19
+ #### Authors: 1
20
+
21
+ - George Kartalis ([@gkartalis](https://github.com/gkartalis))
22
+
23
+ ---
24
+
1
25
  # v11.0.18 (Tue Apr 25 2023)
2
26
 
3
27
  :tada: This release contains work from a new contributor! :tada:
@@ -1,13 +1,12 @@
1
1
  /// <reference types="react" />
2
+ import { TextVariant } from "@artsy/palette-tokens/dist/typography/v3";
2
3
  import { PressableProps } from "react-native";
3
4
  import { HapticFeedbackTypes } from "react-native-haptic-feedback";
4
5
  import { BoxProps } from "../Box";
5
- type ButtonSize = "small" | "large";
6
- type ButtonVariant = "fillDark" | "fillLight" | "fillGray" | "fillSuccess" | "outline" | "outlineGray" | "outlineLight" | "text";
7
6
  export interface ButtonProps extends BoxProps {
8
7
  children: React.ReactNode;
9
- size?: ButtonSize;
10
- variant?: ButtonVariant;
8
+ size?: "small" | "large";
9
+ variant?: "fillDark" | "fillLight" | "fillGray" | "fillSuccess" | "outline" | "outlineGray" | "outlineLight" | "text";
11
10
  onPress?: PressableProps["onPress"];
12
11
  icon?: React.ReactNode;
13
12
  iconPosition?: "left" | "left-start" | "right";
@@ -28,7 +27,14 @@ export interface ButtonProps extends BoxProps {
28
27
  /** Pass the longest text to the button for the button to keep longest text width */
29
28
  longestText?: string;
30
29
  /** Used only for tests and stories */
31
- testOnly_pressed?: PressableProps["testOnly_pressed"];
30
+ testOnly_state?: DisplayState;
31
+ textVariant?: TextVariant;
32
32
  }
33
- export declare const Button: ({ children, disabled: disabledProp, haptic, icon, iconPosition, loading: loadingProp, block, longestText, onPress, size, variant, testOnly_pressed, testID, hitSlop, ...restProps }: ButtonProps) => JSX.Element;
34
- export {};
33
+ declare enum DisplayState {
34
+ Enabled = "enabled",
35
+ Disabled = "disabled",
36
+ Loading = "loading",
37
+ Pressed = "pressed"
38
+ }
39
+ export declare const Button: React.FC<ButtonProps>;
40
+ export { DisplayState as _test_DisplayState };
@@ -1,130 +1,304 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.Button = void 0;
6
+ exports._test_DisplayState = exports.Button = void 0;
30
7
  const jsx_runtime_1 = require("react/jsx-runtime");
31
8
  const react_1 = require("react");
32
9
  const react_native_1 = require("react-native");
33
10
  const react_native_haptic_feedback_1 = __importDefault(require("react-native-haptic-feedback"));
34
- const react_native_reanimated_1 = __importStar(require("react-native-reanimated"));
35
- const colors_1 = require("./colors");
36
- const MeasuredView_1 = require("../../elements/MeasuredView");
11
+ const react_spring_1 = require("react-spring");
12
+ // @ts-ignore
13
+ const renderprops_native_1 = require("react-spring/renderprops-native");
14
+ const native_1 = __importDefault(require("styled-components/native"));
15
+ const hooks_1 = require("../../utils/hooks");
37
16
  const Box_1 = require("../Box");
38
- const Flex_1 = require("../Flex");
17
+ const Flex_1 = require("../Flex/Flex");
18
+ const MeasuredView_1 = require("../MeasuredView");
39
19
  const Spacer_1 = require("../Spacer");
40
20
  const Spinner_1 = require("../Spinner");
41
- const Text_1 = require("../Text");
42
- const ANIMATION_DURATION = 150;
43
- const Button = ({ children, disabled: disabledProp, haptic, icon, iconPosition = "left", loading: loadingProp, block, longestText, onPress, size = "large", variant = "fillDark", testOnly_pressed, testID, hitSlop, ...restProps }) => {
44
- const [disabled, setDisabled, disabledV] = useStateWithProp(!!disabledProp);
45
- const [loading, setLoading, loadingV] = useStateWithProp(!!loadingProp);
46
- const [pressed, setPressed, pressedV] = useStateWithProp(!!testOnly_pressed);
47
- const pressAnimationProgress = (0, react_native_reanimated_1.useSharedValue)(0);
48
- (0, react_native_reanimated_1.useAnimatedReaction)(() => pressedV.value, (pressedVal) => {
49
- pressAnimationProgress.value = (0, react_native_reanimated_1.withTiming)(pressedVal, { duration: ANIMATION_DURATION });
50
- });
51
- const textStyle = (0, Text_1.useTextStyleForPalette)(size === "small" ? "xs" : "sm");
21
+ const Text_1 = require("../Text/Text");
22
+ const helpers_1 = require("../Text/helpers");
23
+ var DisplayState;
24
+ (function (DisplayState) {
25
+ DisplayState["Enabled"] = "enabled";
26
+ DisplayState["Disabled"] = "disabled";
27
+ DisplayState["Loading"] = "loading";
28
+ DisplayState["Pressed"] = "pressed";
29
+ })(DisplayState || (DisplayState = {}));
30
+ exports._test_DisplayState = DisplayState;
31
+ const Button = ({ children, disabled, haptic, icon, iconPosition = "left", loading, longestText, onPress, size = "large", variant = "fillDark", testOnly_state, testID, textVariant, hitSlop, ...rest }) => {
32
+ const textVariantBySize = size === "small" ? "xs" : "sm";
33
+ const textStyle = (0, helpers_1.useTextStyleForPalette)(textVariant ?? textVariantBySize);
34
+ const [innerDisplayState, setInnerDisplayState] = (0, react_1.useState)(DisplayState.Enabled);
52
35
  const [longestTextMeasurements, setLongestTextMeasurements] = (0, react_1.useState)({
53
36
  width: 0,
54
37
  height: 0,
55
38
  });
56
- const height = (() => {
39
+ const displayState = testOnly_state ?? // if we use the test prop, use that
40
+ (loading // if we have loading or disabled in props, they are used
41
+ ? DisplayState.Loading
42
+ : disabled
43
+ ? DisplayState.Disabled
44
+ : innerDisplayState); // otherwise use the inner state for pressed or enabled
45
+ const getSize = () => {
57
46
  switch (size) {
58
47
  case "small":
59
- return 30;
48
+ return { height: 30, mx: "15px" };
60
49
  case "large":
61
- return 50;
50
+ return { height: 50, mx: "30px" };
62
51
  }
63
- })();
52
+ };
64
53
  const spinnerColor = variant === "text" ? "blue100" : "white100";
65
54
  const handlePress = (event) => {
66
55
  if (onPress === undefined || onPress === null) {
67
56
  return;
68
57
  }
69
- if (disabled || loading) {
58
+ if (displayState === DisplayState.Loading || displayState === DisplayState.Disabled) {
70
59
  return;
71
60
  }
61
+ // Did someone tap really fast? Flick the highlighted state
62
+ if (displayState === DisplayState.Enabled) {
63
+ setInnerDisplayState(DisplayState.Pressed);
64
+ setTimeout(() => {
65
+ setInnerDisplayState(DisplayState.Enabled);
66
+ }, 0.3);
67
+ }
68
+ else {
69
+ // Was already selected
70
+ setInnerDisplayState(DisplayState.Enabled);
71
+ }
72
72
  if (haptic !== undefined) {
73
73
  react_native_haptic_feedback_1.default.trigger(haptic === true ? "impactLight" : haptic);
74
74
  }
75
75
  onPress(event);
76
76
  };
77
- const colorsForVariantAndState = (0, colors_1.useColorsForVariantAndState)();
78
- const containerColorsAnim = (0, react_native_reanimated_1.useAnimatedStyle)(() => {
79
- const colors = colorsForVariantAndState[variant];
80
- if (disabled) {
81
- return {
82
- backgroundColor: colors.disabled.bg,
83
- borderColor: colors.disabled.border,
84
- };
85
- }
86
- return {
87
- backgroundColor: (0, react_native_reanimated_1.interpolateColor)(pressAnimationProgress.value, [0, 1], [colors.active.bg, colors.pressed.bg]),
88
- borderColor: (0, react_native_reanimated_1.interpolateColor)(pressAnimationProgress.value, [0, 1], [colors.active.border, colors.pressed.border]),
89
- };
90
- });
91
- const textAnim = (0, react_native_reanimated_1.useAnimatedStyle)(() => {
92
- "worklet";
93
- const colors = colorsForVariantAndState[variant];
94
- if (loading) {
95
- return { color: "rgba(0, 0, 0, 0)" };
96
- }
97
- return {
98
- color: (0, react_native_reanimated_1.interpolateColor)(pressAnimationProgress.value, [0, 1], [colors.active.text, colors.pressed.text]),
99
- textDecorationLine: pressAnimationProgress.value > 0 ? "underline" : "none",
100
- };
101
- });
102
- return ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { disabled: disabled, onPressIn: () => {
103
- if (loading) {
104
- return;
105
- }
106
- setPressed(true);
107
- }, onPressOut: () => {
108
- if (loading) {
109
- return;
110
- }
111
- setPressed(false);
112
- }, onPress: handlePress, testID: testID, testOnly_pressed: testOnly_pressed, hitSlop: hitSlop, children: (0, jsx_runtime_1.jsx)(Flex_1.Flex, { flexDirection: "row", children: (0, jsx_runtime_1.jsx)(Flex_1.Flex, { ...restProps, height: height, width: block ? "100%" : undefined, borderRadius: 50, overflow: "hidden", children: (0, jsx_runtime_1.jsx)(AFlex, { borderWidth: 1, borderRadius: 50, overflow: "hidden", style: containerColorsAnim, children: (0, jsx_runtime_1.jsxs)(Flex_1.Flex, { height: "100%", mx: "25px", flexDirection: "row", alignItems: "center", justifyContent: "center", children: [iconPosition === "left-start" && !!icon ? ((0, jsx_runtime_1.jsxs)(Box_1.Box, { position: "absolute", left: 0, children: [icon, (0, jsx_runtime_1.jsx)(Spacer_1.Spacer, { x: 0.5 })] })) : null, iconPosition === "left" && !!icon ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon, (0, jsx_runtime_1.jsx)(Spacer_1.Spacer, { x: 0.5 })] })) : null, (0, jsx_runtime_1.jsx)(AText, { style: [{ width: Math.ceil(longestTextMeasurements.width) }, textStyle, textAnim], textAlign: "center", children: children }), (0, jsx_runtime_1.jsx)(MeasuredView_1.MeasuredView, { setMeasuredState: setLongestTextMeasurements, children: (0, jsx_runtime_1.jsx)(Text_1.Text, { color: "red", style: textStyle, children: longestText ? longestText : children }) }), iconPosition === "right" && !!icon ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Spacer_1.Spacer, { x: 0.5 }), icon] })) : null, loading ? ((0, jsx_runtime_1.jsx)(Box_1.Box, { position: "absolute", width: "100%", height: "100%", alignItems: "center", justifyContent: "center", children: (0, jsx_runtime_1.jsx)(Spinner_1.Spinner, { size: size, color: spinnerColor }) })) : null] }) }) }) }) }));
77
+ const containerSize = getSize();
78
+ const to = useStyleForVariantAndState(variant, testOnly_state ?? displayState);
79
+ return ((0, jsx_runtime_1.jsx)(renderprops_native_1.Spring, { native: true, to: to, config: react_spring_1.config.stiff, children: (springProps) => ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { hitSlop: hitSlop, testOnly_pressed: testOnly_state === DisplayState.Pressed, disabled: testOnly_state === DisplayState.Disabled || disabled, onPressIn: () => {
80
+ if (displayState === DisplayState.Loading) {
81
+ return;
82
+ }
83
+ setInnerDisplayState(DisplayState.Pressed);
84
+ }, onPressOut: () => {
85
+ if (displayState === DisplayState.Loading) {
86
+ return;
87
+ }
88
+ setInnerDisplayState(DisplayState.Enabled);
89
+ }, onPress: handlePress, testID: testID, children: (0, jsx_runtime_1.jsx)(Flex_1.Flex, { flexDirection: "row", children: (0, jsx_runtime_1.jsx)(AnimatedContainer, { ...rest, style: {
90
+ backgroundColor: springProps.backgroundColor,
91
+ borderColor: springProps.borderColor,
92
+ height: containerSize.height,
93
+ }, children: (0, jsx_runtime_1.jsxs)(Flex_1.Flex, { mx: containerSize.mx, children: [(0, jsx_runtime_1.jsxs)(Flex_1.Flex, { height: "100%", flexDirection: "row", alignItems: "center", justifyContent: "center", children: [iconPosition === "left-start" && !!icon ? ((0, jsx_runtime_1.jsxs)(Box_1.Box, { position: "absolute", left: 0, children: [icon, (0, jsx_runtime_1.jsx)(Spacer_1.Spacer, { x: 0.5 })] })) : null, iconPosition === "left" && !!icon ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon, (0, jsx_runtime_1.jsx)(Spacer_1.Spacer, { x: 0.5 })] })) : null, !__TEST__ && ((0, jsx_runtime_1.jsx)(MeasuredView_1.MeasuredView, { setMeasuredState: setLongestTextMeasurements, children: (0, jsx_runtime_1.jsx)(Text_1.Text, { color: "red", style: textStyle, children: longestText ? longestText : children }) })), (0, jsx_runtime_1.jsx)(AnimatedText, { style: [
94
+ {
95
+ width: Math.ceil(longestTextMeasurements.width),
96
+ color: springProps.textColor,
97
+ textDecorationLine: springProps.textDecorationLine,
98
+ },
99
+ textStyle,
100
+ ], textAlign: "center", children: children }), iconPosition === "right" && !!icon ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Spacer_1.Spacer, { x: 0.5 }), icon] })) : null] }), displayState === DisplayState.Loading ? ((0, jsx_runtime_1.jsx)(SpinnerContainer, { children: (0, jsx_runtime_1.jsx)(Spinner_1.Spinner, { size: size, color: spinnerColor }) })) : null] }) }) }) })) }));
113
101
  };
114
102
  exports.Button = Button;
115
- const AText = react_native_reanimated_1.default.createAnimatedComponent(Text_1.Text);
116
- const AFlex = react_native_reanimated_1.default.createAnimatedComponent(Flex_1.Flex);
117
- const useStateWithProp = (prop) => {
118
- const [state, setState] = (0, react_1.useState)(!!prop);
119
- (0, react_1.useEffect)(() => {
120
- setState(!!prop);
121
- }, [prop]);
122
- const stateV = (0, react_native_reanimated_1.useDerivedValue)(() => {
123
- "worklet";
124
- if (!!state) {
125
- return 1;
126
- }
127
- return 0;
128
- }, [state]);
129
- return [state, setState, stateV];
103
+ const useStyleForVariantAndState = (variant, state) => {
104
+ const color = (0, hooks_1.useColor)();
105
+ const retval = {
106
+ textDecorationLine: "none",
107
+ };
108
+ if (state === DisplayState.Loading) {
109
+ retval.backgroundColor = variant === "text" ? color("black10") : color("blue100");
110
+ retval.borderColor = "rgba(0, 0, 0, 0)";
111
+ retval.borderWidth = 0;
112
+ retval.textColor = "rgba(0, 0, 0, 0)";
113
+ return retval;
114
+ }
115
+ switch (variant) {
116
+ case "fillDark":
117
+ retval.textColor = color("white100");
118
+ switch (state) {
119
+ case DisplayState.Enabled:
120
+ retval.backgroundColor = color("black100");
121
+ retval.borderColor = color("black100");
122
+ break;
123
+ case DisplayState.Disabled:
124
+ retval.backgroundColor = color("black30");
125
+ retval.borderColor = color("black30");
126
+ break;
127
+ case DisplayState.Pressed:
128
+ retval.backgroundColor = color("blue100");
129
+ retval.borderColor = color("blue100");
130
+ retval.textDecorationLine = "underline";
131
+ break;
132
+ default:
133
+ assertNever(state);
134
+ }
135
+ break;
136
+ case "fillLight":
137
+ switch (state) {
138
+ case DisplayState.Enabled:
139
+ retval.backgroundColor = color("white100");
140
+ retval.borderColor = color("white100");
141
+ retval.textColor = color("black100");
142
+ break;
143
+ case DisplayState.Disabled:
144
+ retval.backgroundColor = color("black30");
145
+ retval.borderColor = color("black30");
146
+ retval.textColor = color("white100");
147
+ break;
148
+ case DisplayState.Pressed:
149
+ retval.backgroundColor = color("blue100");
150
+ retval.borderColor = color("blue100");
151
+ retval.textColor = color("white100");
152
+ retval.textDecorationLine = "underline";
153
+ break;
154
+ default:
155
+ assertNever(state);
156
+ }
157
+ break;
158
+ case "fillGray":
159
+ switch (state) {
160
+ case DisplayState.Enabled:
161
+ retval.backgroundColor = color("black10");
162
+ retval.borderColor = color("black10");
163
+ retval.textColor = color("black100");
164
+ break;
165
+ case DisplayState.Disabled:
166
+ retval.backgroundColor = color("black30");
167
+ retval.borderColor = color("black30");
168
+ retval.textColor = color("white100");
169
+ break;
170
+ case DisplayState.Pressed:
171
+ retval.backgroundColor = color("blue100");
172
+ retval.borderColor = color("blue100");
173
+ retval.textColor = color("white100");
174
+ retval.textDecorationLine = "underline";
175
+ break;
176
+ default:
177
+ assertNever(state);
178
+ }
179
+ break;
180
+ case "fillSuccess":
181
+ retval.textColor = color("white100");
182
+ switch (state) {
183
+ case DisplayState.Enabled:
184
+ retval.backgroundColor = color("blue100");
185
+ retval.borderColor = color("blue100");
186
+ break;
187
+ case DisplayState.Disabled:
188
+ retval.backgroundColor = color("blue100");
189
+ retval.borderColor = color("blue100");
190
+ break;
191
+ case DisplayState.Pressed:
192
+ retval.backgroundColor = color("blue10");
193
+ retval.borderColor = color("blue10");
194
+ retval.textDecorationLine = "underline";
195
+ break;
196
+ default:
197
+ assertNever(state);
198
+ }
199
+ break;
200
+ case "outline":
201
+ switch (state) {
202
+ case DisplayState.Enabled:
203
+ retval.backgroundColor = color("white100");
204
+ retval.borderColor = color("black60");
205
+ retval.textColor = color("black100");
206
+ break;
207
+ case DisplayState.Disabled:
208
+ retval.backgroundColor = color("white100");
209
+ retval.borderColor = color("black30");
210
+ retval.textColor = color("black30");
211
+ break;
212
+ case DisplayState.Pressed:
213
+ retval.backgroundColor = color("blue100");
214
+ retval.borderColor = color("blue100");
215
+ retval.textColor = color("white100");
216
+ retval.textDecorationLine = "underline";
217
+ break;
218
+ default:
219
+ assertNever(state);
220
+ }
221
+ break;
222
+ case "outlineGray":
223
+ switch (state) {
224
+ case DisplayState.Enabled:
225
+ retval.backgroundColor = color("white100");
226
+ retval.borderColor = color("black30");
227
+ retval.textColor = color("black100");
228
+ break;
229
+ case DisplayState.Disabled:
230
+ retval.backgroundColor = color("white100");
231
+ retval.borderColor = color("black30");
232
+ retval.textColor = color("black30");
233
+ break;
234
+ case DisplayState.Pressed:
235
+ retval.backgroundColor = color("blue100");
236
+ retval.borderColor = color("blue100");
237
+ retval.textColor = color("white100");
238
+ retval.textDecorationLine = "underline";
239
+ break;
240
+ default:
241
+ assertNever(state);
242
+ }
243
+ break;
244
+ case "outlineLight":
245
+ switch (state) {
246
+ case DisplayState.Enabled:
247
+ retval.backgroundColor = "rgba(0, 0, 0, 0)";
248
+ retval.borderColor = color("white100");
249
+ retval.textColor = color("white100");
250
+ break;
251
+ case DisplayState.Disabled:
252
+ retval.backgroundColor = "rgba(0, 0, 0, 0)";
253
+ retval.borderColor = color("black30");
254
+ retval.textColor = color("black30");
255
+ break;
256
+ case DisplayState.Pressed:
257
+ retval.backgroundColor = color("blue100");
258
+ retval.borderColor = color("blue100");
259
+ retval.textColor = color("white100");
260
+ retval.textDecorationLine = "underline";
261
+ break;
262
+ default:
263
+ assertNever(state);
264
+ }
265
+ break;
266
+ case "text":
267
+ retval.backgroundColor = "rgba(0, 0, 0, 0)";
268
+ retval.borderColor = "rgba(0, 0, 0, 0)";
269
+ switch (state) {
270
+ case DisplayState.Enabled:
271
+ retval.textColor = color("black100");
272
+ break;
273
+ case DisplayState.Disabled:
274
+ retval.textColor = color("black30");
275
+ break;
276
+ case DisplayState.Pressed:
277
+ retval.textColor = color("blue100");
278
+ retval.textDecorationLine = "underline";
279
+ break;
280
+ default:
281
+ assertNever(state);
282
+ }
283
+ break;
284
+ default:
285
+ assertNever(variant);
286
+ }
287
+ return retval;
130
288
  };
289
+ const Container = (0, native_1.default)(Box_1.Box) `
290
+ position: relative;
291
+ border-width: 1px;
292
+ border-radius: 50px;
293
+ width: ${(p) => (p.block ? "100%" : "auto")};
294
+ overflow: hidden;
295
+ `;
296
+ const SpinnerContainer = (0, native_1.default)(Box_1.Box) `
297
+ position: absolute;
298
+ width: 100%;
299
+ height: 100%;
300
+ align-items: center;
301
+ justify-content: center;
302
+ `;
303
+ const AnimatedContainer = (0, renderprops_native_1.animated)(Container);
304
+ const AnimatedText = (0, renderprops_native_1.animated)(Text_1.Text);
@@ -1,5 +1,5 @@
1
1
  /// <reference types="react" />
2
- import { ButtonProps } from "./Button";
2
+ import { ButtonProps } from ".";
3
3
  type FollowButtonProps = Omit<ButtonProps, "variant" | "size" | "longestText" | "icon" | "children"> & {
4
4
  isFollowed: boolean;
5
5
  };
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FollowButton = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const Button_1 = require("./Button");
6
- const svgs_1 = require("../../svgs");
5
+ const _1 = require(".");
6
+ const CheckIcon_1 = require("../../svgs/CheckIcon");
7
7
  const FollowButton = ({ isFollowed, ...restProps }) => {
8
- return ((0, jsx_runtime_1.jsx)(Button_1.Button, { variant: isFollowed ? "outline" : "outlineGray", size: "small", longestText: "Following", icon: isFollowed && (0, jsx_runtime_1.jsx)(svgs_1.CheckIcon, { fill: "black60", width: "16px", height: "16px" }), ...restProps, children: isFollowed ? "Following" : "Follow" }));
8
+ return ((0, jsx_runtime_1.jsx)(_1.Button, { variant: isFollowed ? "outline" : "outlineGray", size: "small", longestText: "Following", icon: isFollowed && (0, jsx_runtime_1.jsx)(CheckIcon_1.CheckIcon, { fill: "black60", width: "16px", height: "16px" }), ...restProps, children: isFollowed ? "Following" : "Follow" }));
9
9
  };
10
10
  exports.FollowButton = FollowButton;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LinkButton = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const __1 = require("..");
5
6
  const Text_1 = require("../Text");
6
- const Touchable_1 = require("../Touchable");
7
- const LinkButton = (props) => ((0, jsx_runtime_1.jsx)(Touchable_1.Touchable, { onPress: props.onPress, children: (0, jsx_runtime_1.jsx)(Text_1.Text, { underline: true, ...props }) }));
7
+ const LinkButton = (props) => ((0, jsx_runtime_1.jsx)(__1.Touchable, { onPress: props.onPress, children: (0, jsx_runtime_1.jsx)(Text_1.Text, { underline: true, ...props }) }));
8
8
  exports.LinkButton = LinkButton;
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useColorsForVariantAndState = void 0;
4
- const hooks_1 = require("../../utils/hooks");
4
+ const useColor_1 = require("../../utils/hooks/useColor");
5
5
  const useColorsForVariantAndState = () => {
6
- const color = (0, hooks_1.useColor)();
6
+ const color = (0, useColor_1.useColor)();
7
7
  return {
8
8
  fillDark: {
9
9
  disabled: { bg: color("black30"), border: color("black30"), text: color("onPrimaryHigh") },
@@ -1,4 +1,4 @@
1
1
  export * from "./Button";
2
2
  export * from "./CTAButton";
3
- export * from "./FollowButton";
4
3
  export * from "./LinkButton";
4
+ export * from "./FollowButton";
@@ -16,5 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./Button"), exports);
18
18
  __exportStar(require("./CTAButton"), exports);
19
- __exportStar(require("./FollowButton"), exports);
20
19
  __exportStar(require("./LinkButton"), exports);
20
+ __exportStar(require("./FollowButton"), exports);
@@ -0,0 +1,34 @@
1
+ /// <reference types="react" />
2
+ import { PressableProps } from "react-native";
3
+ import { HapticFeedbackTypes } from "react-native-haptic-feedback";
4
+ import { BoxProps } from "../Box";
5
+ type ButtonSize = "small" | "large";
6
+ type ButtonVariant = "fillDark" | "fillLight" | "fillGray" | "fillSuccess" | "outline" | "outlineGray" | "outlineLight" | "text";
7
+ export interface ButtonProps extends BoxProps {
8
+ children: React.ReactNode;
9
+ size?: ButtonSize;
10
+ variant?: ButtonVariant;
11
+ onPress?: PressableProps["onPress"];
12
+ icon?: React.ReactNode;
13
+ iconPosition?: "left" | "left-start" | "right";
14
+ /**
15
+ * `haptic` can be used like:
16
+ * <Button haptic />
17
+ * or
18
+ * <Button haptic="impactHeavy" />
19
+ * to add haptic feedback on the button.
20
+ */
21
+ haptic?: HapticFeedbackTypes | true;
22
+ /** Displays a loader in the button */
23
+ loading?: boolean;
24
+ /** Disabled interactions */
25
+ disabled?: boolean;
26
+ /** Makes button full width */
27
+ block?: boolean;
28
+ /** Pass the longest text to the button for the button to keep longest text width */
29
+ longestText?: string;
30
+ /** Used only for tests and stories */
31
+ testOnly_pressed?: PressableProps["testOnly_pressed"];
32
+ }
33
+ export declare const Button: ({ children, disabled: disabledProp, haptic, icon, iconPosition, loading: loadingProp, block, longestText, onPress, size, variant, testOnly_pressed, testID, hitSlop, ...restProps }: ButtonProps) => JSX.Element;
34
+ export {};
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ exports.Button = void 0;
30
+ const jsx_runtime_1 = require("react/jsx-runtime");
31
+ const react_1 = require("react");
32
+ const react_native_1 = require("react-native");
33
+ const react_native_haptic_feedback_1 = __importDefault(require("react-native-haptic-feedback"));
34
+ const react_native_reanimated_1 = __importStar(require("react-native-reanimated"));
35
+ const colors_1 = require("./colors");
36
+ const MeasuredView_1 = require("../../elements/MeasuredView");
37
+ const Box_1 = require("../Box");
38
+ const Flex_1 = require("../Flex");
39
+ const Spacer_1 = require("../Spacer");
40
+ const Spinner_1 = require("../Spinner");
41
+ const Text_1 = require("../Text");
42
+ const ANIMATION_DURATION = 150;
43
+ const Button = ({ children, disabled: disabledProp, haptic, icon, iconPosition = "left", loading: loadingProp, block, longestText, onPress, size = "large", variant = "fillDark", testOnly_pressed, testID, hitSlop, ...restProps }) => {
44
+ const [disabled, setDisabled, disabledV] = useStateWithProp(!!disabledProp);
45
+ const [loading, setLoading, loadingV] = useStateWithProp(!!loadingProp);
46
+ const [pressed, setPressed, pressedV] = useStateWithProp(!!testOnly_pressed);
47
+ const pressAnimationProgress = (0, react_native_reanimated_1.useSharedValue)(0);
48
+ (0, react_native_reanimated_1.useAnimatedReaction)(() => pressedV.value, (pressedVal) => {
49
+ pressAnimationProgress.value = (0, react_native_reanimated_1.withTiming)(pressedVal, { duration: ANIMATION_DURATION });
50
+ });
51
+ const textStyle = (0, Text_1.useTextStyleForPalette)(size === "small" ? "xs" : "sm");
52
+ const [longestTextMeasurements, setLongestTextMeasurements] = (0, react_1.useState)({
53
+ width: 0,
54
+ height: 0,
55
+ });
56
+ const height = (() => {
57
+ switch (size) {
58
+ case "small":
59
+ return 30;
60
+ case "large":
61
+ return 50;
62
+ }
63
+ })();
64
+ const spinnerColor = variant === "text" ? "blue100" : "white100";
65
+ const handlePress = (event) => {
66
+ if (onPress === undefined || onPress === null) {
67
+ return;
68
+ }
69
+ if (disabled || loading) {
70
+ return;
71
+ }
72
+ if (haptic !== undefined) {
73
+ react_native_haptic_feedback_1.default.trigger(haptic === true ? "impactLight" : haptic);
74
+ }
75
+ onPress(event);
76
+ };
77
+ const colorsForVariantAndState = (0, colors_1.useColorsForVariantAndState)();
78
+ const containerColorsAnim = (0, react_native_reanimated_1.useAnimatedStyle)(() => {
79
+ const colors = colorsForVariantAndState[variant];
80
+ if (disabled) {
81
+ return {
82
+ backgroundColor: colors.disabled.bg,
83
+ borderColor: colors.disabled.border,
84
+ };
85
+ }
86
+ return {
87
+ backgroundColor: (0, react_native_reanimated_1.interpolateColor)(pressAnimationProgress.value, [0, 1], [colors.active.bg, colors.pressed.bg]),
88
+ borderColor: (0, react_native_reanimated_1.interpolateColor)(pressAnimationProgress.value, [0, 1], [colors.active.border, colors.pressed.border]),
89
+ };
90
+ });
91
+ const textAnim = (0, react_native_reanimated_1.useAnimatedStyle)(() => {
92
+ "worklet";
93
+ const colors = colorsForVariantAndState[variant];
94
+ if (loading) {
95
+ return { color: "rgba(0, 0, 0, 0)" };
96
+ }
97
+ return {
98
+ color: (0, react_native_reanimated_1.interpolateColor)(pressAnimationProgress.value, [0, 1], [colors.active.text, colors.pressed.text]),
99
+ textDecorationLine: pressAnimationProgress.value > 0 ? "underline" : "none",
100
+ };
101
+ });
102
+ return ((0, jsx_runtime_1.jsx)(react_native_1.Pressable, { disabled: disabled, onPressIn: () => {
103
+ if (loading) {
104
+ return;
105
+ }
106
+ setPressed(true);
107
+ }, onPressOut: () => {
108
+ if (loading) {
109
+ return;
110
+ }
111
+ setPressed(false);
112
+ }, onPress: handlePress, testID: testID, testOnly_pressed: testOnly_pressed, hitSlop: hitSlop, children: (0, jsx_runtime_1.jsx)(Flex_1.Flex, { flexDirection: "row", children: (0, jsx_runtime_1.jsx)(Flex_1.Flex, { ...restProps, height: height, width: block ? "100%" : undefined, borderRadius: 50, overflow: "hidden", children: (0, jsx_runtime_1.jsx)(AFlex, { borderWidth: 1, borderRadius: 50, overflow: "hidden", style: containerColorsAnim, children: (0, jsx_runtime_1.jsxs)(Flex_1.Flex, { height: "100%", mx: "25px", flexDirection: "row", alignItems: "center", justifyContent: "center", children: [iconPosition === "left-start" && !!icon ? ((0, jsx_runtime_1.jsxs)(Box_1.Box, { position: "absolute", left: 0, children: [icon, (0, jsx_runtime_1.jsx)(Spacer_1.Spacer, { x: 0.5 })] })) : null, iconPosition === "left" && !!icon ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon, (0, jsx_runtime_1.jsx)(Spacer_1.Spacer, { x: 0.5 })] })) : null, (0, jsx_runtime_1.jsx)(AText, { style: [{ width: Math.ceil(longestTextMeasurements.width) }, textStyle, textAnim], textAlign: "center", children: children }), (0, jsx_runtime_1.jsx)(MeasuredView_1.MeasuredView, { setMeasuredState: setLongestTextMeasurements, children: (0, jsx_runtime_1.jsx)(Text_1.Text, { color: "red", style: textStyle, children: longestText ? longestText : children }) }), iconPosition === "right" && !!icon ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Spacer_1.Spacer, { x: 0.5 }), icon] })) : null, loading ? ((0, jsx_runtime_1.jsx)(Box_1.Box, { position: "absolute", width: "100%", height: "100%", alignItems: "center", justifyContent: "center", children: (0, jsx_runtime_1.jsx)(Spinner_1.Spinner, { size: size, color: spinnerColor }) })) : null] }) }) }) }) }));
113
+ };
114
+ exports.Button = Button;
115
+ const AText = react_native_reanimated_1.default.createAnimatedComponent(Text_1.Text);
116
+ const AFlex = react_native_reanimated_1.default.createAnimatedComponent(Flex_1.Flex);
117
+ const useStateWithProp = (prop) => {
118
+ const [state, setState] = (0, react_1.useState)(!!prop);
119
+ (0, react_1.useEffect)(() => {
120
+ setState(!!prop);
121
+ }, [prop]);
122
+ const stateV = (0, react_native_reanimated_1.useDerivedValue)(() => {
123
+ "worklet";
124
+ if (!!state) {
125
+ return 1;
126
+ }
127
+ return 0;
128
+ }, [state]);
129
+ return [state, setState, stateV];
130
+ };
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ import { ButtonProps } from "./Button";
3
+ export declare const CTAButton: (props: ButtonProps) => JSX.Element;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CTAButton = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const Button_1 = require("./Button");
6
+ const CTAButton = (props) => (0, jsx_runtime_1.jsx)(Button_1.Button, { block: true, haptic: true, ...props });
7
+ exports.CTAButton = CTAButton;
@@ -0,0 +1,7 @@
1
+ /// <reference types="react" />
2
+ import { ButtonProps } from "./Button";
3
+ type FollowButtonProps = Omit<ButtonProps, "variant" | "size" | "longestText" | "icon" | "children"> & {
4
+ isFollowed: boolean;
5
+ };
6
+ export declare const FollowButton: ({ isFollowed, ...restProps }: FollowButtonProps) => JSX.Element;
7
+ export {};
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FollowButton = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const Button_1 = require("./Button");
6
+ const svgs_1 = require("../../svgs");
7
+ const FollowButton = ({ isFollowed, ...restProps }) => {
8
+ return ((0, jsx_runtime_1.jsx)(Button_1.Button, { variant: isFollowed ? "outline" : "outlineGray", size: "small", longestText: "Following", icon: isFollowed && (0, jsx_runtime_1.jsx)(svgs_1.CheckIcon, { fill: "black60", width: "16px", height: "16px" }), ...restProps, children: isFollowed ? "Following" : "Follow" }));
9
+ };
10
+ exports.FollowButton = FollowButton;
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ import { TextProps } from "../Text";
3
+ export declare const LinkButton: (props: TextProps) => JSX.Element;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LinkButton = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const Text_1 = require("../Text");
6
+ const Touchable_1 = require("../Touchable");
7
+ const LinkButton = (props) => ((0, jsx_runtime_1.jsx)(Touchable_1.Touchable, { onPress: props.onPress, children: (0, jsx_runtime_1.jsx)(Text_1.Text, { underline: true, ...props }) }));
8
+ exports.LinkButton = LinkButton;
@@ -0,0 +1,9 @@
1
+ import { ButtonProps } from "./Button";
2
+ import { NoUndefined } from "../../utils/types";
3
+ type State = "disabled" | "pressed" | "active";
4
+ export declare const useColorsForVariantAndState: () => Record<NoUndefined<ButtonProps["variant"]>, Record<State, {
5
+ bg: string;
6
+ border: string;
7
+ text: string;
8
+ }>>;
9
+ export {};
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useColorsForVariantAndState = void 0;
4
+ const hooks_1 = require("../../utils/hooks");
5
+ const useColorsForVariantAndState = () => {
6
+ const color = (0, hooks_1.useColor)();
7
+ return {
8
+ fillDark: {
9
+ disabled: { bg: color("black30"), border: color("black30"), text: color("onPrimaryHigh") },
10
+ pressed: { bg: color("blue100"), border: color("blue100"), text: color("onPrimaryHigh") },
11
+ active: { bg: color("primary"), border: color("primary"), text: color("onPrimaryHigh") },
12
+ },
13
+ fillLight: {
14
+ disabled: { bg: color("black30"), border: color("black30"), text: color("onPrimaryHigh") },
15
+ pressed: { bg: color("blue100"), border: color("blue100"), text: color("onPrimaryHigh") },
16
+ active: {
17
+ bg: color("white100"),
18
+ border: color("white100"),
19
+ text: color("black100"),
20
+ },
21
+ },
22
+ fillGray: {
23
+ disabled: { bg: color("black30"), border: color("black30"), text: color("white100") },
24
+ pressed: { bg: color("blue100"), border: color("blue100"), text: color("white100") },
25
+ active: { bg: color("black10"), border: color("black10"), text: color("black100") },
26
+ },
27
+ fillSuccess: {
28
+ disabled: { bg: color("blue100"), border: color("blue100"), text: color("white100") },
29
+ pressed: { bg: color("blue100"), border: color("blue100"), text: color("white100") },
30
+ active: { bg: color("blue10"), border: color("blue10"), text: color("white100") },
31
+ },
32
+ outline: {
33
+ disabled: {
34
+ bg: color("background"),
35
+ border: color("onBackgroundLow"),
36
+ text: color("onBackgroundLow"),
37
+ },
38
+ pressed: { bg: color("blue100"), border: color("blue100"), text: color("white100") },
39
+ active: {
40
+ bg: color("background"),
41
+ border: color("onBackgroundMedium"),
42
+ text: color("onBackgroundHigh"),
43
+ },
44
+ },
45
+ outlineGray: {
46
+ disabled: {
47
+ bg: color("white100"),
48
+ border: color("black30"),
49
+ text: color("black30"),
50
+ },
51
+ pressed: { bg: color("blue100"), border: color("blue100"), text: color("white100") },
52
+ active: {
53
+ bg: color("white100"),
54
+ border: color("black30"),
55
+ text: color("black100"),
56
+ },
57
+ },
58
+ outlineLight: {
59
+ disabled: {
60
+ bg: "rgba(0, 0, 0, 0)",
61
+ border: color("black30"),
62
+ text: color("black30"),
63
+ },
64
+ pressed: { bg: color("blue100"), border: color("blue100"), text: color("white100") },
65
+ active: {
66
+ bg: "rgba(0, 0, 0, 0)",
67
+ border: color("white100"),
68
+ text: color("white100"),
69
+ },
70
+ },
71
+ text: {
72
+ disabled: { bg: "rgba(0, 0, 0, 0)", border: "rgba(0, 0, 0, 0)", text: color("black30") },
73
+ pressed: { bg: color("black10"), border: color("black10"), text: color("blue100") },
74
+ active: { bg: "rgba(0, 0, 0, 0)", border: "rgba(0, 0, 0, 0)", text: color("black100") },
75
+ },
76
+ };
77
+ };
78
+ exports.useColorsForVariantAndState = useColorsForVariantAndState;
@@ -0,0 +1,4 @@
1
+ export * from "./Button";
2
+ export * from "./CTAButton";
3
+ export * from "./FollowButton";
4
+ export * from "./LinkButton";
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./Button"), exports);
18
+ __exportStar(require("./CTAButton"), exports);
19
+ __exportStar(require("./FollowButton"), exports);
20
+ __exportStar(require("./LinkButton"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artsy/palette-mobile",
3
- "version": "11.0.18",
3
+ "version": "11.0.20",
4
4
  "description": "Artsy's design system for React Native",
5
5
  "scripts": {
6
6
  "android": "react-native run-android",
@@ -24,7 +24,7 @@
24
24
  "setup:artsy": "./scripts/download-fonts",
25
25
  "start:reset-cache": "react-native start --reset-cache",
26
26
  "start": "react-native start",
27
- "../../storybook-watcher": "sb-rn-watcher",
27
+ "storybook-watcher": "sb-rn-watcher",
28
28
  "test": "jest",
29
29
  "type-check": "tsc --noEmit"
30
30
  },
@@ -39,6 +39,7 @@
39
39
  "events": "^3.3.0",
40
40
  "lodash": "^4.17.21",
41
41
  "react-nanny": "^2.15.0",
42
+ "react-spring": "8.0.23",
42
43
  "styled-system": "^5.1.5"
43
44
  },
44
45
  "peerDependenciesComments": [