2
0
mirror of https://github.com/iconify/iconify.git synced 2024-11-09 23:00:56 +00:00

Clean up code for React with API for new React component compatibility

This commit is contained in:
Vjacheslav Trushkin 2021-01-27 11:45:03 +02:00
parent 6505545902
commit f926986eb6
6 changed files with 67 additions and 22 deletions

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Icon, InlineIcon, enableCache } from '@iconify/react-with-api'; import { Icon, InlineIcon, disableCache } from '@iconify/react-with-api';
import accountIcon from '@iconify-icons/mdi-light/account'; import accountIcon from '@iconify-icons/mdi-light/account';
import homeIcon from '@iconify-icons/mdi-light/home'; import homeIcon from '@iconify-icons/mdi-light/home';
@ -9,8 +9,7 @@ import { InlineDemo } from './components/Inline';
import './App.css'; import './App.css';
// Disable cache for test // Disable cache for test
enableCache('local', false); disableCache('all');
enableCache('session', false);
class CheckboxIcon extends React.Component { class CheckboxIcon extends React.Component {
constructor(props) { constructor(props) {
@ -125,6 +124,26 @@ function App() {
}} }}
/> />
</p> </p>
<p>
Testing reference by adding border to icon (unfortunately
should not work yet):{' '}
<Icon
icon="mdi-light:alert"
ref={(element) => {
if (element) {
element.style.border = '1px solid red';
}
}}
/>
<Icon
icon={accountIcon}
ref={(element) => {
if (element) {
element.style.border = '1px solid red';
}
}}
/>
</p>
</section> </section>
<InlineDemo /> <InlineDemo />

View File

@ -1,12 +1,12 @@
{ {
"name": "@iconify/react-with-api", "name": "@iconify/react-with-api",
"version": "1.0.0-rc.5", "version": "1.0.0-rc.6",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@iconify/react-with-api", "name": "@iconify/react-with-api",
"version": "1.0.0-rc.5", "version": "1.0.0-rc.6",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@babel/core": "^7.12.7", "@babel/core": "^7.12.7",

View File

@ -2,7 +2,7 @@
"name": "@iconify/react-with-api", "name": "@iconify/react-with-api",
"description": "Iconify icon component for React.", "description": "Iconify icon component for React.",
"author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)", "author": "Vjacheslav Trushkin <cyberalien@gmail.com> (https://iconify.design)",
"version": "1.0.0-rc.5", "version": "1.0.0-rc.6",
"license": "MIT", "license": "MIT",
"bugs": "https://github.com/iconify/iconify/issues", "bugs": "https://github.com/iconify/iconify/issues",
"homepage": "https://iconify.design/", "homepage": "https://iconify.design/",

View File

@ -33,7 +33,13 @@ const config = [
}, },
], ],
external: ['react', 'axios'], external: ['react', 'axios'],
plugins: [resolve(), commonjs(), buble()], plugins: [
resolve(),
commonjs({
ignore: ['cross-fetch'],
}),
buble(),
],
}, },
// Dev build // Dev build
{ {
@ -45,7 +51,13 @@ const config = [
}, },
], ],
external: ['react', 'axios'], external: ['react', 'axios'],
plugins: [resolve(), commonjs(), buble()], plugins: [
resolve(),
commonjs({
ignore: ['cross-fetch'],
}),
buble(),
],
}, },
// Production // Production
{ {
@ -57,7 +69,14 @@ const config = [
}, },
], ],
external: ['react', 'axios'], external: ['react', 'axios'],
plugins: [resolve(), commonjs(), buble(), terser()], plugins: [
resolve(),
commonjs({
ignore: ['cross-fetch'],
}),
buble(),
terser(),
],
}, },
]; ];

View File

