@lumx/react 3.7.6-alpha.9 → 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.
Files changed (33) hide show
  1. package/index.d.ts +1 -65
  2. package/index.js +551 -1293
  3. package/index.js.map +1 -1
  4. package/package.json +3 -3
  5. package/src/components/heading/Heading.test.tsx +3 -1
  6. package/src/components/heading/Heading.tsx +3 -2
  7. package/src/components/image-block/ImageBlock.stories.tsx +74 -63
  8. package/src/components/image-block/ImageBlock.tsx +1 -0
  9. package/src/components/image-block/ImageCaption.tsx +6 -6
  10. package/src/components/thumbnail/Thumbnail.stories.tsx +0 -29
  11. package/src/components/thumbnail/Thumbnail.tsx +0 -16
  12. package/src/components/thumbnail/useFocusPointStyle.tsx +4 -3
  13. package/src/hooks/useOnResize.ts +41 -0
  14. package/src/index.ts +0 -1
  15. package/src/utils/type.ts +0 -15
  16. package/src/components/image-lightbox/ImageLightbox.stories.tsx +0 -165
  17. package/src/components/image-lightbox/ImageLightbox.test.tsx +0 -252
  18. package/src/components/image-lightbox/ImageLightbox.tsx +0 -72
  19. package/src/components/image-lightbox/constants.ts +0 -11
  20. package/src/components/image-lightbox/index.ts +0 -2
  21. package/src/components/image-lightbox/internal/ImageSlide.tsx +0 -106
  22. package/src/components/image-lightbox/internal/ImageSlideshow.tsx +0 -173
  23. package/src/components/image-lightbox/internal/useAnimateScroll.ts +0 -55
  24. package/src/components/image-lightbox/internal/usePointerZoom.ts +0 -148
  25. package/src/components/image-lightbox/types.ts +0 -50
  26. package/src/components/image-lightbox/useImageLightbox.tsx +0 -130
  27. package/src/hooks/useElementSizeDependentOfWindowSize.ts +0 -32
  28. package/src/hooks/useImageSize.ts +0 -17
  29. package/src/stories/generated/ImageLightbox/Demos.stories.tsx +0 -6
  30. package/src/utils/findImage.tsx +0 -3
  31. package/src/utils/getPrefersReducedMotion.ts +0 -6
  32. package/src/utils/startViewTransition.ts +0 -54
  33. 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-alpha.9",
