@lumx/react 3.4.0 → 3.5.1-alpha.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/index.d.ts +2 -0
- package/index.js +9 -7
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/tabs/Tab.test.tsx +5 -0
- package/src/components/tabs/Tab.tsx +4 -1
- package/src/components/thumbnail/Thumbnail.stories.tsx +17 -1
- package/src/components/thumbnail/useFocusPointStyle.tsx +2 -2
- package/src/components/thumbnail/useImageLoad.ts +3 -2
- package/src/stories/controls/image.ts +20 -1
package/package.json
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@juggle/resize-observer": "^3.2.0",
|
|
10
|
-
"@lumx/core": "^3.
|
|
11
|
-
"@lumx/icons": "^3.
|
|
10
|
+
"@lumx/core": "^3.5.1-alpha.0",
|
|
11
|
+
"@lumx/icons": "^3.5.1-alpha.0",
|
|
12
12
|
"@popperjs/core": "^2.5.4",
|
|
13
13
|
"body-scroll-lock": "^3.1.5",
|
|
14
14
|
"classnames": "^2.2.6",
|
|
@@ -117,5 +117,5 @@
|
|
|
117
117
|
"build:storybook": "storybook build"
|
|
118
118
|
},
|
|
119
119
|
"sideEffects": false,
|
|
120
|
-
"version": "3.
|
|
120
|
+
"version": "3.5.1-alpha.0"
|
|
121
121
|
}
|
|
@@ -38,6 +38,11 @@ describe(`<${Tab.displayName}>`, () => {
|
|
|
38
38
|
expect(icon).toBeInTheDocument();
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
+
it('should render icon with props', () => {
|
|
42
|
+
const { icon } = setup({ icon: mdiPlay, iconProps: { color: 'green', colorVariant: 'L2', hasShape: true } });
|
|
43
|
+
expect(icon).toHaveClass('lumx-icon--color-green', 'lumx-icon--color-variant-L2');
|
|
44
|
+
});
|
|
45
|
+
|
|
41
46
|
commonTestsSuiteRTL(setup, {
|
|
42
47
|
baseClassName: CLASSNAME,
|
|
43
48
|
forwardClassName: 'tab',
|
|
@@ -15,6 +15,8 @@ export interface TabProps extends GenericProps {
|
|
|
15
15
|
children?: never;
|
|
16
16
|
/** Icon (SVG path). */
|
|
17
17
|
icon?: IconProps['icon'];
|
|
18
|
+
/** Icon component properties. */
|
|
19
|
+
iconProps?: Omit<IconProps, 'icon'>;
|
|
18
20
|
/** Native id property. */
|
|
19
21
|
id?: string;
|
|
20
22
|
/** Whether the tab is active or not. */
|
|
@@ -54,6 +56,7 @@ export const Tab: Comp<TabProps, HTMLButtonElement> = forwardRef((props, ref) =>
|
|
|
54
56
|
className,
|
|
55
57
|
disabled,
|
|
56
58
|
icon,
|
|
59
|
+
iconProps = {},
|
|
57
60
|
id,
|
|
58
61
|
isActive: propIsActive,
|
|
59
62
|
isDisabled = disabled,
|
|
@@ -110,7 +113,7 @@ export const Tab: Comp<TabProps, HTMLButtonElement> = forwardRef((props, ref) =>
|
|
|
110
113
|
aria-selected={isActive}
|
|
111
114
|
aria-controls={state?.tabPanelId}
|
|
112
115
|
>
|
|
113
|
-
{icon && <Icon icon={icon} size={Size.xs} />}
|
|
116
|
+
{icon && <Icon icon={icon} size={Size.xs} {...iconProps} />}
|
|
114
117
|
{label && <span>{label}</span>}
|
|
115
118
|
</button>
|
|
116
119
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
|
|
3
|
-
import { mdiAbTesting } from '@lumx/icons';
|
|
3
|
+
import { mdiAbTesting, mdiImageBroken } from '@lumx/icons';
|
|
4
4
|
import { Alignment, AspectRatio, Badge, FlexBox, Icon, Size, Thumbnail, ThumbnailVariant } from '@lumx/react';
|
|
5
5
|
import { CustomLink } from '@lumx/react/stories/utils/CustomLink';
|
|
6
6
|
import { IMAGE_SIZES, imageArgType, IMAGES } from '@lumx/react/stories/controls/image';
|
|
@@ -44,6 +44,10 @@ export const IsLoading = {
|
|
|
44
44
|
args: { ...Simple.args, isLoading: true },
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
+
export const WithoutSource = {
|
|
48
|
+
args: { image: IMAGES.emptyImage, size: Size.xxl, aspectRatio: AspectRatio.square },
|
|
49
|
+
};
|
|
50
|
+
|
|
47
51
|
/** Thumbnail error fallback and size variants */
|
|
48
52
|
export const ErrorFallback = {
|
|
49
53
|
args: { image: 'foo' },
|
|
@@ -126,6 +130,18 @@ export const FillHeightAndRatio = {
|
|
|
126
130
|
],
|
|
127
131
|
};
|
|
128
132
|
|
|
133
|
+
/**
|
|
134
|
+
* Simple thumbnail with svg image
|
|
135
|
+
* */
|
|
136
|
+
export const WithSvgImages = {
|
|
137
|
+
args: {
|
|
138
|
+
image: IMAGES.defaultSvg,
|
|
139
|
+
size: Size.xxl,
|
|
140
|
+
fillHeight: true,
|
|
141
|
+
'focusPoint.x': 1,
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
|
|
129
145
|
export const Original = () => (
|
|
130
146
|
<>
|
|
131
147
|
<h1>Ratio: Original</h1>
|
|
@@ -74,8 +74,8 @@ export const useFocusPointStyle = (
|
|
|
74
74
|
setStyle({ visibility: 'hidden' });
|
|
75
75
|
return;
|
|
76
76
|
}
|
|
77
|
-
if (!containerSize) {
|
|
78
|
-
// Missing container size abort focus point compute.
|
|
77
|
+
if (!containerSize || !imageSize.height || !imageSize.width) {
|
|
78
|
+
// Missing container or image size abort focus point compute.
|
|
79
79
|
setStyle({});
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
@@ -3,8 +3,9 @@ import { useEffect, useState } from 'react';
|
|
|
3
3
|
export type LoadingState = 'isLoading' | 'isLoaded' | 'hasError';
|
|
4
4
|
|
|
5
5
|
function getState(img: HTMLImageElement | null | undefined, event?: Event) {
|
|
6
|
-
// Error event occurred or image
|
|
7
|
-
if (event?.type === 'error' || (img?.complete && (
|
|
6
|
+
// Error event occurred or image has no source.
|
|
7
|
+
if (event?.type === 'error' || (img?.complete && !img.getAttribute('src'))) {
|
|
8
|
+
console.log('HAS ERROR');
|
|
8
9
|
return 'hasError';
|
|
9
10
|
}
|
|
10
11
|
// Image is undefined or incomplete.
|
|
@@ -14,12 +14,23 @@ const portrait2 = '/demo-assets/portrait2.jpg';
|
|
|
14
14
|
const portrait3 = '/demo-assets/portrait3.jpg';
|
|
15
15
|
const square1 = '/demo-assets/square1.jpg';
|
|
16
16
|
const square2 = '/demo-assets/square2.jpg';
|
|
17
|
+
const defaultSvg = '/demo-assets/defaultSvg.svg';
|
|
18
|
+
const emptyImage = '';
|
|
17
19
|
|
|
18
20
|
export const AVATAR_IMAGES = { avatar1, avatar2, avatar3, avatar4 };
|
|
19
21
|
export const SQUARE_IMAGES = { square1, square2 };
|
|
22
|
+
export const SVG_IMAGES = { defaultSvg };
|
|
23
|
+
export const EMPTY_IMAGES = { emptyImage };
|
|
20
24
|
export const LANDSCAPE_IMAGES = { landscape1, landscape1s200, landscape2, landscape3 };
|
|
21
25
|
export const PORTRAIT_IMAGES = { portrait1, portrait1s200, portrait2, portrait3 };
|
|
22
|
-
export const IMAGES = {
|
|
26
|
+
export const IMAGES = {
|
|
27
|
+
...LANDSCAPE_IMAGES,
|
|
28
|
+
...PORTRAIT_IMAGES,
|
|
29
|
+
...SQUARE_IMAGES,
|
|
30
|
+
...AVATAR_IMAGES,
|
|
31
|
+
...SVG_IMAGES,
|
|
32
|
+
...EMPTY_IMAGES,
|
|
33
|
+
};
|
|
23
34
|
|
|
24
35
|
export const avatarImageArgType = getSelectArgType(AVATAR_IMAGES);
|
|
25
36
|
export const squareImageArgType = getSelectArgType(SQUARE_IMAGES);
|
|
@@ -51,9 +62,17 @@ export const PORTRAIT_IMAGE_SIZES: Record<keyof typeof PORTRAIT_IMAGES, Size> =
|
|
|
51
62
|
portrait2: { width: 350, height: 500 },
|
|
52
63
|
portrait3: { width: 300, height: 500 },
|
|
53
64
|
};
|
|
65
|
+
export const SVG_IMAGE_SIZES: Record<keyof typeof SVG_IMAGES, Size> = {
|
|
66
|
+
defaultSvg: { width: 0, height: 0 },
|
|
67
|
+
};
|
|
68
|
+
export const EMPTY_IMAGES_SIZES: Record<keyof typeof EMPTY_IMAGES, Size> = {
|
|
69
|
+
emptyImage: { width: 0, height: 0 },
|
|
70
|
+
};
|
|
54
71
|
export const IMAGE_SIZES: Record<keyof typeof IMAGES, Size> = {
|
|
55
72
|
...LANDSCAPE_IMAGE_SIZES,
|
|
56
73
|
...PORTRAIT_IMAGE_SIZES,
|
|
57
74
|
...SQUARE_IMAGE_SIZES,
|
|
58
75
|
...AVATAR_IMAGE_SIZES,
|
|
76
|
+
...SVG_IMAGE_SIZES,
|
|
77
|
+
...EMPTY_IMAGES_SIZES,
|
|
59
78
|
};
|