@jobber/components-native 0.11.0 → 0.12.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.
@@ -0,0 +1,37 @@
1
+ /// <reference types="react" />
2
+ import { TextAlign, TextColor, TruncateLength, TypographyProps } from "../Typography";
3
+ type HeadingColor = Extract<TextColor, "text" | "subdued" | "heading">;
4
+ export type HeadingLevel = "title" | "subtitle" | "heading" | "subHeading";
5
+ interface HeadingProps<T extends HeadingLevel> extends Pick<TypographyProps<"base">, "selectable"> {
6
+ /**
7
+ * Text to display.
8
+ */
9
+ readonly children: string;
10
+ /**
11
+ * The type of heading, e.g., "Title"
12
+ */
13
+ readonly level?: T;
14
+ /**
15
+ * The text color of heading
16
+ */
17
+ readonly variation?: HeadingColor;
18
+ /**
19
+ * Uses the reverse variant of the text color for the heading
20
+ */
21
+ readonly reverseTheme?: boolean;
22
+ /**
23
+ * Alignment of heading
24
+ */
25
+ readonly align?: TextAlign;
26
+ /**
27
+ * The maximum amount of lines the text can occupy before being truncated with "...".
28
+ * Uses predefined string values that correspond to a doubling scale for the amount of lines.
29
+ */
30
+ readonly maxLines?: TruncateLength;
31
+ /**
32
+ * Allow text to be resized based on user's device display scale
33
+ */
34
+ readonly allowFontScaling?: boolean;
35
+ }
36
+ export declare function Heading<T extends HeadingLevel = "heading">({ children, level, variation, reverseTheme, align, maxLines, allowFontScaling, selectable, }: HeadingProps<T>): JSX.Element;
37
+ export {};
@@ -0,0 +1,2 @@
1
+ export { Heading } from "./Heading";
2
+ export type { HeadingLevel } from "./Heading";
@@ -11,3 +11,4 @@ export * from "./StatusLabel";
11
11
  export * from "./AtlantisContext";
12
12
  export * from "./Button";
13
13
  export * from "./InputFieldWrapper";
14
+ export * from "./Heading";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jobber/components-native",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "license": "MIT",
5
5
  "main": "dist/src/index.js",
6
6
  "module": "dist/src/index.js",
@@ -47,5 +47,5 @@
47
47
  "react": "^18",
48
48
  "react-native": ">=0.69.2"
49
49
  },
50
- "gitHead": "91380d5821e334f130fcf7a02290b25548fa05e2"
50
+ "gitHead": "b059ff05b89ebdd41e79b4b2cf761e91706bc9c9"
51
51
  }
