@jobber/components-native 0.69.5-dependabot.8 → 0.70.1-CLEANUPex-e95f16e.2
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 +4 -6
- package/dist/src/Checkbox/Checkbox.js +1 -1
- package/dist/src/Form/components/FormActionBar/FormActionBar.js +1 -3
- package/dist/src/Icon/Icon.js +5 -38
- package/dist/src/InputPressable/InputPressable.style.js +1 -1
- package/dist/src/Typography/Typography.style.js +2 -2
- package/dist/src/utils/design/index.js +4 -3
- package/dist/src/utils/meta/meta.json +67 -0
- package/dist/tsconfig.json +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/src/utils/design/index.d.ts +2 -2
- package/package.json +4 -6
- package/src/Checkbox/Checkbox.tsx +1 -1
- package/src/Form/components/FormActionBar/FormActionBar.tsx +2 -2
- package/src/Icon/Icon.tsx +10 -66
- package/src/InputPressable/InputPressable.style.ts +1 -1
- package/src/Typography/Typography.style.ts +2 -2
- package/src/utils/design/index.ts +5 -5
- package/src/utils/meta/meta.json +67 -0
- package/src/utils/meta/meta.test.tsx +71 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const tokens: typeof
|
|
1
|
+
import { iosTokens } from "@jobber/design";
|
|
2
|
+
export declare const tokens: typeof iosTokens;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jobber/components-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.70.1-CLEANUPex-e95f16e.2+e95f16e9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "React Native implementation of Atlantis",
|
|
6
6
|
"repository": {
|
|
@@ -36,8 +36,6 @@
|
|
|
36
36
|
"build:clean": "rm -rf ./dist"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@jobber/design": "^0.63.1-dependabot.16+d8e3efef",
|
|
40
|
-
"@jobber/hooks": "^2.10.2",
|
|
41
39
|
"@react-native-clipboard/clipboard": "^1.11.2",
|
|
42
40
|
"@react-native-picker/picker": "^2.4.10",
|
|
43
41
|
"autolinker": "^4.0.0",
|
|
@@ -70,8 +68,8 @@
|
|
|
70
68
|
"peerDependencies": {
|
|
71
69
|
"@babel/core": "^7.4.5",
|
|
72
70
|
"@react-native-community/datetimepicker": ">=6.7.0",
|
|
73
|
-
"date-fns": "^2.
|
|
74
|
-
"date-fns-tz": "
|
|
71
|
+
"date-fns": "^2.30.0",
|
|
72
|
+
"date-fns-tz": "^2.0.0",
|
|
75
73
|
"react": "^18.2.0",
|
|
76
74
|
"react-intl": "^6.4.2",
|
|
77
75
|
"react-native": ">=0.69.2",
|
|
@@ -84,5 +82,5 @@
|
|
|
84
82
|
"react-native-safe-area-context": "^4.5.2",
|
|
85
83
|
"react-native-svg": ">=12.0.0"
|
|
86
84
|
},
|
|
87
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "e95f16e9ba785cb1e14de3f3cf39096563784f86"
|
|
88
86
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { ColorValue, Pressable, View } from "react-native";
|
|
3
3
|
import { XOR } from "ts-xor";
|
|
4
|
-
import { tokens } from "@jobber/design
|
|
4
|
+
import { tokens } from "@jobber/design";
|
|
5
5
|
import { styles } from "./Checkbox.style";
|
|
6
6
|
import { Text } from "../Text";
|
|
7
7
|
import { Icon } from "../Icon";
|
|
@@ -35,7 +35,8 @@ export function FormActionBar({
|
|
|
35
35
|
const buttonStyle = StyleSheet.flatten([
|
|
36
36
|
styles.saveButton,
|
|
37
37
|
{
|
|
38
|
-
position:
|
|
38
|
+
position:
|
|
39
|
+
keyboardHeight > 0 ? ("absolute" as const) : ("relative" as const),
|
|
39
40
|
bottom: 0,
|
|
40
41
|
},
|
|
41
42
|
]);
|
|
@@ -45,7 +46,6 @@ export function FormActionBar({
|
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
return (
|
|
48
|
-
//@ts-expect-error tsc-ci
|
|
49
49
|
<ReanimatedView style={buttonStyle} onLayout={onLayout}>
|
|
50
50
|
{renderStickySection ? (
|
|
51
51
|
renderStickySection(submit, saveButtonLabel, isFormSubmitting)
|
package/src/Icon/Icon.tsx
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import Svg, {
|
|
3
|
-
import {
|
|
4
|
-
IconColorNames,
|
|
5
|
-
IconNames,
|
|
6
|
-
IconSizes,
|
|
7
|
-
colorsClassMap,
|
|
8
|
-
getIcon,
|
|
9
|
-
iconClassMap,
|
|
10
|
-
iconStyles,
|
|
11
|
-
sizesClassMap,
|
|
12
|
-
} from "@jobber/design";
|
|
2
|
+
import Svg, { Path } from "react-native-svg";
|
|
3
|
+
import { IconColorNames, IconNames, IconSizes, getIcon } from "@jobber/design";
|
|
13
4
|
|
|
14
5
|
export interface IconProps {
|
|
15
6
|
/** The icon to show. */
|
|
@@ -46,72 +37,25 @@ export function Icon({
|
|
|
46
37
|
customColor,
|
|
47
38
|
testID,
|
|
48
39
|
}: IconProps): JSX.Element {
|
|
49
|
-
const {
|
|
40
|
+
const { svgStyle, paths, viewBox } = getIcon({
|
|
50
41
|
name,
|
|
51
42
|
color,
|
|
52
43
|
size,
|
|
44
|
+
platform: "mobile",
|
|
45
|
+
format: "js",
|
|
53
46
|
});
|
|
54
47
|
|
|
55
|
-
/*
|
|
56
|
-
* This is to fix a bug where icons with built-in colours do not respect
|
|
57
|
-
* their color property. At time of writing, if you pass a color to getIcon,
|
|
58
|
-
* pathClassNames will return the color class first in pathClassNames.
|
|
59
|
-
* getSvgStyle applies styles in order, so the styles in the last class
|
|
60
|
-
* processed take precedence.
|
|
61
|
-
*
|
|
62
|
-
* This fix reverses the order of pathClassNames, so any color-specific
|
|
63
|
-
* CSS classes are processed last. The order of classes in pathClassNames
|
|
64
|
-
* is not contractual, so this is potentially fragile if there are updates
|
|
65
|
-
* to the @jobber/design package it comes from.
|
|
66
|
-
*/
|
|
67
|
-
const reversedPathClassNames = pathClassNames.split(" ").reverse().join(" ");
|
|
68
|
-
|
|
69
|
-
const svgStyle = getSvgStyle(svgClassNames + " " + reversedPathClassNames);
|
|
70
|
-
|
|
71
48
|
const icon = paths.map((path: string) => {
|
|
72
49
|
return <Path key={path} d={path} fill={customColor || svgStyle.fill} />;
|
|
73
50
|
});
|
|
74
51
|
|
|
75
52
|
return (
|
|
76
|
-
<Svg
|
|
53
|
+
<Svg
|
|
54
|
+
style={{ ...svgStyle, display: "flex" }}
|
|
55
|
+
testID={testID || name}
|
|
56
|
+
viewBox={viewBox}
|
|
57
|
+
>
|
|
77
58
|
{icon}
|
|
78
59
|
</Svg>
|
|
79
60
|
);
|
|
80
61
|
}
|
|
81
|
-
|
|
82
|
-
/*
|
|
83
|
-
* get svg styles based on the class names
|
|
84
|
-
* @param className - list of hashed names separated by space - "_2GsLyQLHv8yNULHeXGdver _1ANbiqwd8qgeLaumvLs27n"
|
|
85
|
-
* @default ""
|
|
86
|
-
* @return - style object for the icon - {"display": "flex" "height": 24, "width": 24, "verticalAlign": "middle" }
|
|
87
|
-
*
|
|
88
|
-
* Since the class names are hashed, we use the [name]ClassMap to find the actual class name. For example if we get
|
|
89
|
-
* "_2GsLyQLHv8yNULHeXGdver _1ANbiqwd8qgeLaumvLs27n", it might map to ".icon .base". Then using the mapped class names,
|
|
90
|
-
* we get the style from the css files which will be something like {"display": "flex" "height": 24, "width": 24, "verticalAlign": "middle" }
|
|
91
|
-
*
|
|
92
|
-
* Atlantis returns "display: inline-block" for icons, but since React Native doesn't support that, we override it with
|
|
93
|
-
* the default "display" value for React Native which is "flex"
|
|
94
|
-
*/
|
|
95
|
-
function getSvgStyle(classNames = ""): SvgProps["style"] & FillProps {
|
|
96
|
-
const classMap = {
|
|
97
|
-
...iconClassMap,
|
|
98
|
-
...sizesClassMap,
|
|
99
|
-
...colorsClassMap,
|
|
100
|
-
};
|
|
101
|
-
const svgStyle = getStylesForClassNames(classNames.split(" "), classMap);
|
|
102
|
-
|
|
103
|
-
return { ...svgStyle, display: "flex" };
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function getStylesForClassNames(
|
|
107
|
-
classNames: string[],
|
|
108
|
-
classMap: Record<string, string>,
|
|
109
|
-
) {
|
|
110
|
-
return classNames.reduce(
|
|
111
|
-
(acc, className) => ({
|
|
112
|
-
...acc,
|
|
113
|
-
...iconStyles[classMap[className] as keyof typeof iconStyles],
|
|
114
|
-
}),
|
|
115
|
-
{},
|
|
116
|
-
);
|
|
117
|
-
}
|
|
@@ -9,7 +9,7 @@ const largerLineHeight = tokens["typography--lineHeight-larger"];
|
|
|
9
9
|
const largeLineHeight = tokens["typography--lineHeight-large"];
|
|
10
10
|
const baseLineHeight = tokens["typography--lineHeight-base"];
|
|
11
11
|
const tightLineHeight = tokens["typography--lineHeight-tight"];
|
|
12
|
-
const
|
|
12
|
+
const minusculeLineHeight = tokens["typography--lineHeight-minuscule"];
|
|
13
13
|
|
|
14
14
|
const deviceFonts = {
|
|
15
15
|
baseRegularRegular: {
|
|
@@ -306,7 +306,7 @@ export const typographyTokens: { [index: string]: TextStyle } = {
|
|
|
306
306
|
|
|
307
307
|
smallestSize: {
|
|
308
308
|
fontSize: tokens["typography--fontSize-smallest"],
|
|
309
|
-
lineHeight:
|
|
309
|
+
lineHeight: minusculeLineHeight,
|
|
310
310
|
},
|
|
311
311
|
|
|
312
312
|
smallerSize: {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { tokens as mobileFoundationBase } from "@jobber/design/foundation.native";
|
|
2
1
|
import { Platform } from "react-native";
|
|
2
|
+
import { androidTokens, iosTokens } from "@jobber/design";
|
|
3
3
|
|
|
4
|
-
export const tokens: typeof
|
|
5
|
-
ios: () =>
|
|
6
|
-
android: () =>
|
|
7
|
-
default: () =>
|
|
4
|
+
export const tokens: typeof iosTokens = Platform.select({
|
|
5
|
+
ios: () => iosTokens,
|
|
6
|
+
android: () => androidTokens,
|
|
7
|
+
default: () => androidTokens,
|
|
8
8
|
})();
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"exportedComponents": [
|
|
3
|
+
"ActionItem",
|
|
4
|
+
"ActionItemGroup",
|
|
5
|
+
"ActionLabel",
|
|
6
|
+
"ActivityIndicator",
|
|
7
|
+
"AtlantisContext.Provider",
|
|
8
|
+
"AtlantisContext.Consumer",
|
|
9
|
+
"AutoLink",
|
|
10
|
+
"Banner",
|
|
11
|
+
"BottomSheet",
|
|
12
|
+
"BottomSheetOption",
|
|
13
|
+
"Button",
|
|
14
|
+
"ButtonGroup",
|
|
15
|
+
"ButtonGroup.PrimaryAction",
|
|
16
|
+
"ButtonGroup.SecondaryAction",
|
|
17
|
+
"Card",
|
|
18
|
+
"Checkbox",
|
|
19
|
+
"CheckboxGroup",
|
|
20
|
+
"Chip",
|
|
21
|
+
"Content",
|
|
22
|
+
"ContentOverlay",
|
|
23
|
+
"Disclosure",
|
|
24
|
+
"Divider",
|
|
25
|
+
"EmptyState",
|
|
26
|
+
"ErrorMessageContext.Provider",
|
|
27
|
+
"ErrorMessageContext.Consumer",
|
|
28
|
+
"ErrorMessageProvider",
|
|
29
|
+
"ErrorMessageWrapper",
|
|
30
|
+
"Flex",
|
|
31
|
+
"Form",
|
|
32
|
+
"FormMessage",
|
|
33
|
+
"AtlantisFormContext.Provider",
|
|
34
|
+
"AtlantisFormContext.Consumer",
|
|
35
|
+
"FormatFile",
|
|
36
|
+
"FormField",
|
|
37
|
+
"Glimmer",
|
|
38
|
+
"Heading",
|
|
39
|
+
"Icon",
|
|
40
|
+
"IconButton",
|
|
41
|
+
"InputCurrency",
|
|
42
|
+
"InputDate",
|
|
43
|
+
"InputEmail",
|
|
44
|
+
"InputFieldWrapper",
|
|
45
|
+
"InputNumber",
|
|
46
|
+
"InputPassword",
|
|
47
|
+
"InputPressable",
|
|
48
|
+
"FilterButton",
|
|
49
|
+
"InputSearch",
|
|
50
|
+
"InputText",
|
|
51
|
+
"InputAccessoriesContext.Provider",
|
|
52
|
+
"InputAccessoriesContext.Consumer",
|
|
53
|
+
"InputAccessoriesProvider",
|
|
54
|
+
"InputTime",
|
|
55
|
+
"Menu",
|
|
56
|
+
"ProgressBar",
|
|
57
|
+
"Option",
|
|
58
|
+
"Select",
|
|
59
|
+
"StatusLabel",
|
|
60
|
+
"Switch",
|
|
61
|
+
"Text",
|
|
62
|
+
"TextList",
|
|
63
|
+
"ThumbnailList",
|
|
64
|
+
"Toast",
|
|
65
|
+
"TypographyGestureDetector"
|
|
66
|
+
]
|
|
67
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import * as fs from "fs/promises";
|
|
2
|
+
import * as allExports from "../../index";
|
|
3
|
+
|
|
4
|
+
jest.mock("../../AutoLink/clipboard", () => {
|
|
5
|
+
return {
|
|
6
|
+
copyTextToClipboard: jest.fn(),
|
|
7
|
+
};
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe("meta", () => {
|
|
11
|
+
// If this test fails, please update meta.json accordingly.
|
|
12
|
+
it("verifies that the meta.json file is up to date", async () => {
|
|
13
|
+
const meta = await fs.readFile(`${__dirname}/meta.json`, "utf-8");
|
|
14
|
+
const allNames = findComponentNamesDeep(allExports);
|
|
15
|
+
|
|
16
|
+
expect(JSON.parse(meta)).toStrictEqual({
|
|
17
|
+
exportedComponents: allNames,
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
function isComponent(name: string, value: any): boolean {
|
|
24
|
+
const isFirstLetterUppercase = /^[A-Z]/.test(name);
|
|
25
|
+
const isFunctionComponent = typeof value === "function";
|
|
26
|
+
|
|
27
|
+
return isFirstLetterUppercase && isFunctionComponent;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
|
+
function isContext(value: any): boolean {
|
|
32
|
+
return (
|
|
33
|
+
value &&
|
|
34
|
+
typeof value === "object" &&
|
|
35
|
+
Object.prototype.hasOwnProperty.call(value, "Provider") &&
|
|
36
|
+
Object.prototype.hasOwnProperty.call(value, "Consumer")
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
|
+
function isForwardedRef(name: string, value: any): boolean {
|
|
42
|
+
const isFirstLetterUppercase = /^[A-Z]/.test(name);
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
isFirstLetterUppercase &&
|
|
46
|
+
value &&
|
|
47
|
+
typeof value === "object" &&
|
|
48
|
+
typeof value.render === "function"
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
53
|
+
function findComponentNamesDeep(objectOrFunction: any, name?: string) {
|
|
54
|
+
const entries = [...Object.entries(objectOrFunction)];
|
|
55
|
+
|
|
56
|
+
return entries.reduce<string[]>((allNames, [k, v]) => {
|
|
57
|
+
if (isContext(v)) {
|
|
58
|
+
allNames.push(`${k}.Provider`, `${k}.Consumer`);
|
|
59
|
+
} else if (isForwardedRef(k, v)) {
|
|
60
|
+
allNames.push(k);
|
|
61
|
+
} else if (isComponent(k, v)) {
|
|
62
|
+
const thisName = name ? `${name}.${k}` : k;
|
|
63
|
+
allNames.push(thisName);
|
|
64
|
+
|
|
65
|
+
const childComponents = findComponentNamesDeep(v, k);
|
|
66
|
+
allNames.push(...childComponents);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return allNames;
|
|
70
|
+
}, []);
|
|
71
|
+
}
|