-
-
Notifications
You must be signed in to change notification settings - Fork 303
/
SVGIcon.tsx
135 lines (119 loc) · 3.88 KB
/
SVGIcon.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import React, { FC, forwardRef, HTMLAttributes, ReactNode } from "react";
import cn from "classnames";
import { bem, WithForwardedRef } from "@react-md/utils";
export interface SVGIconProps extends HTMLAttributes<SVGSVGElement> {
/**
* Boolean if the SVG should gain the `focusable` attribute. This is disabled by default
* since IE11 and Edge actually default this to true and keyboard's will tab focus all SVGs.
*/
focusable?: "false" | "true" | boolean;
/**
* The `viewBox` attribute allows you to specify that a given set of graphics stretch to
* fit a particular container element.
*
* The value of the `viewBox` attribute is a list of four numbers min-x, min-y, width and
* height, separated by white space and/or a comma, which specify a rectangle in user
* space which should be mapped to the bounds of the viewport established by the given
* element, taking into account attribute `preserveAspectRatio`.
*
* Negative values for width or height are not permitted and a value of zero disables
* rendering of the element. An optional `viewbox` for the SVG.
*
* For example, if the SVG element is 250 (width) by 200 (height) and you provide
* `viewBox="0 0 25 20"`, the coordinates inside the SVG will go from the top left corner
* (0, 0) to the bottom right (25, 20) and each unit will be worth `10px`.
*/
viewBox?: string;
/**
* An optional `xmlns` string to provide. The `use` prop will not work without this prop
* defined.
*/
xmlns?: string;
/**
* This should be a link to a part of an SVG sprite map. So normally one of the following:
* - `'#some-custom-svg'`
* - `'/images/spritemap.svg#some-custom-svg'`
*
* This prop **should not** be used with the `children` prop as only one will be rendered.
*
* > NOTE: IE **does not support** external SVGs. Please see the demo for more details.
*/
use?: string;
/**
* Boolean if the icon should use the dense spec.
*/
dense?: boolean;
/**
* Any `<svg>` children to render to create your icon. This can not be used with the `use` prop.
*/
children?: ReactNode;
}
type WithRef = WithForwardedRef<SVGSVGElement>;
type DefaultProps = Required<
Pick<
SVGIconProps,
"focusable" | "xmlns" | "viewBox" | "dense" | "aria-hidden"
>
>;
type WithDefaultProps = SVGIconProps & DefaultProps & WithRef;
const block = bem("rmd-icon");
/**
* The `SVGIcon` component is used to render inline SVG icons or SVG icons in a sprite map
* as an icon.
*/
const SVGIcon: FC<SVGIconProps &
WithForwardedRef<SVGSVGElement>> = providedProps => {
const {
className,
use,
children: propChildren,
dense,
forwardedRef,
...props
} = providedProps as WithDefaultProps;
let children = propChildren;
if (!children && use) {
children = <use xlinkHref={use} />;
}
return (
<svg
{...props}
ref={forwardedRef}
className={cn(block({ svg: true, dense }), className)}
>
{children}
</svg>
);
};
const defaultProps: DefaultProps = {
"aria-hidden": true,
focusable: "false",
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 24 24",
dense: false,
};
SVGIcon.defaultProps = defaultProps;
if (process.env.NODE_ENV !== "production") {
SVGIcon.displayName = "SVGIcon";
let PropTypes = null;
try {
PropTypes = require("prop-types");
} catch (e) {}
if (PropTypes) {
SVGIcon.propTypes = {
className: PropTypes.string,
role: PropTypes.string,
"aria-hidden": PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
"aria-labelledby": PropTypes.string,
focusable: PropTypes.oneOf(["true", "false"]),
viewBox: PropTypes.string,
xmlns: PropTypes.string,
use: PropTypes.string,
dense: PropTypes.bool,
children: PropTypes.node,
};
}
}
export default forwardRef<SVGSVGElement, SVGIconProps>((props, ref) => (
<SVGIcon {...props} forwardedRef={ref} />
));