@leafygreen-ui/icon 11.9.0 → 11.10.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/CHANGELOG.md +7 -0
- package/dist/createIconComponent.d.ts +1 -0
- package/dist/createIconComponent.d.ts.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/isComponentGlyph.d.ts +7 -2
- package/dist/isComponentGlyph.d.ts.map +1 -1
- package/dist/types/LGGlyph.d.ts +5 -2
- package/dist/types/LGGlyph.d.ts.map +1 -1
- package/package.json +11 -3
- package/scripts/build.ts +1 -1
- package/{src → scripts}/template.ts +0 -0
- package/src/Icon.spec.tsx +76 -17
- package/src/Icon.story.tsx +21 -21
- package/src/createGlyphComponent.tsx +3 -3
- package/src/createIconComponent.tsx +3 -1
- package/src/isComponentGlyph.ts +27 -6
- package/src/types/LGGlyph.ts +4 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/template.d.ts +0 -19
- package/dist/template.d.ts.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leafygreen-ui/icon",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.10.0",
|
|
4
4
|
"description": "LeafyGreen UI Kit Icons",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -26,5 +26,13 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@leafygreen-ui/lib": "^9.2.0"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "dd71a2d404218ccec2e657df9c0263dc1c15b9e0"
|
|
30
|
-
|
|
29
|
+
"gitHead": "dd71a2d404218ccec2e657df9c0263dc1c15b9e0",
|
|
30
|
+
"homepage": "https://github.com/mongodb/leafygreen-ui/tree/main/packages/icon",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/mongodb/leafygreen-ui"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://jira.mongodb.org/projects/PD/summary"
|
|
37
|
+
}
|
|
38
|
+
}
|
package/scripts/build.ts
CHANGED
|
File without changes
|
package/src/Icon.spec.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import { createIconComponent, glyphs } from '.';
|
|
|
11
11
|
import createGlyphComponent from './createGlyphComponent';
|
|
12
12
|
import EditIcon from '@leafygreen-ui/icon/dist/Edit';
|
|
13
13
|
import { Size } from './glyphCommon';
|
|
14
|
+
import { isComponentGlyph } from './isComponentGlyph';
|
|
14
15
|
|
|
15
16
|
function getBaseName(filePath: string): string {
|
|
16
17
|
return path.basename(filePath, path.extname(filePath));
|
|
@@ -32,6 +33,50 @@ fs.readdirSync(generatedFilesDirectory).forEach(filePath => {
|
|
|
32
33
|
baseNameToGeneratedFilePath[getBaseName(filePath)] = filePath;
|
|
33
34
|
});
|
|
34
35
|
|
|
36
|
+
const MyTestSVGRGlyph: SVGR.Component = props => (
|
|
37
|
+
<svg data-testid="my-glyph" {...props}></svg>
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const customTestGlyphs = {
|
|
41
|
+
MyTestSVGRGlyph: createGlyphComponent('MyTestSVGRGlyph', MyTestSVGRGlyph),
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
describe('packages/Icon/isComponentGlyph', () => {
|
|
45
|
+
test('returns `true` for a rendered component', () => {
|
|
46
|
+
const TestNode: React.ComponentType<any> & { isGlyph?: boolean } = () => (
|
|
47
|
+
<div />
|
|
48
|
+
);
|
|
49
|
+
TestNode.isGlyph = true;
|
|
50
|
+
const renderedTestNode = <TestNode />;
|
|
51
|
+
expect(isComponentGlyph(renderedTestNode)).toBeTruthy();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('returns `true` for a component function', () => {
|
|
55
|
+
const TestNode: React.ComponentType<any> & { isGlyph?: boolean } = () => (
|
|
56
|
+
<div />
|
|
57
|
+
);
|
|
58
|
+
TestNode.isGlyph = true;
|
|
59
|
+
expect(isComponentGlyph(TestNode)).toBeTruthy();
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('returns `false` if isGlyph is false', () => {
|
|
63
|
+
const TestNode: React.ComponentType<any> & { isGlyph?: boolean } = () => (
|
|
64
|
+
<div />
|
|
65
|
+
);
|
|
66
|
+
TestNode.isGlyph = false;
|
|
67
|
+
const renderedTestNode = <TestNode />;
|
|
68
|
+
expect(isComponentGlyph(TestNode)).toBeFalsy();
|
|
69
|
+
expect(isComponentGlyph(renderedTestNode)).toBeFalsy();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('returns `false` if isGlyph is not set', () => {
|
|
73
|
+
const TestNode: React.ComponentType<any> = () => <div />;
|
|
74
|
+
const renderedTestNode = <TestNode />;
|
|
75
|
+
expect(isComponentGlyph(TestNode)).toBeFalsy();
|
|
76
|
+
expect(isComponentGlyph(renderedTestNode)).toBeFalsy();
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
|
|
35
80
|
describe('packages/Icon/glyphs/', () => {
|
|
36
81
|
describe('a11y', () => {
|
|
37
82
|
test('does not have basic accessibility issues', async () => {
|
|
@@ -86,19 +131,28 @@ describe('packages/Icon/glyphs/', () => {
|
|
|
86
131
|
});
|
|
87
132
|
});
|
|
88
133
|
|
|
89
|
-
const MyGlyph: SVGR.Component = props => (
|
|
90
|
-
<svg data-testid="my-glyph" {...props}></svg>
|
|
91
|
-
);
|
|
92
|
-
|
|
93
134
|
describe('packages/Icon/createGlyphComponent', () => {
|
|
94
|
-
const GlyphComponent = createGlyphComponent(
|
|
135
|
+
const GlyphComponent = createGlyphComponent(
|
|
136
|
+
'MyTestSVGRGlyph',
|
|
137
|
+
MyTestSVGRGlyph,
|
|
138
|
+
);
|
|
95
139
|
|
|
96
|
-
test('returns a
|
|
140
|
+
test('returns a LGGlyph component', () => {
|
|
97
141
|
expect(typeof GlyphComponent).toBe('function');
|
|
142
|
+
expect(isComponentGlyph(GlyphComponent)).toBeTruthy();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
test('returned component has correct display name', () => {
|
|
146
|
+
expect(GlyphComponent.displayName).toBe('MyTestSVGRGlyph');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test('returned component has the property `isGlyph`', () => {
|
|
150
|
+
expect(GlyphComponent).toHaveProperty('isGlyph');
|
|
151
|
+
expect(GlyphComponent.isGlyph).toBeTruthy();
|
|
98
152
|
});
|
|
99
153
|
|
|
100
|
-
test('returned function
|
|
101
|
-
expect(GlyphComponent
|
|
154
|
+
test('returned function passes `isComponentGlyph`', () => {
|
|
155
|
+
expect(isComponentGlyph(GlyphComponent)).toBeTruthy();
|
|
102
156
|
});
|
|
103
157
|
|
|
104
158
|
test('returned function renders the glyph specified', () => {
|
|
@@ -134,12 +188,8 @@ describe('packages/Icon/createGlyphComponent', () => {
|
|
|
134
188
|
});
|
|
135
189
|
});
|
|
136
190
|
|
|
137
|
-
const customGlyphs = {
|
|
138
|
-
MyGlyph: createGlyphComponent('MyGlyph', MyGlyph),
|
|
139
|
-
};
|
|
140
|
-
|
|
141
191
|
describe('packages/Icon/createIconComponent', () => {
|
|
142
|
-
const IconComponent = createIconComponent(
|
|
192
|
+
const IconComponent = createIconComponent(customTestGlyphs);
|
|
143
193
|
|
|
144
194
|
test('returns a function', () => {
|
|
145
195
|
expect(typeof IconComponent).toBe('function');
|
|
@@ -149,8 +199,17 @@ describe('packages/Icon/createIconComponent', () => {
|
|
|
149
199
|
expect(IconComponent.displayName).toBe('Icon');
|
|
150
200
|
});
|
|
151
201
|
|
|
202
|
+
test('returned function has the property: `isGlyph`', () => {
|
|
203
|
+
expect(IconComponent).toHaveProperty('isGlyph');
|
|
204
|
+
expect(IconComponent.isGlyph).toBeTruthy();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test('returned function passes `isComponentGlyph`', () => {
|
|
208
|
+
expect(isComponentGlyph(IconComponent)).toBeTruthy();
|
|
209
|
+
});
|
|
210
|
+
|
|
152
211
|
test('returned funciton renders the glyph specified', () => {
|
|
153
|
-
const { getByTestId } = render(<IconComponent glyph="
|
|
212
|
+
const { getByTestId } = render(<IconComponent glyph="MyTestSVGRGlyph" />);
|
|
154
213
|
const glyph = getByTestId('my-glyph');
|
|
155
214
|
|
|
156
215
|
if (!typeIs.element(glyph)) {
|
|
@@ -162,7 +221,7 @@ describe('packages/Icon/createIconComponent', () => {
|
|
|
162
221
|
describe('returned funcion passes through props', () => {
|
|
163
222
|
test('`size` prop as number', () => {
|
|
164
223
|
const { getByTestId } = render(
|
|
165
|
-
<IconComponent glyph="
|
|
224
|
+
<IconComponent glyph="MyTestSVGRGlyph" size={20} />,
|
|
166
225
|
);
|
|
167
226
|
const glyph = getByTestId('my-glyph');
|
|
168
227
|
expect(glyph).toHaveAttribute('height', '20');
|
|
@@ -171,7 +230,7 @@ describe('packages/Icon/createIconComponent', () => {
|
|
|
171
230
|
|
|
172
231
|
test('`size` prop as Size', () => {
|
|
173
232
|
const { getByTestId } = render(
|
|
174
|
-
<IconComponent glyph="
|
|
233
|
+
<IconComponent glyph="MyTestSVGRGlyph" size={Size.Large} />,
|
|
175
234
|
);
|
|
176
235
|
const glyph = getByTestId('my-glyph');
|
|
177
236
|
expect(glyph).toHaveAttribute('height', '20');
|
|
@@ -180,7 +239,7 @@ describe('packages/Icon/createIconComponent', () => {
|
|
|
180
239
|
|
|
181
240
|
test('`role`', () => {
|
|
182
241
|
const { getByTestId } = render(
|
|
183
|
-
<IconComponent glyph="
|
|
242
|
+
<IconComponent glyph="MyTestSVGRGlyph" role="presentation" />,
|
|
184
243
|
);
|
|
185
244
|
const glyph = getByTestId('my-glyph');
|
|
186
245
|
expect(glyph).toHaveAttribute('role', 'presentation');
|
package/src/Icon.story.tsx
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
+
// TODO: Generate Icon props with controls
|
|
1
2
|
import React from 'react';
|
|
2
|
-
import Icon, { glyphs
|
|
3
|
+
import Icon, { glyphs } from '.';
|
|
3
4
|
import { css } from '@leafygreen-ui/emotion';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
5
|
+
import { ComponentStory, Meta } from '@storybook/react';
|
|
6
|
+
import { palette } from '@leafygreen-ui/palette';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'Packages/Icons',
|
|
10
|
+
component: Icon,
|
|
11
|
+
} as Meta<typeof Icon>;
|
|
7
12
|
|
|
8
13
|
const containerStyle = css`
|
|
9
14
|
width: 150px;
|
|
10
15
|
height: 70px;
|
|
11
16
|
flex-shrink: 0;
|
|
12
17
|
text-align: center;
|
|
13
|
-
border: 1px solid
|
|
18
|
+
border: 1px solid ${palette.gray.light1};
|
|
14
19
|
border-radius: 5px;
|
|
15
20
|
display: flex;
|
|
16
21
|
align-items: center;
|
|
@@ -21,22 +26,17 @@ const containerStyle = css`
|
|
|
21
26
|
|
|
22
27
|
const textStyle = css`
|
|
23
28
|
font-size: 12px;
|
|
24
|
-
color: ${
|
|
29
|
+
color: ${palette.gray.base};
|
|
25
30
|
margin-top: 0.5rem;
|
|
26
31
|
`;
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
</div>
|
|
39
|
-
))}
|
|
40
|
-
</>
|
|
41
|
-
);
|
|
42
|
-
});
|
|
33
|
+
export const AllIcons: ComponentStory<typeof Icon> = args => (
|
|
34
|
+
<>
|
|
35
|
+
{Object.keys(glyphs).map(glyph => (
|
|
36
|
+
<div key={glyph} className={containerStyle}>
|
|
37
|
+
<Icon {...args} glyph={glyph} />
|
|
38
|
+
<div className={textStyle}>{glyph}</div>
|
|
39
|
+
</div>
|
|
40
|
+
))}
|
|
41
|
+
</>
|
|
42
|
+
);
|
|
@@ -15,7 +15,7 @@ export default function createGlyphComponent(
|
|
|
15
15
|
glyphName: string,
|
|
16
16
|
Glyph: SVGR.Component,
|
|
17
17
|
): LGGlyph.Component {
|
|
18
|
-
|
|
18
|
+
const GlyphComponent: LGGlyph.Component = ({
|
|
19
19
|
className,
|
|
20
20
|
size = Size.Default,
|
|
21
21
|
fill,
|
|
@@ -24,7 +24,7 @@ export default function createGlyphComponent(
|
|
|
24
24
|
'aria-label': ariaLabel,
|
|
25
25
|
role = 'img',
|
|
26
26
|
...rest
|
|
27
|
-
}: LGGlyph.ComponentProps) {
|
|
27
|
+
}: LGGlyph.ComponentProps) => {
|
|
28
28
|
const fillStyle = css`
|
|
29
29
|
color: ${fill};
|
|
30
30
|
`;
|
|
@@ -56,7 +56,7 @@ export default function createGlyphComponent(
|
|
|
56
56
|
{...rest}
|
|
57
57
|
/>
|
|
58
58
|
);
|
|
59
|
-
}
|
|
59
|
+
};
|
|
60
60
|
|
|
61
61
|
GlyphComponent.displayName = glyphName;
|
|
62
62
|
|
|
@@ -21,12 +21,14 @@ export default function createIconComponent<
|
|
|
21
21
|
>(glyphs: G) {
|
|
22
22
|
const Icon = ({ glyph, ...rest }: IconProps) => {
|
|
23
23
|
const SVGComponent = glyphs[glyph];
|
|
24
|
-
|
|
24
|
+
SVGComponent.isGlyph = true;
|
|
25
25
|
return <SVGComponent {...rest} />;
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
Icon.displayName = 'Icon';
|
|
29
29
|
|
|
30
|
+
Icon.isGlyph = true;
|
|
31
|
+
|
|
30
32
|
Icon.propTypes = {
|
|
31
33
|
glyph: PropTypes.oneOf(Object.keys(glyphs)).isRequired,
|
|
32
34
|
size: PropTypes.oneOfType([
|
package/src/isComponentGlyph.ts
CHANGED
|
@@ -1,13 +1,34 @@
|
|
|
1
|
+
import { ComponentType, isValidElement, ReactNode } from 'react';
|
|
1
2
|
import { LGGlyph } from './types';
|
|
2
3
|
|
|
4
|
+
type ExtendedComponentType = ComponentType<any> & {
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
};
|
|
3
7
|
/** Helper type to check if element is a LeafyGreen UI Glyph */
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
function isComponentGlyph(node: ReactNode): node is LGGlyph.Element;
|
|
9
|
+
function isComponentGlyph(
|
|
10
|
+
component: ExtendedComponentType,
|
|
11
|
+
): component is LGGlyph.Component;
|
|
12
|
+
function isComponentGlyph(
|
|
13
|
+
child: ReactNode | ExtendedComponentType,
|
|
14
|
+
): child is LGGlyph.Element | LGGlyph.Component {
|
|
15
|
+
// If we're received a rendered component (i.e. ReactNode)
|
|
16
|
+
if (isValidElement(child)) {
|
|
17
|
+
return (
|
|
18
|
+
child != null &&
|
|
19
|
+
typeof child === 'object' &&
|
|
20
|
+
'type' in child &&
|
|
21
|
+
(child.type as any).isGlyph === true
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// If we've recieved a component function
|
|
7
26
|
return (
|
|
8
27
|
child != null &&
|
|
9
|
-
typeof child === '
|
|
10
|
-
'
|
|
11
|
-
|
|
28
|
+
typeof child === 'function' &&
|
|
29
|
+
'isGlyph' in child &&
|
|
30
|
+
child.isGlyph === true
|
|
12
31
|
);
|
|
13
32
|
}
|
|
33
|
+
|
|
34
|
+
export { isComponentGlyph };
|
package/src/types/LGGlyph.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { ComponentType } from 'react';
|
|
1
|
+
import { ComponentType, ReactComponentElement } from 'react';
|
|
2
2
|
import * as SVGR from './SVGR';
|
|
3
3
|
|
|
4
4
|
export interface ComponentProps extends SVGR.ComponentProps {
|
|
5
5
|
size?: number | 'small' | 'default' | 'large' | 'xlarge';
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export type Component = ComponentType<ComponentProps
|
|
8
|
+
export type Component = ComponentType<ComponentProps> & { isGlyph?: boolean };
|
|
9
|
+
|
|
10
|
+
export type Element = ReactComponentElement<Component, ComponentProps>;
|