@lumx/react 3.7.6-alpha.8 → 3.7.6-test.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 +1 -63
- package/index.js +551 -1286
- package/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/heading/Heading.test.tsx +3 -1
- package/src/components/heading/Heading.tsx +3 -2
- package/src/components/image-block/ImageBlock.stories.tsx +74 -63
- package/src/components/image-block/ImageBlock.tsx +1 -0
- package/src/components/image-block/ImageCaption.tsx +7 -7
- package/src/components/thumbnail/useFocusPointStyle.tsx +4 -3
- package/src/hooks/useOnResize.ts +41 -0
- package/src/index.ts +0 -1
- package/src/utils/type.ts +0 -15
- package/src/components/image-lightbox/ImageLightbox.stories.tsx +0 -165
- package/src/components/image-lightbox/ImageLightbox.test.tsx +0 -252
- package/src/components/image-lightbox/ImageLightbox.tsx +0 -72
- package/src/components/image-lightbox/constants.ts +0 -11
- package/src/components/image-lightbox/index.ts +0 -2
- package/src/components/image-lightbox/internal/ImageSlide.tsx +0 -106
- package/src/components/image-lightbox/internal/ImageSlideshow.tsx +0 -173
- package/src/components/image-lightbox/internal/useAnimateScroll.ts +0 -55
- package/src/components/image-lightbox/internal/usePointerZoom.ts +0 -148
- package/src/components/image-lightbox/types.ts +0 -47
- package/src/components/image-lightbox/useImageLightbox.tsx +0 -135
- package/src/hooks/useElementSizeDependentOfWindowSize.ts +0 -32
- package/src/hooks/useImageSize.ts +0 -17
- package/src/stories/generated/ImageLightbox/Demos.stories.tsx +0 -6
- package/src/utils/findImage.tsx +0 -3
- package/src/utils/getPrefersReducedMotion.ts +0 -6
- package/src/utils/startViewTransition.ts +0 -54
- package/src/utils/unref.ts +0 -6
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.7.6-
|
|
11
|
-
"@lumx/icons": "^3.7.6-
|
|
10
|
+
"@lumx/core": "^3.7.6-test.0",
|
|
11
|
+
"@lumx/icons": "^3.7.6-test.0",
|
|
12
12
|
"@popperjs/core": "^2.5.4",
|
|
13
13
|
"body-scroll-lock": "^3.1.5",
|
|
14
14
|
"classnames": "^2.3.2",
|
|
@@ -112,5 +112,5 @@
|
|
|
112
112
|
"build:storybook": "storybook build"
|
|
113
113
|
},
|
|
114
114
|
"sideEffects": false,
|
|
115
|
-
"version": "3.7.6-
|
|
115
|
+
"version": "3.7.6-test.0"
|
|
116
116
|
}
|
|
@@ -21,13 +21,15 @@ describe(`<${Heading.displayName}>`, () => {
|
|
|
21
21
|
const heading = screen.getByRole('heading', { level: 1, name: 'Some text' });
|
|
22
22
|
expect(heading).toBeInTheDocument();
|
|
23
23
|
expect(heading).toHaveClass(CLASSNAME);
|
|
24
|
+
expect(heading).toHaveClass('lumx-typography-display1');
|
|
24
25
|
});
|
|
25
26
|
|
|
26
|
-
it('should render with as', () => {
|
|
27
|
+
it('should render with as with the correct default typography', () => {
|
|
27
28
|
setup({ children: 'Some text', as: 'h2' });
|
|
28
29
|
const heading = screen.getByRole('heading', { level: 2, name: 'Some text' });
|
|
29
30
|
expect(heading).toBeInTheDocument();
|
|
30
31
|
expect(heading).toHaveClass(CLASSNAME);
|
|
32
|
+
expect(heading).toHaveClass('lumx-typography-headline');
|
|
31
33
|
});
|
|
32
34
|
|
|
33
35
|
it('should correctly render levels nested in HeadingLevel', () => {
|
|
@@ -40,6 +40,7 @@ export const Heading: Comp<HeadingProps> = forwardRef((props, ref) => {
|
|
|
40
40
|
const { children, as, className, ...forwardedProps } = props;
|
|
41
41
|
const { headingElement } = useHeadingLevel();
|
|
42
42
|
|
|
43
|
+
const computedHeadingElement = as || headingElement;
|
|
43
44
|
return (
|
|
44
45
|
<Text
|
|
45
46
|
ref={ref}
|
|
@@ -49,8 +50,8 @@ export const Heading: Comp<HeadingProps> = forwardRef((props, ref) => {
|
|
|
49
50
|
prefix: CLASSNAME,
|
|
50
51
|
}),
|
|
51
52
|
)}
|
|
52
|
-
as={
|
|
53
|
-
typography={DEFAULT_TYPOGRAPHY_BY_LEVEL[
|
|
53
|
+
as={computedHeadingElement}
|
|
54
|
+
typography={DEFAULT_TYPOGRAPHY_BY_LEVEL[computedHeadingElement]}
|
|
54
55
|
{...forwardedProps}
|
|
55
56
|
>
|
|
56
57
|
{children}
|
|
@@ -15,94 +15,105 @@ import {
|
|
|
15
15
|
import { getSelectArgType } from '@lumx/react/stories/controls/selectArgType';
|
|
16
16
|
import { imageArgType, PORTRAIT_IMAGES, LANDSCAPE_IMAGES } from '@lumx/react/stories/controls/image';
|
|
17
17
|
import { mdiFileEdit } from '@lumx/icons';
|
|
18
|
-
import {
|
|
18
|
+
import { withNestedProps } from '@lumx/react/stories/decorators/withNestedProps';
|
|
19
19
|
import { focusPoint } from '@lumx/react/stories/controls/focusPoint';
|
|
20
|
+
import { withWrapper } from '@lumx/react/stories/decorators/withWrapper';
|
|
20
21
|
|
|
21
22
|
export default {
|
|
22
23
|
title: 'LumX components/image-block/Image Block',
|
|
24
|
+
component: ImageBlock,
|
|
23
25
|
argTypes: {
|
|
24
26
|
size: getSelectArgType<ImageBlockSize>([Size.xl, Size.xxl]),
|
|
25
27
|
image: imageArgType,
|
|
26
28
|
captionPosition: getSelectArgType(ImageBlockCaptionPosition),
|
|
27
29
|
'thumbnailProps.aspectRatio': getSelectArgType(AspectRatio),
|
|
28
30
|
align: getSelectArgType<HorizontalAlignment>([Alignment.left, Alignment.center, Alignment.right]),
|
|
31
|
+
tags: { control: false },
|
|
32
|
+
actions: { control: false },
|
|
29
33
|
},
|
|
30
34
|
args: { ...ImageBlock.defaultProps, image: LANDSCAPE_IMAGES.landscape1 },
|
|
35
|
+
decorators: [withNestedProps()],
|
|
31
36
|
};
|
|
32
37
|
|
|
33
|
-
export const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
captionPosition: ImageBlockCaptionPosition.below,
|
|
41
|
-
size: Size.xxl,
|
|
42
|
-
title: 'Image block title',
|
|
43
|
-
description: 'Image block description',
|
|
38
|
+
export const WithCaptionBelow = {
|
|
39
|
+
args: {
|
|
40
|
+
captionPosition: ImageBlockCaptionPosition.below,
|
|
41
|
+
size: Size.xxl,
|
|
42
|
+
title: 'Image block title',
|
|
43
|
+
description: 'Image block description',
|
|
44
|
+
},
|
|
44
45
|
};
|
|
45
46
|
|
|
46
|
-
export const WithCaptionOver
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
export const WithCaptionOver = {
|
|
48
|
+
args: {
|
|
49
|
+
captionPosition: ImageBlockCaptionPosition.over,
|
|
50
|
+
size: Size.xxl,
|
|
51
|
+
title: 'Image block title',
|
|
52
|
+
description: 'Image block description',
|
|
53
|
+
},
|
|
52
54
|
};
|
|
53
55
|
|
|
54
|
-
export const WithAlign
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
export const WithAlign = {
|
|
57
|
+
args: {
|
|
58
|
+
...WithCaptionBelow.args,
|
|
59
|
+
image: LANDSCAPE_IMAGES.landscape1s200,
|
|
60
|
+
size: undefined,
|
|
61
|
+
align: Alignment.center,
|
|
62
|
+
},
|
|
60
63
|
};
|
|
61
64
|
|
|
62
|
-
export const WithTags
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
</ChipGroup>
|
|
73
|
-
),
|
|
65
|
+
export const WithTags = {
|
|
66
|
+
args: {
|
|
67
|
+
size: Size.xxl,
|
|
68
|
+
tags: (
|
|
69
|
+
<ChipGroup align={Alignment.left}>
|
|
70
|
+
<Chip size={Size.s}>Tag 1</Chip>
|
|
71
|
+
<Chip size={Size.s}>Tag 2</Chip>
|
|
72
|
+
</ChipGroup>
|
|
73
|
+
),
|
|
74
|
+
},
|
|
74
75
|
};
|
|
75
76
|
|
|
76
|
-
export const WithActions
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
size: Size.xxl,
|
|
82
|
-
actions: <IconButton label="Edit" icon={mdiFileEdit} />,
|
|
77
|
+
export const WithActions = {
|
|
78
|
+
args: {
|
|
79
|
+
size: Size.xxl,
|
|
80
|
+
actions: <IconButton label="Edit" icon={mdiFileEdit} />,
|
|
81
|
+
},
|
|
83
82
|
};
|
|
84
83
|
|
|
85
|
-
export const WithFocusPointHorizontal
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
84
|
+
export const WithFocusPointHorizontal = {
|
|
85
|
+
args: {
|
|
86
|
+
size: Size.xxl,
|
|
87
|
+
'thumbnailProps.aspectRatio': AspectRatio.vertical,
|
|
88
|
+
'thumbnailProps.focusPoint.x': 1,
|
|
89
|
+
'thumbnailProps.focusPoint.y': 0,
|
|
90
|
+
},
|
|
91
|
+
argTypes: {
|
|
92
|
+
'thumbnailProps.focusPoint.x': focusPoint,
|
|
93
|
+
'thumbnailProps.focusPoint.y': focusPoint,
|
|
94
|
+
},
|
|
95
95
|
};
|
|
96
96
|
|
|
97
|
-
export const WithFocusPointVertical
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
97
|
+
export const WithFocusPointVertical = {
|
|
98
|
+
args: {
|
|
99
|
+
size: Size.xxl,
|
|
100
|
+
image: PORTRAIT_IMAGES.portrait1,
|
|
101
|
+
'thumbnailProps.aspectRatio': AspectRatio.horizontal,
|
|
102
|
+
'thumbnailProps.focusPoint.x': 0,
|
|
103
|
+
'thumbnailProps.focusPoint.y': 1,
|
|
104
|
+
},
|
|
105
|
+
argTypes: {
|
|
106
|
+
'thumbnailProps.focusPoint.x': focusPoint,
|
|
107
|
+
'thumbnailProps.focusPoint.y': focusPoint,
|
|
108
|
+
},
|
|
104
109
|
};
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
export const FullFeatured = {
|
|
111
|
+
args: {
|
|
112
|
+
...WithCaptionBelow.args,
|
|
113
|
+
...WithTags.args,
|
|
114
|
+
...WithActions.args,
|
|
115
|
+
...WithFocusPointVertical.args,
|
|
116
|
+
...WithAlign.args,
|
|
117
|
+
},
|
|
118
|
+
decorators: [withWrapper({ style: { width: 400, height: 300 } })],
|
|
108
119
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
|
|
3
|
-
import { FlexBox, HorizontalAlignment, Text } from '@lumx/react';
|
|
3
|
+
import { FlexBox, HorizontalAlignment, Text, TextProps } from '@lumx/react';
|
|
4
4
|
import { HasClassName, HasPolymorphicAs, HasTheme } from '@lumx/react/utils/type';
|
|
5
5
|
|
|
6
6
|
type As = 'div' | 'figcaption';
|
|
@@ -22,8 +22,8 @@ export type ImageCaptionProps<AS extends As = 'figcaption'> = HasTheme &
|
|
|
22
22
|
ImageCaptionMetadata & {
|
|
23
23
|
/** Alignment. */
|
|
24
24
|
align?: HorizontalAlignment;
|
|
25
|
-
/** Truncate title & description */
|
|
26
|
-
truncate?:
|
|
25
|
+
/** Truncate text on title & description (no line wrapping). */
|
|
26
|
+
truncate?: TextProps['truncate'];
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
/** Internal component used to render image captions */
|
|
@@ -32,7 +32,7 @@ export const ImageCaption = <AS extends As>(props: ImageCaptionProps<AS>) => {
|
|
|
32
32
|
if (!title && !description && !tags) return null;
|
|
33
33
|
|
|
34
34
|
const titleColor = { color: theme === 'dark' ? 'light' : 'dark' } as const;
|
|
35
|
-
const
|
|
35
|
+
const baseColor = { color: theme === 'dark' ? 'light' : 'dark', colorVariant: 'L2' } as const;
|
|
36
36
|
|
|
37
37
|
// Display description as string or HTML
|
|
38
38
|
const descriptionContent =
|
|
@@ -43,19 +43,19 @@ export const ImageCaption = <AS extends As>(props: ImageCaptionProps<AS>) => {
|
|
|
43
43
|
as={as}
|
|
44
44
|
className={className}
|
|
45
45
|
style={captionStyle}
|
|
46
|
-
orientation="
|
|
46
|
+
orientation="vertical"
|
|
47
47
|
vAlign={align}
|
|
48
48
|
hAlign={align === 'center' ? align : undefined}
|
|
49
49
|
gap="regular"
|
|
50
50
|
>
|
|
51
51
|
{(title || description) && (
|
|
52
|
-
<Text as="p" truncate={truncate}>
|
|
52
|
+
<Text as="p" truncate={truncate} {...baseColor}>
|
|
53
53
|
{title && (
|
|
54
54
|
<Text as="span" typography="subtitle1" {...titleColor}>
|
|
55
55
|
{title}
|
|
56
56
|
</Text>
|
|
57
57
|
)}{' '}
|
|
58
|
-
{description && <Text as="span" typography="body1" {...
|
|
58
|
+
{description && <Text as="span" typography="body1" {...descriptionContent} />}
|
|
59
59
|
</Text>
|
|
60
60
|
)}
|
|
61
61
|
{tags && (
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { CSSProperties, useEffect, useMemo, useState } from 'react';
|
|
2
2
|
import { AspectRatio } from '@lumx/react/components';
|
|
3
3
|
import { ThumbnailProps } from '@lumx/react/components/thumbnail/Thumbnail';
|
|
4
|
-
import { RectSize } from '@lumx/react/utils/type';
|
|
5
4
|
|
|
6
5
|
// Calculate shift to center the focus point in the container.
|
|
7
6
|
export function shiftPosition({
|
|
@@ -25,6 +24,8 @@ export function shiftPosition({
|
|
|
25
24
|
return Math.floor(Math.max(Math.min(shift, 1), 0) * 100);
|
|
26
25
|
}
|
|
27
26
|
|
|
27
|
+
type Size = { width: number; height: number };
|
|
28
|
+
|
|
28
29
|
// Compute CSS properties to apply the focus point.
|
|
29
30
|
export const useFocusPointStyle = (
|
|
30
31
|
{ image, aspectRatio, focusPoint, imgProps: { width, height } = {} }: ThumbnailProps,
|
|
@@ -32,7 +33,7 @@ export const useFocusPointStyle = (
|
|
|
32
33
|
isLoaded: boolean,
|
|
33
34
|
): CSSProperties => {
|
|
34
35
|
// Get natural image size from imgProps or img element.
|
|
35
|
-
const imageSize:
|
|
36
|
+
const imageSize: Size | undefined = useMemo(() => {
|
|
36
37
|
// Focus point is not applicable => exit early
|
|
37
38
|
if (!image || aspectRatio === AspectRatio.original || (!focusPoint?.x && !focusPoint?.y)) return undefined;
|
|
38
39
|
if (typeof width === 'number' && typeof height === 'number') return { width, height };
|
|
@@ -41,7 +42,7 @@ export const useFocusPointStyle = (
|
|
|
41
42
|
}, [aspectRatio, element, focusPoint?.x, focusPoint?.y, height, image, isLoaded, width]);
|
|
42
43
|
|
|
43
44
|
// Get container size (dependant on imageSize).
|
|
44
|
-
const [containerSize, setContainerSize] = useState<
|
|
45
|
+
const [containerSize, setContainerSize] = useState<Size | undefined>(undefined);
|
|
45
46
|
useEffect(
|
|
46
47
|
function updateContainerSize() {
|
|
47
48
|
const cWidth = element?.offsetWidth;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Callback, Falsy } from '@lumx/react/utils/type';
|
|
2
|
+
import { MutableRefObject, RefObject, useEffect, useRef } from 'react';
|
|
3
|
+
import { WINDOW } from '@lumx/react/constants';
|
|
4
|
+
import { ResizeObserver as Polyfill } from '@juggle/resize-observer';
|
|
5
|
+
|
|
6
|
+
const ResizeObserver: typeof Polyfill = (WINDOW as any)?.ResizeObserver || Polyfill;
|
|
7
|
+
|
|
8
|
+
export function useOnResize(element: HTMLElement | Falsy, update: RefObject<Callback>): void {
|
|
9
|
+
const observerRef = useRef(null) as MutableRefObject<Polyfill | null>;
|
|
10
|
+
const previousSize = useRef<{ width: number; height: number }>();
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (!element || !update) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
previousSize.current = undefined;
|
|
18
|
+
const observer =
|
|
19
|
+
observerRef.current ||
|
|
20
|
+
new ResizeObserver(([entry]) => {
|
|
21
|
+
const updateFunction = update.current;
|
|
22
|
+
if (!updateFunction) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const { width, height } = entry.contentRect;
|
|
27
|
+
if (previousSize.current?.width === width && previousSize.current?.height === height) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
window.requestAnimationFrame(() => updateFunction());
|
|
32
|
+
previousSize.current = entry.contentRect;
|
|
33
|
+
});
|
|
34
|
+
if (!observerRef.current) observerRef.current = observer;
|
|
35
|
+
|
|
36
|
+
observer.observe(element);
|
|
37
|
+
return () => {
|
|
38
|
+
observer.unobserve(element);
|
|
39
|
+
};
|
|
40
|
+
}, [element, update]);
|
|
41
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -25,7 +25,6 @@ export * from './components/grid';
|
|
|
25
25
|
export * from './components/grid-column';
|
|
26
26
|
export * from './components/icon';
|
|
27
27
|
export * from './components/image-block';
|
|
28
|
-
export * from './components/image-lightbox';
|
|
29
28
|
export * from './components/inline-list';
|
|
30
29
|
export * from './components/input-helper';
|
|
31
30
|
export * from './components/input-label';
|
package/src/utils/type.ts
CHANGED
|
@@ -139,18 +139,3 @@ export type ComponentRef<C> = C extends keyof JSX.IntrinsicElements
|
|
|
139
139
|
: C extends React.JSXElementConstructor<{ ref?: infer R }>
|
|
140
140
|
? R
|
|
141
141
|
: never;
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Rectangle size
|
|
145
|
-
*/
|
|
146
|
-
export type RectSize = { width: number; height: number };
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Maybe a HTMLElement or a React ref of a HTMLElement
|
|
150
|
-
*/
|
|
151
|
-
export type MaybeElementOrRef<E extends HTMLElement> = E | React.RefObject<E | null> | null | undefined;
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* A point coordinate in 2D space
|
|
155
|
-
*/
|
|
156
|
-
export type Point = { x: number; y: number };
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { IMAGES } from '@lumx/react/stories/controls/image';
|
|
3
|
-
import { Button, Mosaic, ImageLightbox, ImageLightboxProps, Chip, ChipGroup } from '@lumx/react';
|
|
4
|
-
import { withWrapper } from '@lumx/react/stories/decorators/withWrapper';
|
|
5
|
-
|
|
6
|
-
const ZOOM_PROPS = {
|
|
7
|
-
zoomInButtonProps: { label: 'Zoom in' },
|
|
8
|
-
zoomOutButtonProps: { label: 'Zoom out' },
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const SLIDESHOW_PROPS = {
|
|
12
|
-
slideshowControlsProps: {
|
|
13
|
-
nextButtonProps: { label: 'Next' },
|
|
14
|
-
previousButtonProps: { label: 'Previous' },
|
|
15
|
-
paginationItemProps: (index: number) => ({ label: `Go to slide ${index + 1}` }),
|
|
16
|
-
},
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const MULTIPLE_IMAGES: ImageLightboxProps['images'] = [
|
|
20
|
-
{
|
|
21
|
-
image: 'https://picsum.photos/id/237/2000/3000',
|
|
22
|
-
alt: 'Image 1',
|
|
23
|
-
title: 'Little puppy',
|
|
24
|
-
description: 'A black labrador puppy with big brown eyes, looking up with a curious and innocent expression.',
|
|
25
|
-
tags: (
|
|
26
|
-
<ChipGroup>
|
|
27
|
-
<Chip theme="dark" size="s">
|
|
28
|
-
Tag 1
|
|
29
|
-
</Chip>
|
|
30
|
-
<Chip theme="dark" size="s">
|
|
31
|
-
Tag 2
|
|
32
|
-
</Chip>
|
|
33
|
-
</ChipGroup>
|
|
34
|
-
),
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
image: 'https://picsum.photos/id/337/3000/1000',
|
|
38
|
-
alt: 'Image 2',
|
|
39
|
-
// Intentionally using the wrong size to see how it renders while loading the image
|
|
40
|
-
imgProps: { width: '300px', height: '100px' },
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
image: 'https://picsum.photos/id/437/2000/2000',
|
|
44
|
-
alt: 'Image 3',
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
image: 'https://picsum.photos/id/537/300/400',
|
|
48
|
-
alt: 'Image 4',
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
image: 'https://picsum.photos/id/637/400/200',
|
|
52
|
-
alt: 'Image 5',
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
image: 'https://picsum.photos/id/737/300/300',
|
|
56
|
-
alt: 'Image 6',
|
|
57
|
-
},
|
|
58
|
-
];
|
|
59
|
-
|
|
60
|
-
export default {
|
|
61
|
-
title: 'LumX components/image-lightbox/ImageLightbox',
|
|
62
|
-
component: ImageLightbox,
|
|
63
|
-
args: {
|
|
64
|
-
closeButtonProps: { label: 'Close' },
|
|
65
|
-
},
|
|
66
|
-
argTypes: {
|
|
67
|
-
onClose: { action: true },
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Display a single image fullscreen in the ImageLightbox
|
|
73
|
-
*/
|
|
74
|
-
export const SingleImage = {
|
|
75
|
-
args: {
|
|
76
|
-
images: [{ image: IMAGES.portrait1s200, alt: 'Image 1' }],
|
|
77
|
-
isOpen: true,
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Display a single image fullscreen in the ImageLightbox with zoom controls
|
|
83
|
-
*/
|
|
84
|
-
export const SingleImageWithZoom = {
|
|
85
|
-
...SingleImage,
|
|
86
|
-
args: { ...SingleImage.args, ...ZOOM_PROPS },
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Display a single image fullscreen in the ImageLightbox with metadata (title, description, etc.)
|
|
91
|
-
*/
|
|
92
|
-
export const SingleImageWithMetadata = {
|
|
93
|
-
...SingleImage,
|
|
94
|
-
args: { ...SingleImage.args, images: [MULTIPLE_IMAGES[0]] },
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Display a multiple image fullscreen in the ImageLightbox
|
|
99
|
-
*/
|
|
100
|
-
export const MultipleImages = {
|
|
101
|
-
args: {
|
|
102
|
-
images: MULTIPLE_IMAGES,
|
|
103
|
-
isOpen: true,
|
|
104
|
-
...SLIDESHOW_PROPS,
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Display a multiple images fullscreen in the ImageLightbox with zoom controls
|
|
110
|
-
*/
|
|
111
|
-
export const MultipleImagesWithZoom = {
|
|
112
|
-
...MultipleImages,
|
|
113
|
-
args: { ...MultipleImages.args, ...ZOOM_PROPS },
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Open ImageLightbox via buttons
|
|
118
|
-
*/
|
|
119
|
-
export const WithButtonTrigger = {
|
|
120
|
-
decorators: [
|
|
121
|
-
(Story: any, { args }: any) => {
|
|
122
|
-
const { getTriggerProps, imageLightboxProps } = ImageLightbox.useImageLightbox({
|
|
123
|
-
images: [
|
|
124
|
-
{ image: IMAGES.portrait1s200, alt: 'Image 1' },
|
|
125
|
-
{ image: IMAGES.landscape1s200, alt: 'Image 2' },
|
|
126
|
-
],
|
|
127
|
-
});
|
|
128
|
-
return (
|
|
129
|
-
<>
|
|
130
|
-
<Story args={{ ...args, ...imageLightboxProps }} />
|
|
131
|
-
<Button {...(getTriggerProps({ activeImageIndex: 0 }) as any)}>Image 1</Button>
|
|
132
|
-
<Button {...(getTriggerProps({ activeImageIndex: 1 }) as any)}>Image 2</Button>
|
|
133
|
-
</>
|
|
134
|
-
);
|
|
135
|
-
},
|
|
136
|
-
],
|
|
137
|
-
// Disables Chromatic snapshot (not relevant for this story).
|
|
138
|
-
parameters: { chromatic: { disable: true } },
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Open ImageLightbox with zoom and slideshow via clickable thumbnails in a Mosaic
|
|
143
|
-
*/
|
|
144
|
-
export const WithMosaicTrigger = {
|
|
145
|
-
args: { ...SLIDESHOW_PROPS, ...ZOOM_PROPS },
|
|
146
|
-
decorators: [
|
|
147
|
-
(Story: any, { args }: any) => {
|
|
148
|
-
const { getTriggerProps, imageLightboxProps } = ImageLightbox.useImageLightbox({ images: MULTIPLE_IMAGES });
|
|
149
|
-
return (
|
|
150
|
-
<>
|
|
151
|
-
<Story args={{ ...args, ...imageLightboxProps }} />
|
|
152
|
-
<Mosaic
|
|
153
|
-
thumbnails={MULTIPLE_IMAGES.map((image, index) => ({
|
|
154
|
-
...image,
|
|
155
|
-
...getTriggerProps({ activeImageIndex: index }),
|
|
156
|
-
}))}
|
|
157
|
-
/>
|
|
158
|
-
</>
|
|
159
|
-
);
|
|
160
|
-
},
|
|
161
|
-
withWrapper({ style: { width: 300 } }),
|
|
162
|
-
],
|
|
163
|
-
// Disables Chromatic snapshot (not relevant for this story).
|
|
164
|
-
parameters: { chromatic: { disable: true } },
|
|
165
|
-
};
|