@lumx/react 2.2.22 → 2.2.23

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.
@@ -0,0 +1,106 @@
1
+ import React from 'react';
2
+ import { mdiPencil } from '@lumx/icons';
3
+ import { GenericBlock, Button, Icon, Size } from '@lumx/react';
4
+
5
+ export default { title: 'LumX components/generic-block/GenericBlock' };
6
+
7
+ const redBorderStyle = { border: '1px solid red' };
8
+
9
+ export const SectionsInProps = ({ theme }) => (
10
+ <GenericBlock
11
+ figure={<Icon icon={mdiPencil} size={Size.m} />}
12
+ actionsProps={{ style: redBorderStyle }}
13
+ figureProps={{ style: redBorderStyle }}
14
+ contentProps={{ style: redBorderStyle }}
15
+ actions={<Button theme={theme}>Button</Button>}
16
+ >
17
+ Content
18
+ </GenericBlock>
19
+ );
20
+
21
+ export const SectionsInChildren = ({ theme }) => (
22
+ <GenericBlock>
23
+ <GenericBlock.Figure style={redBorderStyle}>
24
+ <Icon icon={mdiPencil} size={Size.m} />
25
+ </GenericBlock.Figure>
26
+ <GenericBlock.Content style={redBorderStyle}>Content</GenericBlock.Content>
27
+ <GenericBlock.Actions style={redBorderStyle}>
28
+ <Button theme={theme}>Button</Button>
29
+ </GenericBlock.Actions>
30
+ </GenericBlock>
31
+ );
32
+
33
+ const Template = ({ theme, ...props }) => (
34
+ <GenericBlock {...props}>
35
+ <GenericBlock.Figure style={redBorderStyle} {...props.figureProps}>
36
+ <Icon icon={mdiPencil} size={Size.m} />
37
+ </GenericBlock.Figure>
38
+ <GenericBlock.Content style={redBorderStyle} {...props.contentProps}>
39
+ {props.content || 'Content'}
40
+ </GenericBlock.Content>
41
+ <GenericBlock.Actions style={redBorderStyle} {...props.actionsProps}>
42
+ <Button theme={theme}>Button</Button>
43
+ </GenericBlock.Actions>
44
+ </GenericBlock>
45
+ );
46
+
47
+ export const Vertical = Template.bind({});
48
+ Vertical.args = {
49
+ orientation: 'vertical',
50
+ };
51
+
52
+ export const VerticalAlignCenter = Template.bind({});
53
+ VerticalAlignCenter.args = {
54
+ orientation: 'vertical',
55
+ vAlign: 'center',
56
+ };
57
+
58
+ export const VerticalOverflow = Template.bind({});
59
+ VerticalOverflow.args = {
60
+ orientation: 'vertical',
61
+ style: { width: 300 },
62
+ content: (
63
+ <span style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>
64
+ _________________________________________________________________
65
+ </span>
66
+ ),
67
+ };
68
+
69
+ export const Horizontal = Template.bind({});
70
+ Horizontal.args = {
71
+ orientation: 'horizontal',
72
+ };
73
+
74
+ export const HorizontalAlignRightBottom = Template.bind({});
75
+ HorizontalAlignRightBottom.args = {
76
+ orientation: 'horizontal',
77
+ vAlign: 'right',
78
+ hAlign: 'bottom',
79
+ };
80
+
81
+ export const HorizontalOverflow = Template.bind({});
82
+ HorizontalOverflow.args = {
83
+ orientation: 'horizontal',
84
+ style: { width: 300 },
85
+ content: (
86
+ <span style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>
87
+ _________________________________________________________________
88
+ </span>
89
+ ),
90
+ };
91
+
92
+ export const GapSizes = ({ theme }) =>
93
+ [Size.regular, Size.big, Size.huge].map((gap) => (
94
+ <GenericBlock key={gap} orientation="vertical" gap={gap} style={{ marginBottom: 40 }}>
95
+ <GenericBlock.Figure style={redBorderStyle}>
96
+ <Icon icon={mdiPencil} size={Size.m} />
97
+ </GenericBlock.Figure>
98
+ <GenericBlock.Content style={redBorderStyle}>
99
+ <h2>{gap} gap size</h2>
100
+ <p>block description</p>
101
+ </GenericBlock.Content>
102
+ <GenericBlock.Actions style={redBorderStyle}>
103
+ <Button theme={theme}>Button</Button>
104
+ </GenericBlock.Actions>
105
+ </GenericBlock>
106
+ ));
@@ -3,7 +3,7 @@ import { mount, shallow } from 'enzyme';
3
3
  import 'jest-enzyme';
