@jobber/components-native 0.75.5 → 0.76.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +2 -2
- package/dist/src/Button/Button.js +8 -5
- package/dist/src/Text/Text.js +2 -2
- package/dist/src/Typography/Typography.js +4 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/Button/Button.d.ts +14 -1
- package/dist/types/src/Text/Text.d.ts +9 -3
- package/dist/types/src/Typography/Typography.d.ts +6 -2
- package/package.json +2 -2
- package/src/Button/Button.test.tsx +88 -1
- package/src/Button/Button.tsx +32 -5
- package/src/Text/Text.test.tsx +20 -0
- package/src/Text/Text.tsx +11 -1
- package/src/Typography/Typography.test.tsx +14 -0
- package/src/Typography/Typography.tsx +11 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StyleProp, ViewStyle } from "react-native";
|
|
1
2
|
import { IconNames } from "@jobber/design";
|
|
2
3
|
import { XOR } from "ts-xor";
|
|
3
4
|
import { ButtonSize, ButtonType, ButtonVariation } from "./types";
|
|
@@ -58,6 +59,18 @@ interface CommonButtonProps {
|
|
|
58
59
|
* Used to locate this view in end-to-end tests.
|
|
59
60
|
*/
|
|
60
61
|
readonly testID?: string;
|
|
62
|
+
/**
|
|
63
|
+
* **Use at your own risk:** Custom style for specific elements. This should only be used as a
|
|
64
|
+
* **last resort**. Using this may result in unexpected side effects.
|
|
65
|
+
* More information [here](https://atlantis.getjobber.com/storybook/?path=/docs/guides-customizing-components--docs#unsafe_-props).
|
|
66
|
+
*/
|
|
67
|
+
readonly UNSAFE_style?: ButtonUnsafeStyle;
|
|
68
|
+
}
|
|
69
|
+
export interface ButtonUnsafeStyle {
|
|
70
|
+
container?: StyleProp<ViewStyle>;
|
|
71
|
+
contentContainer?: StyleProp<ViewStyle>;
|
|
72
|
+
iconContainer?: StyleProp<ViewStyle>;
|
|
73
|
+
actionLabelContainer?: StyleProp<ViewStyle>;
|
|
61
74
|
}
|
|
62
75
|
interface LabelButton extends CommonButtonProps {
|
|
63
76
|
/**
|
|
@@ -70,5 +83,5 @@ interface IconButton extends CommonButtonProps {
|
|
|
70
83
|
readonly accessibilityLabel: string;
|
|
71
84
|
}
|
|
72
85
|
export type ButtonProps = XOR<LabelButton, IconButton>;
|
|
73
|
-
export declare function Button({ label, onPress, variation, type, fullHeight, fullWidth, disabled, loading, size, accessibilityLabel, accessibilityHint, icon, testID, }: ButtonProps): JSX.Element;
|
|
86
|
+
export declare function Button({ label, onPress, variation, type, fullHeight, fullWidth, disabled, loading, size, accessibilityLabel, accessibilityHint, icon, testID, UNSAFE_style, }: ButtonProps): JSX.Element;
|
|
74
87
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TextAlign, TextVariation, TruncateLength, TypographyProps } from "../Typography";
|
|
2
|
-
|
|
2
|
+
import { TypographyUnsafeStyle } from "../Typography/Typography";
|
|
3
|
+
export interface TextProps extends Pick<TypographyProps<"base">, "maxFontScaleSize" | "selectable"> {
|
|
3
4
|
/**
|
|
4
5
|
* Visual hierarchy of the text
|
|
5
6
|
*/
|
|
@@ -59,8 +60,13 @@ interface TextProps extends Pick<TypographyProps<"base">, "maxFontScaleSize" | "
|
|
|
59
60
|
* of the TextInput
|
|
60
61
|
*/
|
|
61
62
|
readonly hideFromScreenReader?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* **Use at your own risk:** Custom style for specific elements. This should only be used as a
|
|
65
|
+
* **last resort**. Using this may result in unexpected side effects.
|
|
66
|
+
* More information [here](https://atlantis.getjobber.com/storybook/?path=/docs/guides-customizing-components--docs#unsafe_-props).
|
|
67
|
+
*/
|
|
68
|
+
readonly UNSAFE_style?: TypographyUnsafeStyle;
|
|
62
69
|
}
|
|
63
70
|
export type TextLevel = "text" | "textSupporting";
|
|
64
71
|
export declare const TEXT_MAX_SCALED_FONT_SIZES: Record<TextLevel, number>;
|
|
65
|
-
export declare function Text({ level, variation, emphasis, allowFontScaling, adjustsFontSizeToFit, maxLines, align, children, reverseTheme, strikeThrough, italic, hideFromScreenReader, maxFontScaleSize, underline, selectable, }: TextProps): JSX.Element;
|
|
66
|
-
export {};
|
|
72
|
+
export declare function Text({ level, variation, emphasis, allowFontScaling, adjustsFontSizeToFit, maxLines, align, children, reverseTheme, strikeThrough, italic, hideFromScreenReader, maxFontScaleSize, UNSAFE_style, underline, selectable, }: TextProps): JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { TextProps } from "react-native";
|
|
2
|
+
import { StyleProp, TextProps, TextStyle } from "react-native";
|
|
3
3
|
export interface TypographyProps<T extends FontFamily> extends Pick<TextProps, "selectable"> {
|
|
4
4
|
/**
|
|
5
5
|
* Text capitalization
|
|
@@ -85,9 +85,13 @@ export interface TypographyProps<T extends FontFamily> extends Pick<TextProps, "
|
|
|
85
85
|
* Have text styled with strike through
|
|
86
86
|
*/
|
|
87
87
|
readonly strikeThrough?: boolean;
|
|
88
|
+
readonly UNSAFE_style?: TypographyUnsafeStyle;
|
|
89
|
+
}
|
|
90
|
+
export interface TypographyUnsafeStyle {
|
|
91
|
+
textStyle?: StyleProp<TextStyle>;
|
|
88
92
|
}
|
|
89
93
|
export declare const Typography: React.MemoExoticComponent<typeof InternalTypography>;
|
|
90
|
-
declare function InternalTypography<T extends FontFamily = "base">({ fontFamily, fontStyle, fontWeight, transform, color, align, size, children, maxLines, allowFontScaling, maxFontScaleSize, adjustsFontSizeToFit, lineHeight, letterSpacing, reverseTheme, hideFromScreenReader, accessibilityRole, strikeThrough, underline, selectable, }: TypographyProps<T>): JSX.Element;
|
|
94
|
+
declare function InternalTypography<T extends FontFamily = "base">({ fontFamily, fontStyle, fontWeight, transform, color, align, size, children, maxLines, allowFontScaling, maxFontScaleSize, adjustsFontSizeToFit, lineHeight, letterSpacing, reverseTheme, hideFromScreenReader, accessibilityRole, strikeThrough, underline, UNSAFE_style, selectable, }: TypographyProps<T>): JSX.Element;
|
|
91
95
|
export type FontFamily = "base" | "display";
|
|
92
96
|
export type FontStyle = "regular" | "italic";
|
|
93
97
|
export type FontWeight = "regular" | "medium" | "bold" | "semiBold" | "extraBold" | "black";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.76.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React Native implementation of Atlantis",
|
|
6
6
|
"repository": {
|
|
@@ -80,5 +80,5 @@
|
|
|
80
80
|
"react-native-safe-area-context": "^4.5.2",
|
|
81
81
|
"react-native-svg": ">=12.0.0"
|
|
82
82
|
},
|
|
83
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "3dbb361d102c6ae833d1dce373125b7bf68508c0"
|
|
84
84
|
}
|
|
@@ -44,7 +44,7 @@ function renderButton(element: ReactElement) {
|
|
|
44
44
|
expect(instance.getByText(element.props.label)).toBeDefined();
|
|
45
45
|
|
|
46
46
|
const buttonStyleEl = button.children[0] as ReactTestInstance;
|
|
47
|
-
const buttonStyle = buttonStyleEl.props.style.reduce(
|
|
47
|
+
const buttonStyle = buttonStyleEl.props.style.flat().reduce(
|
|
48
48
|
(mergedStyles: CSSProperties, additionalStyles: CSSProperties) => ({
|
|
49
49
|
...mergedStyles,
|
|
50
50
|
...additionalStyles,
|
|
@@ -298,4 +298,91 @@ describe("Button", () => {
|
|
|
298
298
|
expect(handlePress).toHaveBeenCalledTimes(1);
|
|
299
299
|
});
|
|
300
300
|
});
|
|
301
|
+
|
|
302
|
+
describe("UNSAFE_style", () => {
|
|
303
|
+
it("should apply the container style override", () => {
|
|
304
|
+
const containerStyle = {
|
|
305
|
+
backgroundColor: "red",
|
|
306
|
+
borderColor: tokens["color-base-red--500"],
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
const { buttonStyle } = renderButton(
|
|
310
|
+
<Button
|
|
311
|
+
label="Override"
|
|
312
|
+
onPress={jest.fn()}
|
|
313
|
+
UNSAFE_style={{ container: containerStyle }}
|
|
314
|
+
/>,
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
expect(buttonStyle).toMatchObject(containerStyle);
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it("should apply the contentContainer style override to labels", () => {
|
|
321
|
+
const contentContainerStyle = { padding: 10 };
|
|
322
|
+
|
|
323
|
+
const { getByTestId } = renderButton(
|
|
324
|
+
<Button
|
|
325
|
+
label="Override"
|
|
326
|
+
onPress={jest.fn()}
|
|
327
|
+
UNSAFE_style={{ contentContainer: contentContainerStyle }}
|
|
328
|
+
/>,
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
const contentContainer = getByTestId("contentContainer");
|
|
332
|
+
expect(contentContainer.props.style).toContainEqual(
|
|
333
|
+
contentContainerStyle,
|
|
334
|
+
);
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
it("should apply the contentContainer style override to icons", () => {
|
|
338
|
+
const contentContainerStyle = { padding: 10 };
|
|
339
|
+
|
|
340
|
+
const { getByTestId } = renderButton(
|
|
341
|
+
<Button
|
|
342
|
+
label="Cog"
|
|
343
|
+
icon="cog"
|
|
344
|
+
onPress={jest.fn()}
|
|
345
|
+
UNSAFE_style={{ contentContainer: contentContainerStyle }}
|
|
346
|
+
/>,
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
const contentContainer = getByTestId("contentContainer");
|
|
350
|
+
expect(contentContainer.props.style).toContainEqual(
|
|
351
|
+
contentContainerStyle,
|
|
352
|
+
);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it("should apply the iconContainer style override", () => {
|
|
356
|
+
const iconContainerStyle = { margin: 5 };
|
|
357
|
+
|
|
358
|
+
const { getByTestId } = renderButton(
|
|
359
|
+
<Button
|
|
360
|
+
label="Cog"
|
|
361
|
+
icon="cog"
|
|
362
|
+
onPress={jest.fn()}
|
|
363
|
+
UNSAFE_style={{ iconContainer: iconContainerStyle }}
|
|
364
|
+
/>,
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
const iconContainer = getByTestId("iconContainer");
|
|
368
|
+
expect(iconContainer.props.style).toContainEqual(iconContainerStyle);
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
it("should apply the actionLabelContainer style override", () => {
|
|
372
|
+
const actionLabelContainerStyle = { margin: 5 };
|
|
373
|
+
|
|
374
|
+
const { getByTestId } = renderButton(
|
|
375
|
+
<Button
|
|
376
|
+
label="Override"
|
|
377
|
+
onPress={jest.fn()}
|
|
378
|
+
UNSAFE_style={{ actionLabelContainer: actionLabelContainerStyle }}
|
|
379
|
+
/>,
|
|
380
|
+
);
|
|
381
|
+
|
|
382
|
+
const actionLabelContainer = getByTestId("actionLabelContainer");
|
|
383
|
+
expect(actionLabelContainer.props.style).toContainEqual(
|
|
384
|
+
actionLabelContainerStyle,
|
|
385
|
+
);
|
|
386
|
+
});
|
|
387
|
+
});
|
|
301
388
|
});
|
package/src/Button/Button.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import { TouchableHighlight, View } from "react-native";
|
|
2
|
+
import { StyleProp, TouchableHighlight, View, ViewStyle } from "react-native";
|
|
3
3
|
import { IconColorNames, IconNames } from "@jobber/design";
|
|
4
4
|
import { XOR } from "ts-xor";
|
|
5
5
|
import { styles } from "./Button.style";
|
|
@@ -77,6 +77,20 @@ interface CommonButtonProps {
|
|
|
77
77
|
* Used to locate this view in end-to-end tests.
|
|
78
78
|
*/
|
|
79
79
|
readonly testID?: string;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* **Use at your own risk:** Custom style for specific elements. This should only be used as a
|
|
83
|
+
* **last resort**. Using this may result in unexpected side effects.
|
|
84
|
+
* More information [here](https://atlantis.getjobber.com/storybook/?path=/docs/guides-customizing-components--docs#unsafe_-props).
|
|
85
|
+
*/
|
|
86
|
+
readonly UNSAFE_style?: ButtonUnsafeStyle;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface ButtonUnsafeStyle {
|
|
90
|
+
container?: StyleProp<ViewStyle>;
|
|
91
|
+
contentContainer?: StyleProp<ViewStyle>;
|
|
92
|
+
iconContainer?: StyleProp<ViewStyle>;
|
|
93
|
+
actionLabelContainer?: StyleProp<ViewStyle>;
|
|
80
94
|
}
|
|
81
95
|
|
|
82
96
|
interface LabelButton extends CommonButtonProps {
|
|
@@ -107,6 +121,7 @@ export function Button({
|
|
|
107
121
|
accessibilityHint,
|
|
108
122
|
icon,
|
|
109
123
|
testID,
|
|
124
|
+
UNSAFE_style,
|
|
110
125
|
}: ButtonProps): JSX.Element {
|
|
111
126
|
const buttonStyle = [
|
|
112
127
|
styles.button,
|
|
@@ -141,11 +156,20 @@ export function Button({
|
|
|
141
156
|
fullHeight && styles.fullHeight,
|
|
142
157
|
]}
|
|
143
158
|
>
|
|
144
|
-
<View style={buttonStyle}>
|
|
159
|
+
<View style={[buttonStyle, UNSAFE_style?.container]}>
|
|
145
160
|
{loading && <InternalButtonLoading variation={variation} type={type} />}
|
|
146
|
-
<View
|
|
161
|
+
<View
|
|
162
|
+
style={[
|
|
163
|
+
getContentStyles(label, icon),
|
|
164
|
+
UNSAFE_style?.contentContainer,
|
|
165
|
+
]}
|
|
166
|
+
testID="contentContainer"
|
|
167
|
+
>
|
|
147
168
|
{icon && (
|
|
148
|
-
<View
|
|
169
|
+
<View
|
|
170
|
+
style={[styles.iconStyle, UNSAFE_style?.iconContainer]}
|
|
171
|
+
testID="iconContainer"
|
|
172
|
+
>
|
|
149
173
|
<Icon
|
|
150
174
|
name={icon}
|
|
151
175
|
color={getIconColorVariation(variation, type, disabled)}
|
|
@@ -153,7 +177,10 @@ export function Button({
|
|
|
153
177
|
</View>
|
|
154
178
|
)}
|
|
155
179
|
{label && (
|
|
156
|
-
<View
|
|
180
|
+
<View
|
|
181
|
+
style={[styles.labelStyle, UNSAFE_style?.actionLabelContainer]}
|
|
182
|
+
testID="actionLabelContainer"
|
|
183
|
+
>
|
|
157
184
|
<ActionLabel
|
|
158
185
|
variation={getActionLabelVariation(variation, type)}
|
|
159
186
|
disabled={disabled}
|
package/src/Text/Text.test.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { render } from "@testing-library/react-native";
|
|
3
|
+
import { tokens } from "@jobber/design";
|
|
3
4
|
import { Text } from ".";
|
|
4
5
|
|
|
5
6
|
it("renders text with no additional props", () => {
|
|
@@ -148,3 +149,22 @@ it("renders text with underline styling", () => {
|
|
|
148
149
|
|
|
149
150
|
expect(text.toJSON()).toMatchSnapshot();
|
|
150
151
|
});
|
|
152
|
+
|
|
153
|
+
describe("UNSAFE_style", () => {
|
|
154
|
+
it("applies custom styles via UNSAFE_style prop", () => {
|
|
155
|
+
const customStyle = {
|
|
156
|
+
textStyle: {
|
|
157
|
+
fontSize: 20,
|
|
158
|
+
color: tokens["color-blue--dark"],
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const { getByRole } = render(
|
|
163
|
+
<Text UNSAFE_style={customStyle}>Test Text</Text>,
|
|
164
|
+
);
|
|
165
|
+
const textElement = getByRole("text");
|
|
166
|
+
expect(textElement.props.style).toContainEqual(
|
|
167
|
+
expect.objectContaining(customStyle.textStyle),
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
});
|
package/src/Text/Text.tsx
CHANGED
|
@@ -11,8 +11,9 @@ import {
|
|
|
11
11
|
TypographyProps,
|
|
12
12
|
} from "../Typography";
|
|
13
13
|
import { tokens } from "../utils/design";
|
|
14
|
+
import { TypographyUnsafeStyle } from "../Typography/Typography";
|
|
14
15
|
|
|
15
|
-
interface TextProps
|
|
16
|
+
export interface TextProps
|
|
16
17
|
extends Pick<TypographyProps<"base">, "maxFontScaleSize" | "selectable"> {
|
|
17
18
|
/**
|
|
18
19
|
* Visual hierarchy of the text
|
|
@@ -85,6 +86,13 @@ interface TextProps
|
|
|
85
86
|
* of the TextInput
|
|
86
87
|
*/
|
|
87
88
|
readonly hideFromScreenReader?: boolean;
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* **Use at your own risk:** Custom style for specific elements. This should only be used as a
|
|
92
|
+
* **last resort**. Using this may result in unexpected side effects.
|
|
93
|
+
* More information [here](https://atlantis.getjobber.com/storybook/?path=/docs/guides-customizing-components--docs#unsafe_-props).
|
|
94
|
+
*/
|
|
95
|
+
readonly UNSAFE_style?: TypographyUnsafeStyle;
|
|
88
96
|
}
|
|
89
97
|
|
|
90
98
|
export type TextLevel = "text" | "textSupporting";
|
|
@@ -125,6 +133,7 @@ export function Text({
|
|
|
125
133
|
italic = false,
|
|
126
134
|
hideFromScreenReader = false,
|
|
127
135
|
maxFontScaleSize,
|
|
136
|
+
UNSAFE_style,
|
|
128
137
|
underline,
|
|
129
138
|
selectable,
|
|
130
139
|
}: TextProps): JSX.Element {
|
|
@@ -133,6 +142,7 @@ export function Text({
|
|
|
133
142
|
return (
|
|
134
143
|
<Typography
|
|
135
144
|
color={variation}
|
|
145
|
+
UNSAFE_style={UNSAFE_style}
|
|
136
146
|
fontFamily="base"
|
|
137
147
|
fontStyle={italic ? "italic" : "regular"}
|
|
138
148
|
fontWeight={getFontWeight({ level, emphasis })}
|
|
@@ -225,6 +225,20 @@ it("renders text that is inaccessible", () => {
|
|
|
225
225
|
);
|
|
226
226
|
});
|
|
227
227
|
|
|
228
|
+
it("applies custom UNSAFE_style to text", () => {
|
|
229
|
+
const customStyle = { color: "red", fontSize: 20 };
|
|
230
|
+
const typography = render(
|
|
231
|
+
<Typography UNSAFE_style={{ textStyle: customStyle }}>
|
|
232
|
+
Test Text
|
|
233
|
+
</Typography>,
|
|
234
|
+
);
|
|
235
|
+
const textElement = typography.getByText("Test Text");
|
|
236
|
+
|
|
237
|
+
expect(textElement.props.style).toEqual(
|
|
238
|
+
expect.arrayContaining([expect.objectContaining(customStyle)]),
|
|
239
|
+
);
|
|
240
|
+
});
|
|
241
|
+
|
|
228
242
|
describe("underline", () => {
|
|
229
243
|
it.each(["solid", "double", "dotted", "dashed"] as const)(
|
|
230
244
|
"renders text with %s underline",
|
|
@@ -118,6 +118,8 @@ export interface TypographyProps<T extends FontFamily>
|
|
|
118
118
|
* Have text styled with strike through
|
|
119
119
|
*/
|
|
120
120
|
readonly strikeThrough?: boolean;
|
|
121
|
+
|
|
122
|
+
readonly UNSAFE_style?: TypographyUnsafeStyle;
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
const maxNumberOfLines = {
|
|
@@ -129,6 +131,10 @@ const maxNumberOfLines = {
|
|
|
129
131
|
unlimited: undefined,
|
|
130
132
|
};
|
|
131
133
|
|
|
134
|
+
export interface TypographyUnsafeStyle {
|
|
135
|
+
textStyle?: StyleProp<TextStyle>;
|
|
136
|
+
}
|
|
137
|
+
|
|
132
138
|
export const Typography = React.memo(InternalTypography);
|
|
133
139
|
|
|
134
140
|
// eslint-disable-next-line max-statements
|
|
@@ -152,6 +158,7 @@ function InternalTypography<T extends FontFamily = "base">({
|
|
|
152
158
|
accessibilityRole = "text",
|
|
153
159
|
strikeThrough = false,
|
|
154
160
|
underline,
|
|
161
|
+
UNSAFE_style,
|
|
155
162
|
selectable = true,
|
|
156
163
|
}: TypographyProps<T>): JSX.Element {
|
|
157
164
|
const sizeAndHeight = getSizeAndHeightStyle(size, lineHeight);
|
|
@@ -176,6 +183,10 @@ function InternalTypography<T extends FontFamily = "base">({
|
|
|
176
183
|
style.push(underlineTextStyle, styles.underline);
|
|
177
184
|
}
|
|
178
185
|
|
|
186
|
+
if (UNSAFE_style?.textStyle) {
|
|
187
|
+
style.push(UNSAFE_style.textStyle);
|
|
188
|
+
}
|
|
189
|
+
|
|
179
190
|
const numberOfLinesForNativeText = maxNumberOfLines[maxLines];
|
|
180
191
|
|
|
181
192
|
const text = getTransformedText(children, transform);
|