@lumx/react 2.2.22 → 2.2.24
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/esm/_internal/FlexBox.js.map +1 -1
- package/esm/_internal/GenericBlock.js +32 -52
- package/esm/_internal/GenericBlock.js.map +1 -1
- package/esm/_internal/Link2.js.map +1 -1
- package/esm/_internal/Thumbnail2.js +26 -12
- package/esm/_internal/Thumbnail2.js.map +1 -1
- package/esm/_internal/components.js +7 -7
- package/esm/_internal/components.js.map +1 -1
- package/esm/index.js +1 -1
- package/package.json +4 -4
- package/src/components/flex-box/FlexBox.stories.tsx +1 -1
- package/src/components/flex-box/FlexBox.tsx +1 -1
- package/src/components/generic-block/GenericBlock.stories.jsx +106 -0
- package/src/components/generic-block/GenericBlock.test.tsx +36 -19
- package/src/components/generic-block/GenericBlock.tsx +52 -53
- package/src/components/index.ts +7 -7
- package/src/components/link/Link.stories.tsx +70 -40
- package/src/components/link/Link.tsx +2 -2
- package/src/components/thumbnail/useFocusPointStyle.test.ts +92 -0
- package/src/components/thumbnail/useFocusPointStyle.tsx +26 -4
- package/types.d.ts +18 -15
- package/src/components/generic-block/GenericBlock.stories.tsx +0 -90
|
@@ -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 '
|
|
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(
|
|
23
|
+
const wrapper = shallow(
|
|
24
|
+
<GenericBlock figure="figure" actions="actions">
|
|
25
|
+
Content
|
|
26
|
+
</GenericBlock>,
|
|
27
|
+
);
|
|
24
28
|
|
|
25
|
-
expect(wrapper.prop('gap')).toBe('
|
|
26
|
-
expect(wrapper.prop('
|
|
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).
|
|
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
|
|
41
|
+
expect(actions).toHaveLength(1);
|
|
40
42
|
});
|
|
41
43
|
|
|
42
|
-
it('should
|
|
43
|
-
const wrapper = shallow(
|
|
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('
|
|
46
|
-
expect(wrapper.prop('hAlign')).toBe('
|
|
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).
|
|
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
|
|
60
|
+
expect(content).toHaveLength(1);
|
|
55
61
|
expect(content.prop('vAlign')).toBe('left');
|
|
56
|
-
expect(content.prop('
|
|
62
|
+
expect(content.prop('hAlign')).toBe('bottom');
|
|
57
63
|
|
|
58
64
|
const actions = wrapper.find('.lumx-generic-block__actions');
|
|
59
|
-
expect(actions
|
|
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
|
|
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.
|
|
62
|
-
orientation: Orientation.
|
|
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 = (
|
|
87
|
+
const Figure = noop.bind({}) as Comp<FlexBoxProps>;
|
|
88
88
|
const isFigure = isComponentType(Figure);
|
|
89
89
|
|
|
90
|
-
const Content = (
|
|
90
|
+
const Content = noop.bind({}) as Comp<FlexBoxProps>;
|
|
91
91
|
const isContent = isComponentType(Content);
|
|
92
92
|
|
|
93
|
-
const Actions = (
|
|
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
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
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
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
figureProps
|
|
161
|
-
sections.figureChildProps
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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={
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
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
|
});
|
package/src/components/index.ts
CHANGED
|
@@ -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 {
|
|
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://
|
|
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
|
|
55
|
-
React.
|
|
62
|
+
export const WithCustomLink = () => {
|
|
63
|
+
const CustomLink: React.FC = ({ children, ...props }) =>
|
|
64
|
+
React.createElement('a', { ...props, style: { color: 'red' } }, children);
|
|
56
65
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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://
|
|
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
|
|
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?:
|
|
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: 1200,
|
|
10
|
+
containerSize: 800,
|
|
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: 1200,
|
|
26
|
+
containerSize: 400,
|
|
27
|
+
}),
|
|
28
|
+
).toEqual(0);
|
|
29
|
+
expect(
|
|
30
|
+
shiftPosition({
|
|
31
|
+
scale: 2.4,
|
|
32
|
+
focusPoint: 1,
|
|
33
|
+
imageSize: 1200,
|
|
34
|
+
containerSize: 500,
|
|
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
|
+
});
|