4
4
  import { commonTestsSuite } from '@lumx/react/testing/utils';
5
5
 
6
- import { GenericBlock, GenericBlockProps } from './GenericBlock';
6
+ import { GenericBlock, GenericBlockProps } from '.';
7
7
 
8
8
  const CLASSNAME = GenericBlock.className as string;
9
9
 
@@ -20,43 +20,51 @@ describe(`<${GenericBlock.displayName}>`, () => {
20
20
  // 1. Test render via snapshot.
21
21
  describe('Snapshots and structure', () => {
22
22
  it('should render default', () => {
23
- const wrapper = shallow(<GenericBlock>Content</GenericBlock>);
23
+ const wrapper = shallow(
24
+ <GenericBlock figure="figure" actions="actions">
25
+ Content
26
+ </GenericBlock>,
27
+ );
24
28
 
25
- expect(wrapper.prop('gap')).toBe('regular');
26
- expect(wrapper.prop('hAlign')).toBe('center');
27
- expect(wrapper.prop('orientation')).toBe('vertical');
28
- expect(wrapper.prop('vAlign')).toBe('center');
29
+ expect(wrapper.prop('gap')).toBe('big');
30
+ expect(wrapper.prop('orientation')).toBe('horizontal');
29
31
 
30
32
  const figure = wrapper.find('.lumx-generic-block__figure');
31
- expect(figure).toBeDefined();
33
+ expect(figure).toHaveLength(1);
32
34
 
33
35
  const content = wrapper.find('.lumx-generic-block__content');
36
+ expect(content).toHaveLength(1);
34
37
  expect(content.prop('fillSpace')).toBe(true);
35
- expect(content.prop('vAlign')).toBe('center');
36
38
  expect(content.prop('orientation')).toBe('vertical');
37
39
 
38
40
  const actions = wrapper.find('.lumx-generic-block__actions');
39
- expect(actions.prop('vAlign')).toBe('center');
41
+ expect(actions).toHaveLength(1);
40
42
  });
41
43
 
42
- it('should render horizontal', () => {
43
- const wrapper = shallow(<GenericBlock orientation="horizontal">Content</GenericBlock>);
44
+ it('should forward vAlign & hAlign', () => {
45
+ const wrapper = shallow(
46
+ <GenericBlock figure="figure" actions="actions" vAlign="left" hAlign="bottom">
47
+ Content
48
+ </GenericBlock>,
49
+ );
44
50
 
45
- expect(wrapper.prop('gap')).toBe('regular');
46
- expect(wrapper.prop('hAlign')).toBe('center');
47
- expect(wrapper.prop('orientation')).toBe('horizontal');
48
- expect(wrapper.prop('vAlign')).toBe('center');
51
+ expect(wrapper.prop('vAlign')).toBe('left');
52
+ expect(wrapper.prop('hAlign')).toBe('bottom');
49
53
 
50
54
  const figure = wrapper.find('.lumx-generic-block__figure');
51
- expect(figure).toBeDefined();
55
+ expect(figure).toHaveLength(1);
56
+ expect(figure.prop('vAlign')).toBe('left');
57
+ expect(figure.prop('hAlign')).toBe('bottom');
52
58
 
53
59
  const content = wrapper.find('.lumx-generic-block__content');
54
- expect(content.prop('fillSpace')).toBe(true);
60
+ expect(content).toHaveLength(1);
55
61
  expect(content.prop('vAlign')).toBe('left');
56
- expect(content.prop('orientation')).toBe('vertical');
62
+ expect(content.prop('hAlign')).toBe('bottom');
57
63
 
58
64
  const actions = wrapper.find('.lumx-generic-block__actions');
59
- expect(actions.prop('vAlign')).toBe('right');
65
+ expect(actions).toHaveLength(1);
66
+ expect(actions.prop('vAlign')).toBe('left');
67
+ expect(actions.prop('hAlign')).toBe('bottom');
60
68
  });
61
69
 
62
70
  it('should combine figure props', () => {
@@ -74,6 +82,9 @@ describe(`<${GenericBlock.displayName}>`, () => {
74
82
  expect(figure.prop('fillSpace')).toBe(true);
75
83
  expect(figure.prop('vAlign')).toBe('left');
76
84
  expect(figure).toHaveText('Figure 1Figure 2');
85
+
86
+ expect(wrapper.find('.lumx-generic-block__content')).toHaveLength(0);
87
+ expect(wrapper.find('.lumx-generic-block__actions')).toHaveLength(0);
77
88
  });
78
89
 
79
90
  it('should combine content props', () => {
@@ -92,6 +103,9 @@ describe(`<${GenericBlock.displayName}>`, () => {
92
103
  expect(content.prop('fillSpace')).toBe(true);
93
104
  expect(content.prop('vAlign')).toBe('left');
94
105
  expect(content).toHaveText('Content 2Content 1');
106
+
107
+ expect(wrapper.find('.lumx-generic-block__figure')).toHaveLength(0);
108
+ expect(wrapper.find('.lumx-generic-block__actions')).toHaveLength(0);
95
109
  });
96
110
 
97
111
  it('should combine actions props', () => {
@@ -109,6 +123,9 @@ describe(`<${GenericBlock.displayName}>`, () => {
109
123
  expect(actions.prop('fillSpace')).toBe(true);
110
124
  expect(actions.prop('vAlign')).toBe('left');
111
125
  expect(actions).toHaveText('Actions 1Actions 2');
126
+
127
+ expect(wrapper.find('.lumx-generic-block__figure')).toHaveLength(0);
128
+ expect(wrapper.find('.lumx-generic-block__content')).toHaveLength(0);
112
129
  });
113
130
 
114
131
  it('should forward refs', () => {
@@ -1,7 +1,9 @@
1
1
  import React, { Children, forwardRef, ReactElement, ReactNode } from 'react';
2
2
  import classNames from 'classnames';
3
+ import isEmpty from 'lodash/isEmpty';
4
+ import noop from 'lodash/noop';
3
5
  import { Comp, getRootClassName, isComponentType, partitionMulti } from '@lumx/react/utils';
4
- import { Orientation, Size, FlexBox, FlexBoxProps, Alignment, HorizontalAlignment } from '@lumx/react';
6
+ import { Orientation, Size, FlexBox, FlexBoxProps } from '@lumx/react';
5
7
 
6
8
  export interface GenericBlockProps extends FlexBoxProps {
7
9
  /**
@@ -58,10 +60,8 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
58
60
  * Component default props.
59
61
  */
60
62
  const DEFAULT_PROPS: Partial<GenericBlockProps> = {
61
- gap: Size.regular,
62
- orientation: Orientation.vertical,
63
- hAlign: Alignment.center,
64
- vAlign: Alignment.center,
63
+ gap: Size.big,
64
+ orientation: Orientation.horizontal,
65
65
  };
66
66
 
67
67
  type BaseGenericBlock = Comp<GenericBlockProps, HTMLDivElement>;
@@ -84,13 +84,13 @@ interface GenericBlock extends BaseGenericBlock {
84
84
  Actions: Comp<FlexBoxProps>;
85
85
  }
86
86
 
87
- const Figure = (() => null) as any;
87
+ const Figure = noop.bind({}) as Comp<FlexBoxProps>;
88
88
  const isFigure = isComponentType(Figure);
89
89
 
90
- const Content = (() => null) as any;
90
+ const Content = noop.bind({}) as Comp<FlexBoxProps>;
91
91
  const isContent = isComponentType(Content);
92
92
 
93
- const Actions = (() => null) as any;
93
+ const Actions = noop.bind({}) as Comp<FlexBoxProps>;
94
94
  const isActions = isComponentType(Actions);
95
95
 
96
96
  /**
@@ -98,9 +98,9 @@ const isActions = isComponentType(Actions);
98
98
  * displayed either horizontally of vertically with the same gap between each section.
99
99
  *
100
100
  * The sections are:
101
- * * (Optional) `Figure` => A visual element to display before the main content.
102
- * * (Required) `Content` => The main content displayed
103
- * * (Optional) `Actions` => One or more actions to set after the element.
101
+ * - `Figure` => A visual element to display before the main content.
102
+ * - `Content` => The main content displayed
103
+ * - `Actions` => One or more actions to set after the element.
104
104
  *
105
105
  * @see https://www.figma.com/file/lzzrQmsfaXRaOyRfoEogPZ/DS%3A-playground?node-id=1%3A4076
106
106
  */
@@ -126,24 +126,15 @@ const BaseGenericBlock: BaseGenericBlock = forwardRef((props, ref) => {
126
126
  );
127
127
  return {
128
128
  figureChild,
129
- figureChildProps: (figureChild as ReactElement)?.props || {},
129
+ figureChildProps: (figureChild as ReactElement)?.props,
130
130
  contentChild,
131
- contentChildProps: (contentChild as ReactElement)?.props || {},
131
+ contentChildProps: (contentChild as ReactElement)?.props,
132
132
  actionsChild,
133
- actionsChildProps: (actionsChild as ReactElement)?.props || {},
134
- otherChildren,
133
+ actionsChildProps: (actionsChild as ReactElement)?.props,
134
+ otherChildren: otherChildren.filter((child) => !isEmpty(child)),
135
135
  };
136
136
  }, [children]);
137
137
 
138
- let actionsVAlign: HorizontalAlignment = Alignment.center;
139
- if (orientation === Orientation.horizontal) {
140
- actionsVAlign = Alignment.right;
141
- }
142
- let contentVAlign: HorizontalAlignment = Alignment.center;
143
- if (orientation === Orientation.horizontal) {
144
- contentVAlign = Alignment.left;
145
- }
146
-
147
138
  return (
148
139
  <FlexBox
149
140
  ref={ref}
@@ -152,26 +143,31 @@ const BaseGenericBlock: BaseGenericBlock = forwardRef((props, ref) => {
152
143
  orientation={orientation}
153
144
  {...forwardedProps}
154
145
  >
155
- <FlexBox
156
- ref={(sections.figureChild as any)?.ref}
157
- {...figureProps}
158
- {...sections.figureChildProps}
159
- className={classNames(
160
- figureProps?.className,
161
- sections.figureChildProps?.className,
162
- `${CLASSNAME}__figure`,
163
- )}
164
- >
165
- {figure}
166
- {sections.figureChildProps?.children}
167
- </FlexBox>
146
+ {(figure || sections.figureChildProps?.children) && (
147
+ <FlexBox
148
+ ref={(sections.figureChild as any)?.ref}
149
+ vAlign={forwardedProps.vAlign}
150
+ hAlign={forwardedProps.hAlign}
151
+ {...figureProps}
152
+ {...sections.figureChildProps}
153
+ className={classNames(
154
+ figureProps?.className,
155
+ sections.figureChildProps?.className,
156
+ `${CLASSNAME}__figure`,
157
+ )}
158
+ >
159
+ {figure}
160
+ {sections.figureChildProps?.children}
161
+ </FlexBox>
162
+ )}
168
163
 
169
- {children && (
164
+ {(sections.contentChildProps?.children || sections.otherChildren.length > 0) && (
170
165
  <FlexBox
171
166
  ref={(sections.contentChild as any)?.ref}
172
167
  orientation={Orientation.vertical}
173
168
  fillSpace
174
- vAlign={contentVAlign}
169
+ vAlign={forwardedProps.vAlign}
170
+ hAlign={forwardedProps.hAlign}
175
171
  {...contentProps}
176
172
  {...sections.contentChildProps}
177
173
  className={classNames(
@@ -185,20 +181,23 @@ const BaseGenericBlock: BaseGenericBlock = forwardRef((props, ref) => {
185
181
  </FlexBox>
186
182
  )}
187
183
 
188
- <FlexBox
189
- ref={(sections.actionsChild as any)?.ref}
190
- vAlign={actionsVAlign}
191
- {...actionsProps}
192
- {...sections.actionsChildProps}
193
- className={classNames(
194
- actionsProps?.className,
195
- sections.actionsChildProps?.className,
196
- `${CLASSNAME}__actions`,
197
- )}
198
- >
199
- {actions}
200
- {sections.actionsChildProps?.children}
201
- </FlexBox>
184
+ {(actions || sections.actionsChildProps?.children) && (
185
+ <FlexBox
186
+ ref={(sections.actionsChild as any)?.ref}
187
+ vAlign={forwardedProps.vAlign}
188
+ hAlign={forwardedProps.hAlign}
189
+ {...actionsProps}
190
+ {...sections.actionsChildProps}
191
+ className={classNames(
192
+ actionsProps?.className,
193
+ sections.actionsChildProps?.className,
194
+ `${CLASSNAME}__actions`,
195
+ )}
196
+ >
197
+ {actions}
198
+ {sections.actionsChildProps?.children}
199
+ </FlexBox>
200
+ )}
202
201
  </FlexBox>
203
202
  );
204
203
  });
@@ -119,14 +119,14 @@ export type TypographyTitleCustom = ValueOf<typeof TypographyTitleCustom>;
119
119
  /**
120
120
  * List of typographies that can be customized (via CSS variables).
121
121
  */
122
- const TypographyCustom = {
122
+ export const TypographyCustom = {
123
123
  ...TypographyTitleCustom,
124
- intro: 'intro',
125
- 'body-large': 'body-large',
126
- body: 'body',
127
- quote: 'quote',
128
- 'publish-info': 'publish-info',
129
- button: 'button',
124
+ intro: 'custom-intro',
125
+ 'body-large': 'custom-body-large',
126
+ body: 'custom-body',
127
+ quote: 'custom-quote',
128
+ 'publish-info': 'custom-publish-info',
129
+ button: 'custom-button',
130
130
  } as const;
131
131
  export type TypographyCustom = ValueOf<typeof TypographyCustom>;
132
132
 
@@ -1,6 +1,14 @@
1
1
  /* eslint-disable jsx-a11y/anchor-is-valid */
2
2
  import { mdiChevronDown, mdiLink } from '@lumx/icons';
3
- import { ColorPalette, ColorVariant, Link, Typography, TypographyInterface, TypographyTitleCustom } from '@lumx/react';
3
+ import {
4
+ ColorPalette,
5
+ ColorVariant,
6
+ Link,
7
+ Typography,
8
+ TypographyCustom,
9
+ TypographyInterface,
10
+ TypographyTitleCustom,
11
+ } from '@lumx/react';
4
12
  import { boolean, select, text } from '@storybook/addon-knobs';
5
13
  import React, { Fragment } from 'react';
6
14
 
@@ -13,7 +21,7 @@ const linkTypographies = { ...TypographyInterface, ...TypographyTitleCustom };
13
21
  export const SimpleLink = () => (
14
22
  <>
15
23
  <Link
16
- href={text('href', 'https://google.com', 'Link 1')}
24
+ href={text('href', 'https://example.com', 'Link 1')}
17
25
  target={boolean('target: _blank', false, 'Link 1') ? '_blank' : ''}
18
26
  color={select('Color', ColorPalette, ColorPalette.blue, 'Link 1')}
19
27
  colorVariant={select('Color Variant', ColorVariant, ColorVariant.N, 'Link 1')}
@@ -51,14 +59,16 @@ export const WithoutHref = () => (
51
59
  </div>
52
60
  );
53
61
 
54
- const CustomLink: React.FC = ({ children, ...props }) =>
55
- React.createElement('a', { ...props, style: { color: 'red' } }, children);
62
+ export const WithCustomLink = () => {
63
+ const CustomLink: React.FC = ({ children, ...props }) =>
64
+ React.createElement('a', { ...props, style: { color: 'red' } }, children);
56
65
 
57
- export const WithCustomLink = () => (
58
- <Link linkAs={CustomLink} href="https://google.com">
59
- Custom link
60
- </Link>
61
- );
66
+ return (
67
+ <Link linkAs={CustomLink} href="https://example.com">
68
+ Custom link
69
+ </Link>
70
+ );
71
+ };
62
72
 
63
73
  export const DisabledLink = () => (
64
74
  // eslint-disable-next-line jsx-a11y/anchor-is-valid
@@ -67,36 +77,6 @@ export const DisabledLink = () => (
67
77
  </Link>
68
78
  );
69
79
 
70
- export const WithIcon = () => (
71
- <>
72
- {Object.values(linkTypographies).map((typography) => (
73
- <Fragment key={typography}>
74
- {typography}
75
- <p>
76
- <Link rightIcon={mdiLink} href="https://www.google.com" typography={typography as any}>
77
- With right icon
78
- </Link>
79
- </p>
80
- <p>
81
- <Link leftIcon={mdiChevronDown} href="https://www.google.com" typography={typography as any}>
82
- With left icon
83
- </Link>
84
- </p>
85
- <p>
86
- <Link
87
- leftIcon={mdiChevronDown}
88
- rightIcon={mdiLink}
89
- href="https://www.google.com"
90
- typography={typography as any}
91
- >
92
- With right and left icon
93
- </Link>
94
- </p>
95
- </Fragment>
96
- ))}
97
- </>
98
- );
99
-
100
80
  export const WithCustomizableTypography = () => (
101
81
  <>
102
82
  <style>{`
@@ -104,8 +84,58 @@ export const WithCustomizableTypography = () => (
104
84
  --lumx-typography-custom-title1-font-size: 5px;
105
85
  }
106
86
  `}</style>
107
- <Link typography={Typography.custom.title1} href="https://google.com">
87
+ <Link typography={Typography.custom.title1} href="https://example.com">
108
88
  Link with customizable `body` typography
109
89
  </Link>
110
90
  </>
111
91
  );
92
+
93
+ export const AllTypography = () => {
94
+ const typographies = [undefined, ...Object.values(TypographyInterface), ...Object.values(TypographyCustom)];
95
+ return (
96
+ <table>
97
+ {typographies.map((typography) => (
98
+ <tr key={typography}>
99
+ <td>{typography}</td>
100
+ <td>
101
+ <Link
102
+ leftIcon={mdiChevronDown}
103
+ rightIcon={mdiLink}
104
+ typography={typography}
105
+ href="https://example.com"
106
+ >
107
+ Link text
108
+ </Link>
109
+ </td>
110
+ </tr>
111
+ ))}
112
+ </table>
113
+ );
114
+ };
115
+
116
+ export const AllColor = () => {
117
+ const colorVariants = [undefined, ...Object.values(ColorVariant)];
118
+ const colors = [undefined, ...Object.values(ColorPalette)];
119
+ return (
120
+ <table style={{ borderCollapse: 'separate', borderSpacing: 5 }}>
121
+ <tr>
122
+ <td />
123
+ {colorVariants.map((colorVariant) => (
124
+ <td key={colorVariant}>{colorVariant}</td>
125
+ ))}
126
+ </tr>
127
+ {colors.map((color) => (
128
+ <tr key={color}>
129
+ <td>{color}</td>
130
+ {colorVariants.map((colorVariant) => (
131
+ <td key={colorVariant}>
132
+ <Link href="https://example.com" color={color} colorVariant={colorVariant}>
133
+ Some text
134
+ </Link>
135
+ </td>
136
+ ))}
137
+ </tr>
138
+ ))}
139
+ </table>
140
+ );
141
+ };
@@ -4,7 +4,7 @@ import isEmpty from 'lodash/isEmpty';
4
4
 
5
5
  import classNames from 'classnames';
6
6
 
7
- import { Color, ColorVariant, Icon, Size, Typography, TypographyInterface, TypographyTitleCustom } from '@lumx/react';
7
+ import { Color, ColorVariant, Icon, Size, Typography } from '@lumx/react';
8
8
  import { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';
9
9
  import { renderLink } from '@lumx/react/utils/renderLink';
10
10
 
@@ -31,7 +31,7 @@ export interface LinkProps extends GenericProps {
31
31
  /** Link target. */
32
32
  target?: HTMLAnchorProps['target'];
33
33
  /** Typography variant. */
34
- typography?: TypographyInterface | TypographyTitleCustom;
34
+ typography?: Typography;
35
35
  }
36
36
 
37
37
  /**
@@ -0,0 +1,92 @@
1
+ import { shiftPosition } from './useFocusPointStyle';
2
+
3
+ describe('shiftPosition', () => {
4
+ it('should always return 0% if the imageSize fits the containerSize', () => {
5
+ expect(
6
+ shiftPosition({
7
+ scale: 1.5,
8
+ focusPoint: 0,
9
+ imageSize: 1000,
10
+ containerSize: 1000,
11
+ }),
12
+ ).toEqual(0);
13
+ expect(
14
+ shiftPosition({
15
+ scale: 1,
16
+ focusPoint: 0.27,
17
+ imageSize: 1000,
18
+ containerSize: 1000,
19
+ }),
20
+ ).toEqual(0);
21
+ expect(
22
+ shiftPosition({
23
+ scale: 3,
24
+ focusPoint: 0.5,
25
+ imageSize: 1000,
26
+ containerSize: 1000,
27
+ }),
28
+ ).toEqual(0);
29
+ expect(
30
+ shiftPosition({
31
+ scale: 2.4,
32
+ focusPoint: 1,
33
+ imageSize: 1000,
34
+ containerSize: 1000,
35
+ }),
36
+ ).toEqual(0);
37
+ });
38
+
39
+ describe('with bigger side than container ', () => {
40
+ // This use case will come, for example, if you have an image in width 100%
41
+ // but the image after being resized to keep the ratio is higher than the container.
42
+ // Then we are calculating the y shift.
43
+
44
+ const image = { width: 1000, height: 1200 };
45
+ const container = { width: 1000, height: 300 };
46
+ // scale is always the minimum scale ratio. Here imagewidth/containerwidth.
47
+ const scale = image.width / container.width; // 1
48
+ it('should return 0% if focusPoint equals 0', () => {
49
+ expect(
50
+ shiftPosition({
51
+ scale,
52
+ focusPoint: 0,
53
+ imageSize: image.height,
54
+ containerSize: container.height,
55
+ }),
56
+ ).toEqual(0);
57
+ });
58
+
59
+ it('should return 100% if focusPoint equals 1', () => {
60
+ expect(
61
+ shiftPosition({
62
+ scale,
63
+ focusPoint: 1,
64
+ imageSize: image.height,
65
+ containerSize: container.height,
66
+ }),
67
+ ).toEqual(100);
68
+ });
69
+
70
+ it('should return 50% if focusPoint equals 0.5', () => {
71
+ expect(
72
+ shiftPosition({
73
+ scale,
74
+ focusPoint: 0.5,
75
+ imageSize: image.height,
76
+ containerSize: container.height,
77
+ }),
78
+ ).toEqual(50);
79
+ });
80
+
81
+ it('should return 16% if focusPoint equals 0.25', () => {
82
+ expect(
83
+ shiftPosition({
84
+ scale,
85
+ focusPoint: 0.25,
86
+ imageSize: image.height,
87
+ containerSize: container.height,
88
+ }),
89
+ ).toEqual(16);
90
+ });
91
+ });
92
+ });