@ -1,4 +1,4 @@
import { createElement, Component } from 'react'; import React from 'react';
import { IconifyJSON } from '@iconify/types'; import { IconifyJSON } from '@iconify/types';
// Parent component // Parent component
@ -184,7 +184,7 @@ interface StatefulState {
/** /**
* Dynamic component * Dynamic component
*/ */
class DynamicComponent extends Component<StatefulProps, StatefulState> { class DynamicComponent extends React.Component<StatefulProps, StatefulState> {
protected _abort: IconifyIconLoaderAbort | null; protected _abort: IconifyIconLoaderAbort | null;
/** /**
@ -215,17 +215,19 @@ class DynamicComponent extends Component<StatefulProps, StatefulState> {
const state = this.state; const state = this.state;
if (!state.loaded) { if (!state.loaded) {
// Empty // Empty
return null; return React.createElement('span');
} }
// Replace icon in props with object // Replace icon in props with object
const props = this.props;
let newProps: IconProps = {} as IconProps; let newProps: IconProps = {} as IconProps;
Object.assign(newProps, this.props, { Object.assign(newProps, props, {
icon: state.data, icon: state.data,
}); });
delete newProps['func']; delete newProps['func'];
delete newProps.ref;
return this.props.func(newProps); return React.createElement(this.props.func, newProps);
} }
/** /**
@ -267,7 +269,7 @@ const component = (props: IconProps, func: typeof ReactIcon): JSX.Element => {
if (typeof props.icon === 'string') { if (typeof props.icon === 'string') {
const iconName = stringToIcon(props.icon, true); const iconName = stringToIcon(props.icon, true);
if (!iconName) { if (!iconName) {
return null; return React.createElement('span');
} }
iconData = getIconData(iconName); iconData = getIconData(iconName);
@ -276,7 +278,7 @@ const component = (props: IconProps, func: typeof ReactIcon): JSX.Element => {
let staticProps: IconProps = {} as IconProps; let staticProps: IconProps = {} as IconProps;
Object.assign(staticProps, props); Object.assign(staticProps, props);
staticProps.icon = iconData; staticProps.icon = iconData;
return func(staticProps); return React.createElement(func, staticProps);
} }
// Return dynamic component // Return dynamic component
@ -285,9 +287,10 @@ const component = (props: IconProps, func: typeof ReactIcon): JSX.Element => {
icon: iconName, icon: iconName,
func, func,
}); });
return createElement(DynamicComponent, dynamicProps); return React.createElement(DynamicComponent, dynamicProps);
} else { } else {
return func(props); // Passed icon data as object: render @iconify/react component
return React.createElement(func, props);
} }
}; };

View File

@ -60,10 +60,14 @@ export interface IconifyIconProps extends IconifyIconCustomisations {
type IconifyElementProps = HTMLProps<HTMLElement>; type IconifyElementProps = HTMLProps<HTMLElement>;
type IconifySVGProps = SVGProps<SVGElement>; type IconifySVGProps = SVGProps<SVGElement>;
interface ReactRefProp {
ref?: typeof React.createRef;
}
/** /**
* Mix of icon properties and HTMLElement properties * Mix of icon properties and HTMLElement properties
*/ */
export type IconProps = IconifyElementProps & IconifyIconProps; export type IconProps = IconifyElementProps & IconifyIconProps & ReactRefProp;
/** /**
* Default SVG attributes * Default SVG attributes
@ -105,7 +109,7 @@ const component = (
? storage[props.icon] ? storage[props.icon]
: fullIcon(props.icon); : fullIcon(props.icon);
if (!icon) { if (!icon) {
return null; return React.createElement('span');
} }
const customisations = merge( const customisations = merge(
@ -195,7 +199,7 @@ const component = (
* *
* @param props - Component properties * @param props - Component properties
*/ */
export const Icon = React.forwardRef((props: IconProps, ref) => export const Icon = React.forwardRef((props: IconProps, ref?) =>
component(props, defaults, ref) component(props, defaults, ref)
); );
@ -204,7 +208,7 @@ export const Icon = React.forwardRef((props: IconProps, ref) =>
* *
* @param props - Component properties * @param props - Component properties
*/ */
export const InlineIcon = React.forwardRef((props: IconProps, ref) => export const InlineIcon = React.forwardRef((props: IconProps, ref?) =>
component(props, inlineDefaults, ref) component(props, inlineDefaults, ref)
); );