11
- "@lumx/icons": "^3.7.6-alpha.9",
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-alpha.9"
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={as || headingElement}
53
- typography={DEFAULT_TYPOGRAPHY_BY_LEVEL[headingElement]}
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 { toNestedProps } from '@lumx/react/stories/decorators/withNestedProps';
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 Default = (props: any) => {
34
- const nestedProps = toNestedProps(props) as any;
35
- return <ImageBlock {...nestedProps} />;
36
- };
37
-
38
- export const WithCaptionBelow: any = Default.bind({});
39
- WithCaptionBelow.args = {
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: any = Default.bind({});
47
- WithCaptionOver.args = {
48
- captionPosition: ImageBlockCaptionPosition.over,
49
- size: Size.xxl,
50
- title: 'Image block title',
51
- description: 'Image block description',
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: any = Default.bind({});
55
- WithAlign.args = {
56
- ...WithCaptionBelow.args,
57
- image: LANDSCAPE_IMAGES.landscape1s200,
58
- size: undefined,
59
- align: Alignment.center,
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: any = Default.bind({});
63
- WithTags.argTypes = {
64
- tags: { control: false },
65
- };
66
- WithTags.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
- ),
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: any = Default.bind({});
77
- WithActions.argTypes = {
78
- actions: { control: false },
79
- };
80
- WithActions.args = {
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: any = Default.bind({});
86
- WithFocusPointHorizontal.args = {
87
- size: Size.xxl,
88
- 'thumbnailProps.aspectRatio': AspectRatio.vertical,
89
- 'thumbnailProps.focusPoint.x': 1,
90
- 'thumbnailProps.focusPoint.y': 0,
91
- };
92
- WithFocusPointHorizontal.argTypes = {
93
- 'thumbnailProps.focusPoint.x': focusPoint,
94
- 'thumbnailProps.focusPoint.y': focusPoint,
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: any = Default.bind({});
98
- WithFocusPointVertical.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,
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
- WithFocusPointVertical.argTypes = {
106
- 'thumbnailProps.focusPoint.x': focusPoint,
107
- 'thumbnailProps.focusPoint.y': focusPoint,
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
  };
@@ -117,6 +117,7 @@ export const ImageBlock: Comp<ImageBlockProps, HTMLDivElement> = forwardRef((pro
117
117
  alt={(alt || title) as string}
118
118
  />
119
119
  <ImageCaption
120
+ as="figcaption"
120
121
  className={`${CLASSNAME}__wrapper`}
121
122
  theme={theme}
122
123
  title={title}
@@ -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?: boolean;
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 descriptionColor = { color: theme === 'dark' ? 'light' : 'dark', colorVariant: 'L2' } as 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 =
@@ -49,13 +49,13 @@ export const ImageCaption = <AS extends As>(props: ImageCaptionProps<AS>) => {
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" {...descriptionColor} {...descriptionContent} />}
58
+ {description && <Text as="span" typography="body1" {...descriptionContent} />}
59
59
  </Text>
60
60
  )}
61
61
  {tags && (
@@ -5,7 +5,6 @@ import {
5
5
  Alignment,
6
6
  AspectRatio,
7
7
  Badge,
8
- Button,
9
8
  FlexBox,
10
9
  GridColumn,
11
10
  Icon,
@@ -412,31 +411,3 @@ export const ObjectFit = {
412
411
  withWrapper({ maxColumns: 3, itemMinWidth: 350 }, GridColumn),
413
412
  ],
414
413
  };
415
-
416
- /**
417
- * Demonstrate loading a small image and then use it as the loading placeholder image when loading a bigger image
418
- */
419
- export const LoadingPlaceholderImage = () => {
420
- const [isShown, setShown] = React.useState(false);
421
- const imgRef = React.useRef() as React.RefObject<HTMLImageElement>;
422
- return (
423
- <>
424
- <Button onClick={() => setShown((shown) => !shown)}>
425
- Display bigger image using the small image as a placeholder
426
- </Button>
427
- <FlexBox orientation="horizontal">
428
- <Thumbnail alt="Small image" imgRef={imgRef} image="https://picsum.photos/id/15/128/85" />
429
- {isShown && (
430
- <Thumbnail
431
- loadingPlaceholderImageRef={imgRef}
432
- style={{ maxWidth: 300 }}
433
- alt="Large image"
434
- image="https://picsum.photos/id/15/2500/1667"
435
- />
436
- )}
437
- </FlexBox>
438
- </>
439
- );
440
- };
441
- // Disables Chromatic snapshot (not relevant for this story).
442
- LoadingPlaceholderImage.parameters = { chromatic: { disable: true } };
@@ -58,8 +58,6 @@ export interface ThumbnailProps extends GenericProps, HasTheme {
58
58
  size?: ThumbnailSize;
59
59
  /** Image loading mode. */
60
60
  loading?: ImgHTMLProps['loading'];
61
- /** Ref of an existing placeholder image to display while loading. */
62
- loadingPlaceholderImageRef?: React.RefObject<HTMLImageElement>;
63
61
  /** On click callback. */
64
62
  onClick?: MouseEventHandler<HTMLDivElement>;
65
63
  /** On key press callback. */
@@ -117,7 +115,6 @@ export const Thumbnail: Comp<ThumbnailProps> = forwardRef((props, ref) => {
117
115
  isLoading: isLoadingProp,
118
116
  objectFit,
119
117
  loading,
120
- loadingPlaceholderImageRef,
121
118
  size,
122
119
  theme,
123
120
  variant,
@@ -162,18 +159,6 @@ export const Thumbnail: Comp<ThumbnailProps> = forwardRef((props, ref) => {
162
159
  wrapperProps['aria-label'] = forwardedProps['aria-label'] || alt;
163
160
  }
164
161
 
165
- // If we have a loading placeholder image that is really loaded (complete)
166
- const loadingPlaceholderImage =
167
- (isLoading && loadingPlaceholderImageRef?.current?.complete && loadingPlaceholderImageRef?.current) ||
168
- undefined;
169
- const loadingStyle = loadingPlaceholderImage
170
- ? {
171
- backgroundImage: `url(${loadingPlaceholderImage.src})`,
172
- minWidth: loadingPlaceholderImage.naturalWidth,
173
- minHeight: loadingPlaceholderImage.naturalHeight,
174
- }
175
- : undefined;
176
-
177
162
  return (
178
163
  <Wrapper
179
164
  {...wrapperProps}
@@ -206,7 +191,6 @@ export const Thumbnail: Comp<ThumbnailProps> = forwardRef((props, ref) => {
206
191
  ...imgProps?.style,
207
192
  ...imageErrorStyle,
208
193
  ...focusPointStyle,
209
- ...loadingStyle,
210
194
  }}
211
195
  ref={mergeRefs(setImgElement, propImgRef)}
212
196
  className={classNames(
@@ -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: RectSize | undefined = useMemo(() => {
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<RectSize | undefined>(undefined);
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
- };