@artsy/palette-mobile 11.1.0 → 11.2.1
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 +24 -0
- package/dist/elements/Image/Image.d.ts +15 -0
- package/dist/elements/Image/Image.js +53 -0
- package/dist/elements/Image/Image.stories.d.ts +1 -0
- package/dist/elements/Image/Image.stories.js +10 -0
- package/dist/elements/Image/index.d.ts +1 -0
- package/dist/elements/Image/index.js +17 -0
- package/dist/elements/Tabs/TabsContainer.js +4 -1
- package/dist/elements/index.d.ts +1 -0
- package/dist/elements/index.js +1 -0
- package/dist/storybook/decorators.js +2 -1
- package/dist/utils/createGeminiUrl.d.ts +8 -0
- package/dist/utils/createGeminiUrl.js +30 -0
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
# v11.2.1 (Mon Jun 26 2023)
|
|
2
|
+
|
|
3
|
+
#### 🐛 Bug Fix
|
|
4
|
+
|
|
5
|
+
- fix: indicator on android is not visible [#118](https://github.com/artsy/palette-mobile/pull/118) ([@gkartalis](https://github.com/gkartalis))
|
|
6
|
+
|
|
7
|
+
#### Authors: 1
|
|
8
|
+
|
|
9
|
+
- George Kartalis ([@gkartalis](https://github.com/gkartalis))
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# v11.2.0 (Thu Jun 15 2023)
|
|
14
|
+
|
|
15
|
+
#### 🚀 Enhancement
|
|
16
|
+
|
|
17
|
+
- feat(image): Add new <Image> component [#117](https://github.com/artsy/palette-mobile/pull/117) ([@damassi](https://github.com/damassi))
|
|
18
|
+
|
|
19
|
+
#### Authors: 1
|
|
20
|
+
|
|
21
|
+
- Christopher Pappas ([@damassi](https://github.com/damassi))
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
1
25
|
# v11.1.0 (Thu Jun 15 2023)
|
|
2
26
|
|
|
3
27
|
#### 🚀 Enhancement
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { FlexProps } from "../Flex";
|
|
3
|
+
export interface ImageProps extends FlexProps {
|
|
4
|
+
/** Supplied aspect ratio of image. If none provided, defaults to 1 */
|
|
5
|
+
aspectRatio?: number;
|
|
6
|
+
/** Supplied width of image. If none provided, defaults to screen width */
|
|
7
|
+
width?: number;
|
|
8
|
+
/** Supplied height of image. If none provided, defaults to width / aspectRatio */
|
|
9
|
+
height?: number;
|
|
10
|
+
/** Resize on the fly using Gemini. Defaults to true */
|
|
11
|
+
performResize?: boolean;
|
|
12
|
+
/** Source url to the image */
|
|
13
|
+
src: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const Image: React.FC<ImageProps>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Image = void 0;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const moti_1 = require("moti");
|
|
9
|
+
const react_1 = require("react");
|
|
10
|
+
const react_native_1 = require("react-native");
|
|
11
|
+
const react_native_fast_image_1 = __importDefault(require("react-native-fast-image"));
|
|
12
|
+
const react_native_reanimated_1 = require("react-native-reanimated");
|
|
13
|
+
const createGeminiUrl_1 = require("../../utils/createGeminiUrl");
|
|
14
|
+
const useScreenDimensions_1 = require("../../utils/hooks/useScreenDimensions");
|
|
15
|
+
const Flex_1 = require("../Flex");
|
|
16
|
+
const Skeleton_1 = require("../Skeleton");
|
|
17
|
+
const Image = ({ aspectRatio, width, height, performResize = true, src, ...flexProps }) => {
|
|
18
|
+
const [loading, setLoading] = (0, react_1.useState)(true);
|
|
19
|
+
const dimensions = useImageDimensions({ aspectRatio, width, height });
|
|
20
|
+
let uri = src;
|
|
21
|
+
if (performResize) {
|
|
22
|
+
uri = (0, createGeminiUrl_1.createGeminiUrl)({
|
|
23
|
+
imageURL: src,
|
|
24
|
+
width: react_native_1.PixelRatio.getPixelSizeForLayoutSize(dimensions.width),
|
|
25
|
+
height: react_native_1.PixelRatio.getPixelSizeForLayoutSize(dimensions.height),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
return ((0, jsx_runtime_1.jsxs)(Flex_1.Flex, { position: "relative", ...flexProps, children: [!!loading && ((0, jsx_runtime_1.jsx)(Flex_1.Flex, { position: "absolute", zIndex: 1, children: (0, jsx_runtime_1.jsx)(Skeleton_1.Skeleton, { children: (0, jsx_runtime_1.jsx)(Skeleton_1.SkeletonBox, { ...dimensions }) }) })), (0, jsx_runtime_1.jsx)(moti_1.MotiView, { animate: { opacity: loading ? 0 : 1 }, transition: { type: "timing", duration: 400, easing: react_native_reanimated_1.Easing.sin }, children: (0, jsx_runtime_1.jsx)(react_native_fast_image_1.default, { style: dimensions, onLoadStart: () => setLoading(true), onLoadEnd: () => setLoading(false), source: {
|
|
29
|
+
priority: react_native_fast_image_1.default.priority.normal,
|
|
30
|
+
uri,
|
|
31
|
+
} }) })] }));
|
|
32
|
+
};
|
|
33
|
+
exports.Image = Image;
|
|
34
|
+
const useImageDimensions = (props) => {
|
|
35
|
+
const screenDimensions = (0, useScreenDimensions_1.useScreenDimensions)();
|
|
36
|
+
const imageWidth = props.width ?? screenDimensions.width;
|
|
37
|
+
let imageHeight;
|
|
38
|
+
if (props.height) {
|
|
39
|
+
imageHeight = props.height;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
if (!props.aspectRatio) {
|
|
43
|
+
console.error("[CachedImage] Error: `aspectRatio` is required if `height` is not provided.");
|
|
44
|
+
}
|
|
45
|
+
const aspectRatio = props.aspectRatio ?? 1;
|
|
46
|
+
imageHeight = imageWidth / aspectRatio;
|
|
47
|
+
}
|
|
48
|
+
const dimensions = {
|
|
49
|
+
width: imageWidth,
|
|
50
|
+
height: imageHeight,
|
|
51
|
+
};
|
|
52
|
+
return dimensions;
|
|
53
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
4
|
+
const react_native_1 = require("@storybook/react-native");
|
|
5
|
+
const Image_1 = require("./Image");
|
|
6
|
+
(0, react_native_1.storiesOf)("Image", module)
|
|
7
|
+
.add("With default fallback screen width", () => ((0, jsx_runtime_1.jsx)(Image_1.Image, { aspectRatio: 0.62, src: "https://d32dm0rphc51dk.cloudfront.net/A983VUIZusVBKy420xP3ow/normalized.jpg" })))
|
|
8
|
+
.add("With width and height", () => ((0, jsx_runtime_1.jsx)(Image_1.Image, { width: 250, height: 400, src: "https://d32dm0rphc51dk.cloudfront.net/A983VUIZusVBKy420xP3ow/normalized.jpg" })))
|
|
9
|
+
.add("With aspect ratio", () => ((0, jsx_runtime_1.jsx)(Image_1.Image, { width: 250, aspectRatio: 0.62, src: "https://d32dm0rphc51dk.cloudfront.net/A983VUIZusVBKy420xP3ow/normalized.jpg" })))
|
|
10
|
+
.add("Without automatic resizing", () => ((0, jsx_runtime_1.jsx)(Image_1.Image, { aspectRatio: 0.62, performResize: false, src: "https://d32dm0rphc51dk.cloudfront.net/A983VUIZusVBKy420xP3ow/normalized.jpg" })));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Image";
|
|
@@ -0,0 +1,17 @@
|
|
|
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("./Image"), exports);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TabsContainer = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_native_1 = require("react-native");
|
|
5
6
|
const react_native_collapsible_tab_view_1 = require("react-native-collapsible-tab-view");
|
|
6
7
|
const useColor_1 = require("../../utils/hooks/useColor");
|
|
7
8
|
const useSpace_1 = require("../../utils/hooks/useSpace");
|
|
@@ -11,6 +12,7 @@ const TAB_BAR_HEIGHT = 50;
|
|
|
11
12
|
const TabsContainer = ({ children, indicators = [], initialTabName, renderHeader, tabScrollEnabled = false, onTabPress, ...tabContainerProps }) => {
|
|
12
13
|
const space = (0, useSpace_1.useSpace)();
|
|
13
14
|
const color = (0, useColor_1.useColor)();
|
|
15
|
+
const isIOS = react_native_1.Platform.OS === "ios";
|
|
14
16
|
return ((0, jsx_runtime_1.jsx)(react_native_collapsible_tab_view_1.Tabs.Container, { ...tabContainerProps, renderHeader: renderHeader, headerContainerStyle: {
|
|
15
17
|
shadowOpacity: 0,
|
|
16
18
|
shadowRadius: 0,
|
|
@@ -34,7 +36,8 @@ const TabsContainer = ({ children, indicators = [], initialTabName, renderHeader
|
|
|
34
36
|
}, contentContainerStyle: {}, activeColor: color("onBackground"), inactiveColor: color("onBackgroundMedium"), labelStyle: { marginTop: 0 }, indicatorStyle: {
|
|
35
37
|
backgroundColor: color("onBackground"),
|
|
36
38
|
height: 1,
|
|
37
|
-
|
|
39
|
+
// on android this line breaks the active indicator and it is not visible
|
|
40
|
+
...(isIOS && { bottom: -1 }),
|
|
38
41
|
} }) }));
|
|
39
42
|
}, children: children }));
|
|
40
43
|
};
|
package/dist/elements/index.d.ts
CHANGED
package/dist/elements/index.js
CHANGED
|
@@ -31,6 +31,7 @@ __exportStar(require("./EntityHeader"), exports);
|
|
|
31
31
|
__exportStar(require("./Flex"), exports);
|
|
32
32
|
__exportStar(require("./Header"), exports);
|
|
33
33
|
__exportStar(require("./Histogram"), exports);
|
|
34
|
+
__exportStar(require("./Image"), exports);
|
|
34
35
|
__exportStar(require("./Input"), exports);
|
|
35
36
|
__exportStar(require("./Join"), exports);
|
|
36
37
|
__exportStar(require("./LegacyScreen"), exports);
|
|
@@ -14,6 +14,7 @@ const react_native_safe_area_context_1 = require("react-native-safe-area-context
|
|
|
14
14
|
const Theme_1 = require("../Theme");
|
|
15
15
|
const Flex_1 = require("../elements/Flex");
|
|
16
16
|
const Text_1 = require("../elements/Text");
|
|
17
|
+
const hooks_1 = require("../utils/hooks");
|
|
17
18
|
const withTheme = (story) => ((0, jsx_runtime_1.jsxs)(Theme_1.Theme, { theme: "v3light", children: [(0, jsx_runtime_1.jsx)(Text_1.Text, { color: "red", children: "aaww" }), story()] }));
|
|
18
19
|
exports.withTheme = withTheme;
|
|
19
20
|
const atomStorage = (0, utils_1.createJSONStorage)(() => async_storage_1.default);
|
|
@@ -31,6 +32,6 @@ const useDarkModeSwitcher = (story) => {
|
|
|
31
32
|
}, []);
|
|
32
33
|
const isDarkMode = mode === "dark" || (mode === "system" && systemMode === "dark");
|
|
33
34
|
const theme = isDarkMode ? "v3dark" : "v3light";
|
|
34
|
-
return ((0, jsx_runtime_1.jsx)(react_native_safe_area_context_1.SafeAreaProvider, { children: (0, jsx_runtime_1.jsx)(Theme_1.Theme, { theme: theme, children: (0, jsx_runtime_1.jsxs)(Flex_1.Flex, { flex: 1, backgroundColor: "background", children: [(0, jsx_runtime_1.jsxs)(Flex_1.Flex, { flexDirection: "row", justifyContent: "space-around", children: [(0, jsx_runtime_1.jsxs)(Text_1.Text, { color: "orange", children: ["Dark mode: ", mode, " ", mode === "system" && "(" + systemMode + ")"] }), (0, jsx_runtime_1.jsx)(Text_1.LinkText, { color: "orange", onPress: () => setMode("light"), children: "light" }), (0, jsx_runtime_1.jsx)(Text_1.LinkText, { color: "orange", onPress: () => setMode("dark"), children: "dark" }), (0, jsx_runtime_1.jsx)(Text_1.LinkText, { color: "orange", onPress: () => setMode("system"), children: "system" })] }), story()] }) }) }));
|
|
35
|
+
return ((0, jsx_runtime_1.jsx)(hooks_1.ScreenDimensionsProvider, { children: (0, jsx_runtime_1.jsx)(react_native_safe_area_context_1.SafeAreaProvider, { children: (0, jsx_runtime_1.jsx)(Theme_1.Theme, { theme: theme, children: (0, jsx_runtime_1.jsxs)(Flex_1.Flex, { flex: 1, backgroundColor: "background", children: [(0, jsx_runtime_1.jsxs)(Flex_1.Flex, { flexDirection: "row", justifyContent: "space-around", children: [(0, jsx_runtime_1.jsxs)(Text_1.Text, { color: "orange", children: ["Dark mode: ", mode, " ", mode === "system" && "(" + systemMode + ")"] }), (0, jsx_runtime_1.jsx)(Text_1.LinkText, { color: "orange", onPress: () => setMode("light"), children: "light" }), (0, jsx_runtime_1.jsx)(Text_1.LinkText, { color: "orange", onPress: () => setMode("dark"), children: "dark" }), (0, jsx_runtime_1.jsx)(Text_1.LinkText, { color: "orange", onPress: () => setMode("system"), children: "system" })] }), story()] }) }) }) }));
|
|
35
36
|
};
|
|
36
37
|
exports.useDarkModeSwitcher = useDarkModeSwitcher;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createGeminiUrl = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
function createGeminiUrl({ imageURL, width, height, geminiHost = "d7hftxdivxxvm.cloudfront.net", imageQuality = 80, resizeMode = "fit", }) {
|
|
6
|
+
const src = encodeURIComponent(imageURL);
|
|
7
|
+
const roundedHeight = Math.round(height);
|
|
8
|
+
const roundedWidth = Math.round(width);
|
|
9
|
+
const params = [
|
|
10
|
+
`height=${roundedHeight}`,
|
|
11
|
+
`quality=${imageQuality}`,
|
|
12
|
+
`resize_to=${resizeMode}`,
|
|
13
|
+
`src=${src}`,
|
|
14
|
+
`width=${roundedWidth}`,
|
|
15
|
+
];
|
|
16
|
+
if (react_native_1.Platform.OS === "android" || (react_native_1.Platform.OS === "ios" && osMajorVersion() >= 14)) {
|
|
17
|
+
params.push("convert_to=webp");
|
|
18
|
+
}
|
|
19
|
+
return `https://${geminiHost}/?${params.join("&")}`;
|
|
20
|
+
}
|
|
21
|
+
exports.createGeminiUrl = createGeminiUrl;
|
|
22
|
+
const osMajorVersion = () => {
|
|
23
|
+
// eslint-disable-next-line no-constant-condition
|
|
24
|
+
if (typeof (react_native_1.Platform.Version === "string")) {
|
|
25
|
+
return parseInt(react_native_1.Platform.Version, 10);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return react_native_1.Platform.Version;
|
|
29
|
+
}
|
|
30
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@artsy/palette-mobile",
|
|
3
|
-
"version": "11.1
|
|
3
|
+
"version": "11.2.1",
|
|
4
4
|
"description": "Artsy's design system for React Native",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"android": "react-native run-android",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"moti": "^0.25.3",
|
|
42
42
|
"react-nanny": "^2.15.0",
|
|
43
43
|
"react-native-collapsible-tab-view": "^6.1.4",
|
|
44
|
+
"react-native-fast-image": "^8.6.3",
|
|
44
45
|
"react-native-pager-view": "^6.2.0",
|
|
45
46
|
"react-spring": "8.0.23",
|
|
46
47
|
"styled-system": "^5.1.5"
|