@@ -0,0 +1,83 @@
1
+ import React from "react";
2
+ import { render } from "@testing-library/react-native";
3
+ import { Heading } from "./Heading";
4
+
5
+ describe("when Heading called with text as the only prop", () => {
6
+ it("should match snapshot", () => {
7
+ const view = render(<Heading>Default Heading</Heading>).toJSON();
8
+
9
+ expect(view).toMatchSnapshot();
10
+ });
11
+ });
12
+
13
+ describe("when Heading called with reverseTheme", () => {
14
+ it("should match snapshot", () => {
15
+ const view = render(
16
+ <Heading reverseTheme>Reverse Theme Heading</Heading>,
17
+ ).toJSON();
18
+
19
+ expect(view).toMatchSnapshot();
20
+ });
21
+ });
22
+
23
+ describe("when Heading called with title variation", () => {
24
+ it("should match snapshot", () => {
25
+ const view = render(
26
+ <Heading level={"title"}>Title Heading</Heading>,
27
+ ).toJSON();
28
+
29
+ expect(view).toMatchSnapshot();
30
+ });
31
+ });
32
+
33
+ describe("when Heading called with Subtitle variation", () => {
34
+ it("should match snapshot", () => {
35
+ const view = render(
36
+ <Heading level={"subtitle"}>Subtitle</Heading>,
37
+ ).toJSON();
38
+
39
+ expect(view).toMatchSnapshot();
40
+ });
41
+ });
42
+
43
+ describe("when Heading called with sub-heading variation", () => {
44
+ it("should match snapshot", () => {
45
+ const view = render(
46
+ <Heading level={"subHeading"}>Sub-Heading</Heading>,
47
+ ).toJSON();
48
+
49
+ expect(view).toMatchSnapshot();
50
+ });
51
+ });
52
+
53
+ describe("when Heading called with sub-heading variation and text-color", () => {
54
+ it("should match snapshot", () => {
55
+ const view = render(
56
+ <Heading level={"subHeading"} variation={"subdued"}>
57
+ Sub-Heading
58
+ </Heading>,
59
+ ).toJSON();
60
+
61
+ expect(view).toMatchSnapshot();
62
+ });
63
+ });
64
+
65
+ describe("when Heading called with an alignment", () => {
66
+ it("should match snapshot", () => {
67
+ const view = render(
68
+ <Heading align={"end"}>Text Aligned Right</Heading>,
69
+ ).toJSON();
70
+
71
+ expect(view).toMatchSnapshot();
72
+ });
73
+ });
74
+
75
+ describe("when Heading called with maxLines", () => {
76
+ it("should match snapshot", () => {
77
+ const view = render(
78
+ <Heading maxLines="single">Text Aligned Right</Heading>,
79
+ ).toJSON();
80
+
81
+ expect(view).toMatchSnapshot();
82
+ });
83
+ });
@@ -0,0 +1,132 @@
1
+ import React from "react";
2
+ import {
3
+ FontFamily,
4
+ TextAlign,
5
+ TextColor,
6
+ TruncateLength,
7
+ Typography,
8
+ TypographyProps,
9
+ } from "../Typography";
10
+ import { tokens } from "../utils/design";
11
+
12
+ type HeadingStyle = Pick<
13
+ TypographyProps<FontFamily>,
14
+ "fontFamily" | "fontWeight" | "size" | "lineHeight" | "color"
15
+ >;
16
+ type HeadingColor = Extract<TextColor, "text" | "subdued" | "heading">;
17
+ export type HeadingLevel = "title" | "subtitle" | "heading" | "subHeading";
18
+
19
+ interface HeadingProps<T extends HeadingLevel>
20
+ extends Pick<TypographyProps<"base">, "selectable"> {
21
+ /**
22
+ * Text to display.
23
+ */
24
+ readonly children: string;
25
+
26
+ /**
27
+ * The type of heading, e.g., "Title"
28
+ */
29
+ readonly level?: T;
30
+
31
+ /**
32
+ * The text color of heading
33
+ */
34
+ readonly variation?: HeadingColor;
35
+
36
+ /**
37
+ * Uses the reverse variant of the text color for the heading
38
+ */
39
+ readonly reverseTheme?: boolean;
40
+
41
+ /**
42
+ * Alignment of heading
43
+ */
44
+ readonly align?: TextAlign;
45
+
46
+ /**
47
+ * The maximum amount of lines the text can occupy before being truncated with "...".
48
+ * Uses predefined string values that correspond to a doubling scale for the amount of lines.
49
+ */
50
+ readonly maxLines?: TruncateLength;
51
+
52
+ /**
53
+ * Allow text to be resized based on user's device display scale
54
+ */
55
+ readonly allowFontScaling?: boolean;
56
+ }
57
+
58
+ const maxScaledFontSize: Record<HeadingLevel, number> = {
59
+ subHeading: tokens["typography--fontSize-base"] * 1.375,
60
+ heading: tokens["typography--fontSize-base"] * 1.5,
61
+ subtitle: tokens["typography--fontSize-base"] * 1.5,
62
+ title: tokens["typography--fontSize-base"] * 2.125,
63
+ };
64
+
65
+ export function Heading<T extends HeadingLevel = "heading">({
66
+ children,
67
+ level,
68
+ variation = "heading",
69
+ reverseTheme = false,
70
+ align,
71
+ maxLines = "unlimited",
72
+ allowFontScaling = true,
73
+ selectable,
74
+ }: HeadingProps<T>): JSX.Element {
75
+ const headingStyle = getHeadingStyle(level, variation);
76
+ const accessibilityRole = "header";
77
+
78
+ return (
79
+ <Typography
80
+ {...{
81
+ ...headingStyle,
82
+ accessibilityRole,
83
+ reverseTheme,
84
+ align,
85
+ maxLines,
86
+ allowFontScaling,
87
+ }}
88
+ maxFontScaleSize={maxScaledFontSize[level as HeadingLevel]}
89
+ selectable={selectable}
90
+ >
91
+ {children}
92
+ </Typography>
93
+ );
94
+ }
95
+
96
+ function getHeadingStyle(
97
+ level: HeadingLevel = "heading",
98
+ variation: HeadingColor,
99
+ ): HeadingStyle {
100
+ const headingLevelToStyle: Record<HeadingLevel, HeadingStyle> = {
101
+ title: {
102
+ fontFamily: "display",
103
+ fontWeight: "black",
104
+ size: "jumbo",
105
+ lineHeight: "jumbo",
106
+ color: variation,
107
+ },
108
+ subtitle: {
109
+ fontFamily: "display",
110
+ fontWeight: "extraBold",
111
+ size: "largest",
112
+ lineHeight: "largest",
113
+ color: variation,
114
+ },
115
+ heading: {
116
+ fontFamily: "display",
117
+ fontWeight: "extraBold",
118
+ size: "larger",
119
+ lineHeight: "large",
120
+ color: variation,
121
+ },
122
+ subHeading: {
123
+ fontFamily: "base",
124
+ fontWeight: "semiBold",
125
+ size: "default",
126
+ lineHeight: "base",
127
+ color: variation,
128
+ },
129
+ };
130
+
131
+ return headingLevelToStyle[level];
132
+ }
@@ -0,0 +1,270 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`when Heading called with Subtitle variation should match snapshot 1`] = `
4
+ <Text
5
+ accessibilityRole="header"
6
+ adjustsFontSizeToFit={false}
7
+ allowFontScaling={true}
8
+ collapsable={false}
9
+ maxFontSizeMultiplier={1}
10
+ selectable={true}
11
+ selectionColor="rgb(160, 215, 42)"
12
+ style={
13
+ [
14
+ {
15
+ "fontFamily": "jobberpro-xbd",
16
+ },
17
+ {
18
+ "color": "rgb(1, 41, 57)",
19
+ },
20
+ {
21
+ "textAlign": "left",
22
+ },
23
+ {
24
+ "fontSize": 24,
25
+ "lineHeight": 28,
26
+ },
27
+ {
28
+ "letterSpacing": 0,
29
+ },
30
+ ]
31
+ }
32
+ >
33
+ Subtitle
34
+ </Text>
35
+ `;
36
+
37
+ exports[`when Heading called with an alignment should match snapshot 1`] = `
38
+ <Text
39
+ accessibilityRole="header"
40
+ adjustsFontSizeToFit={false}
41
+ allowFontScaling={true}
42
+ collapsable={false}
43
+ selectable={true}
44
+ selectionColor="rgb(160, 215, 42)"
45
+ style={
46
+ [
47
+ {
48
+ "fontFamily": "jobberpro-xbd",
49
+ },
50
+ {
51
+ "color": "rgb(1, 41, 57)",
52
+ },
53
+ {
54
+ "textAlign": "right",
55
+ },
56
+ {
57
+ "fontSize": 20,
58
+ "lineHeight": 22,
59
+ },
60
+ {
61
+ "letterSpacing": 0,
62
+ },
63
+ ]
64
+ }
65
+ >
66
+ Text Aligned Right
67
+ </Text>
68
+ `;
69
+
70
+ exports[`when Heading called with maxLines should match snapshot 1`] = `
71
+ <Text
72
+ accessibilityRole="header"
73
+ adjustsFontSizeToFit={false}
74
+ allowFontScaling={true}
75
+ collapsable={false}
76
+ numberOfLines={1}
77
+ selectable={true}
78
+ selectionColor="rgb(160, 215, 42)"
79
+ style={
80
+ [
81
+ {
82
+ "fontFamily": "jobberpro-xbd",
83
+ },
84
+ {
85
+ "color": "rgb(1, 41, 57)",
86
+ },
87
+ {
88
+ "textAlign": "left",
89
+ },
90
+ {
91
+ "fontSize": 20,
92
+ "lineHeight": 22,
93
+ },
94
+ {
95
+ "letterSpacing": 0,
96
+ },
97
+ ]
98
+ }
99
+ >
100
+ Text Aligned Right
101
+ </Text>
102
+ `;
103
+
104
+ exports[`when Heading called with reverseTheme should match snapshot 1`] = `
105
+ <Text
106
+ accessibilityRole="header"
107
+ adjustsFontSizeToFit={false}
108
+ allowFontScaling={true}
109
+ collapsable={false}
110
+ selectable={true}
111
+ selectionColor="rgb(160, 215, 42)"
112
+ style={
113
+ [
114
+ {
115
+ "fontFamily": "jobberpro-xbd",
116
+ },
117
+ {
118
+ "color": "rgba(255, 255, 255, 1)",
119
+ },
120
+ {
121
+ "textAlign": "left",
122
+ },
123
+ {
124
+ "fontSize": 20,
125
+ "lineHeight": 22,
126
+ },
127
+ {
128
+ "letterSpacing": 0,
129
+ },
130
+ ]
131
+ }
132
+ >
133
+ Reverse Theme Heading
134
+ </Text>
135
+ `;
136
+
137
+ exports[`when Heading called with sub-heading variation and text-color should match snapshot 1`] = `
138
+ <Text
139
+ accessibilityRole="header"
140
+ adjustsFontSizeToFit={false}
141
+ allowFontScaling={true}
142
+ collapsable={false}
143
+ maxFontSizeMultiplier={1.375}
144
+ selectable={true}
145
+ selectionColor="rgb(160, 215, 42)"
146
+ style={
147
+ [
148
+ {
149
+ "fontFamily": "inter-semibold",
150
+ },
151
+ {
152
+ "color": "rgba(101, 120, 132, 1)",
153
+ },
154
+ {
155
+ "textAlign": "left",
156
+ },
157
+ {
158
+ "fontSize": 16,
159
+ "lineHeight": 20,
160
+ },
161
+ {
162
+ "letterSpacing": 0,
163
+ },
164
+ ]
165
+ }
166
+ >
167
+ Sub-Heading
168
+ </Text>
169
+ `;
170
+
171
+ exports[`when Heading called with sub-heading variation should match snapshot 1`] = `
172
+ <Text
173
+ accessibilityRole="header"
174
+ adjustsFontSizeToFit={false}
175
+ allowFontScaling={true}
176
+ collapsable={false}
177
+ maxFontSizeMultiplier={1.375}
178
+ selectable={true}
179
+ selectionColor="rgb(160, 215, 42)"
180
+ style={
181
+ [
182
+ {
183
+ "fontFamily": "inter-semibold",
184
+ },
185
+ {
186
+ "color": "rgb(1, 41, 57)",
187
+ },
188
+ {
189
+ "textAlign": "left",
190
+ },
191
+ {
192
+ "fontSize": 16,
193
+ "lineHeight": 20,
194
+ },
195
+ {
196
+ "letterSpacing": 0,
197
+ },
198
+ ]
199
+ }
200
+ >
201
+ Sub-Heading
202
+ </Text>
203
+ `;
204
+
205
+ exports[`when Heading called with text as the only prop should match snapshot 1`] = `
206
+ <Text
207
+ accessibilityRole="header"
208
+ adjustsFontSizeToFit={false}
209
+ allowFontScaling={true}
210
+ collapsable={false}
211
+ selectable={true}
212
+ selectionColor="rgb(160, 215, 42)"
213
+ style={
214
+ [
215
+ {
216
+ "fontFamily": "jobberpro-xbd",
217
+ },
218
+ {
219
+ "color": "rgb(1, 41, 57)",
220
+ },
221
+ {
222
+ "textAlign": "left",
223
+ },
224
+ {
225
+ "fontSize": 20,
226
+ "lineHeight": 22,
227
+ },
228
+ {
229
+ "letterSpacing": 0,
230
+ },
231
+ ]
232
+ }
233
+ >
234
+ Default Heading
235
+ </Text>
236
+ `;
237
+
238
+ exports[`when Heading called with title variation should match snapshot 1`] = `
239
+ <Text
240
+ accessibilityRole="header"
241
+ adjustsFontSizeToFit={false}
242
+ allowFontScaling={true}
243
+ collapsable={false}
244
+ maxFontSizeMultiplier={1.0625}
245
+ selectable={true}
246
+ selectionColor="rgb(160, 215, 42)"
247
+ style={
248
+ [
249
+ {
250
+ "fontFamily": "jobberpro-blk",
251
+ },
252
+ {
253
+ "color": "rgb(1, 41, 57)",
254
+ },
255
+ {
256
+ "textAlign": "left",
257
+ },
258
+ {
259
+ "fontSize": 32,
260
+ "lineHeight": 36,
261
+ },
262
+ {
263
+ "letterSpacing": 0,
264
+ },
265
+ ]
266
+ }
267
+ >
268
+ Title Heading
269
+ </Text>
270
+ `;
@@ -0,0 +1,2 @@
1
+ export { Heading } from "./Heading";
2
+ export type { HeadingLevel } from "./Heading";
package/src/index.ts CHANGED
@@ -11,3 +11,4 @@ export * from "./StatusLabel";
11
11
  export * from "./AtlantisContext";
12
12
  export * from "./Button";
13
13
  export * from "./InputFieldWrapper";
14
+ export * from "./Heading";