mirror of
https://github.com/iconify/iconify.git
synced 2024-12-12 21:57:50 +00:00
Refactoring React: full component but without API support
This commit is contained in:
parent
ac37225e5e
commit
3f73f4f145
@ -45,18 +45,22 @@ p {
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.test-row > svg {
|
||||
color: #afafaf;
|
||||
.test-row-icons {
|
||||
padding-right: 4px;
|
||||
}
|
||||
.test-row > svg.success {
|
||||
.test-row-icons > svg {
|
||||
color: #afafaf;
|
||||
display: none;
|
||||
}
|
||||
.test-row-icons > svg.visible {
|
||||
display: inline-block;
|
||||
}
|
||||
.test-row-icons > svg.success {
|
||||
color: #327335;
|
||||
}
|
||||
.test-row > svg.fail {
|
||||
.test-row-icons > svg.failed {
|
||||
color: #ba3329;
|
||||
}
|
||||
.test-row > span {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
/* 24px icon */
|
||||
.icon-24 svg {
|
||||
|
64
packages/react-demo/src/App.js
vendored
64
packages/react-demo/src/App.js
vendored
@ -1,44 +1,47 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Icon,
|
||||
InlineIcon,
|
||||
addIcon,
|
||||
addCollection,
|
||||
addIcon as addOfflineIcon,
|
||||
addCollection as addOfflineCollection,
|
||||
} from '@iconify/react/dist/offline';
|
||||
import alertIcon from '@iconify-icons/mdi-light/alert';
|
||||
import {
|
||||
addIcon as addOnlineIcon,
|
||||
addCollection as addOnlineCollection,
|
||||
} from '@iconify/react/dist/iconify';
|
||||
import presentationPlay from '@iconify-icons/mdi-light/presentation-play';
|
||||
import checkedIcon from '@iconify-icons/uil/check-circle';
|
||||
import uncheckedIcon from '@iconify-icons/uil/circle';
|
||||
import playIcon from '@iconify-icons/mdi-light/play';
|
||||
|
||||
import { Checkbox } from './components/Checkbox';
|
||||
import { InlineDemo } from './components/Inline';
|
||||
import { OfflineUsageDemo } from './components/UsageOffline';
|
||||
import { TestsOffline } from './components/TestsOffline';
|
||||
import { Checkbox } from './demo-components/Checkbox';
|
||||
import { InlineDemo } from './demo-components/Inline';
|
||||
import { OfflineUsageDemo } from './demo-components/UsageOffline';
|
||||
import { FullOfflineUsageDemo } from './demo-components/UsageFullOffline';
|
||||
import { TestsOffline } from './test-components/TestsOffline';
|
||||
import { TestsFullOffline } from './test-components/TestsFullOffline';
|
||||
|
||||
import './App.css';
|
||||
|
||||
// Add 'mdi-light:presentation-play' as 'demo'
|
||||
addIcon('demo', presentationPlay);
|
||||
// Add 'mdi-light:presentation-play' as 'demo' for offline module
|
||||
addOfflineIcon('demo', presentationPlay);
|
||||
|
||||
// Add 'mdi-light:play' as 'demo' for full module
|
||||
addOnlineIcon('demo', playIcon);
|
||||
|
||||
// Add custom icon as 'experiment'
|
||||
addIcon('experiment2', {
|
||||
addOfflineIcon('experiment2', {
|
||||
width: 16,
|
||||
height: 16,
|
||||
body:
|
||||
'<circle fill-opacity="0.2" cx="8" cy="8" r="7" fill="currentColor"/><path fill-rule="evenodd" clip-rule="evenodd" d="M8 16C12.4183 16 16 12.4183 16 8C16 3.58172 12.4183 0 8 0C3.58172 0 0 3.58172 0 8C0 12.4183 3.58172 16 8 16ZM8 15C11.866 15 15 11.866 15 8C15 4.13401 11.866 1 8 1C4.13401 1 1 4.13401 1 8C1 11.866 4.13401 15 8 15Z" fill="currentColor"/><path d="M7 9L5 7L3.5 8.5L7 12L13 6L11.5 4.5L7 9Z" fill="currentColor"/>',
|
||||
});
|
||||
|
||||
// Add icon with id: noto:robot
|
||||
addIcon('noto-robot', {
|
||||
addOnlineIcon('experiment2', {
|
||||
width: 16,
|
||||
height: 16,
|
||||
body:
|
||||
'<path d="M12.53 53.05c-4.57.01-8.28 3.72-8.28 8.29v38.38a8.297 8.297 0 0 0 8.28 8.28h5.55V53l-5.55.05z" fill="#c62828"/><path d="M115.72 53.05c4.57.01 8.28 3.72 8.28 8.29v38.38c-.01 4.57-3.71 8.28-8.28 8.29h-5.55v-55l5.55.04z" fill="#c62828"/><path d="M113.17 54.41l-.12-10c-.03-4.3-3.53-7.77-7.83-7.75H67.05V23.25c5.11-1.69 7.89-7.2 6.2-12.31c-1.69-5.11-7.2-7.89-12.31-6.2s-7.89 7.2-6.2 12.31a9.743 9.743 0 0 0 6.2 6.2v13.46H22.78c-4.28.01-7.75 3.47-7.78 7.75v71.78c.03 4.28 3.5 7.74 7.78 7.76h82.44c4.3.01 7.8-3.46 7.83-7.76v-7.37h.12V54.41z" fill="#90a4ae"/><path d="M64 18c-2.21 0-4-1.79-4-4s1.79-4 4-4s4 1.79 4 4s-1.79 4-4 4z" fill="#c62828"/><g><linearGradient id="ssvg-id-robota" gradientUnits="userSpaceOnUse" x1="64.005" y1="22.44" x2="64.005" y2="35.55" gradientTransform="matrix(1 0 0 -1 0 130)"><stop offset=".12" stop-color="#e0e0e0"/><stop offset=".52" stop-color="#fff"/><stop offset="1" stop-color="#eaeaea"/></linearGradient><path d="M44.15 94.45h39.71c3.46 0 6.27 2.81 6.27 6.27v.57c0 3.46-2.81 6.27-6.27 6.27H44.15c-3.46 0-6.27-2.81-6.27-6.27v-.57c0-3.46 2.81-6.27 6.27-6.27z" fill="url(#ssvg-id-robota)"/><linearGradient id="ssvg-id-robotb" gradientUnits="userSpaceOnUse" x1="54.85" y1="22.44" x2="54.85" y2="35.53" gradientTransform="matrix(1 0 0 -1 0 130)"><stop offset="0" stop-color="#333"/><stop offset=".55" stop-color="#666"/><stop offset="1" stop-color="#333"/></linearGradient><path fill="url(#ssvg-id-robotb)" d="M53.67 94.47h2.36v13.09h-2.36z"/><linearGradient id="ssvg-id-robotc" gradientUnits="userSpaceOnUse" x1="64.06" y1="22.44" x2="64.06" y2="35.53" gradientTransform="matrix(1 0 0 -1 0 130)"><stop offset="0" stop-color="#333"/><stop offset=".55" stop-color="#666"/><stop offset="1" stop-color="#333"/></linearGradient><path fill="url(#ssvg-id-robotc)" d="M62.88 94.47h2.36v13.09h-2.36z"/><linearGradient id="ssvg-id-robotd" gradientUnits="userSpaceOnUse" x1="73.15" y1="22.44" x2="73.15" y2="35.53" gradientTransform="matrix(1 0 0 -1 0 130)"><stop offset="0" stop-color="#333"/><stop offset=".55" stop-color="#666"/><stop offset="1" stop-color="#333"/></linearGradient><path fill="url(#ssvg-id-robotd)" d="M71.97 94.47h2.36v13.09h-2.36z"/><linearGradient id="ssvg-id-robote" gradientUnits="userSpaceOnUse" x1="82.8" y1="22.44" x2="82.8" y2="35.53" gradientTransform="matrix(1 0 0 -1 0 130)"><stop offset="0" stop-color="#333"/><stop offset=".55" stop-color="#666"/><stop offset="1" stop-color="#333"/></linearGradient><path fill="url(#ssvg-id-robote)" d="M81.62 94.47h2.36v13.09h-2.36z"/><linearGradient id="ssvg-id-robotf" gradientUnits="userSpaceOnUse" x1="45.2" y1="22.46" x2="45.2" y2="35.55" gradientTransform="matrix(1 0 0 -1 0 130)"><stop offset="0" stop-color="#333"/><stop offset=".55" stop-color="#666"/><stop offset="1" stop-color="#333"/></linearGradient><path fill="url(#ssvg-id-robotf)" d="M44.02 94.45h2.36v13.09h-2.36z"/><g><path d="M64 85.33h-5.33c-.55 0-1-.45-1-1c0-.16.04-.31.11-.45l2.74-5.41l2.59-4.78a.996.996 0 0 1 1.76 0l2.61 5l2.71 5.19c.25.49.06 1.09-.43 1.35c-.14.07-.29.11-.45.11L64 85.33z" fill="#c62828"/></g><g><radialGradient id="ssvg-id-robotg" cx="42.64" cy="63.19" r="11.5" gradientTransform="matrix(1 0 0 -1 0 130)" gradientUnits="userSpaceOnUse"><stop offset=".48" stop-color="#fff"/><stop offset=".77" stop-color="#fdfdfd"/><stop offset=".88" stop-color="#f6f6f6"/><stop offset=".96" stop-color="#ebebeb"/><stop offset="1" stop-color="#e0e0e0"/></radialGradient><circle cx="42.64" cy="66.81" r="11.5" fill="url(#ssvg-id-robotg)"/><linearGradient id="ssvg-id-roboth" gradientUnits="userSpaceOnUse" x1="30.14" y1="63.19" x2="55.14" y2="63.19" gradientTransform="matrix(1 0 0 -1 0 130)"><stop offset="0" stop-color="#333"/><stop offset=".55" stop-color="#666"/><stop offset="1" stop-color="#333"/></linearGradient><circle cx="42.64" cy="66.81" r="11.5" fill="none" stroke="url(#ssvg-id-roboth)" stroke-width="2" stroke-miterlimit="10"/><radialGradient id="ssvg-id-roboti" cx="84.95" cy="63.22" r="11.5" gradientTransform="matrix(1 0 0 -1 0 130)" gradientUnits="userSpaceOnUse"><stop offset=".48" stop-color="#fff"/><stop offset=".77" stop-color="#fdfdfd"/><stop offset=".88" stop-color="#f6f6f6"/><stop offset=".96" stop-color="#ebebeb"/><stop offset="1" stop-color="#e0e0e0"/></radialGradient><path d="M85 55.28c-6.35 0-11.5 5.15-11.5 11.5s5.15 11.5 11.5 11.5s11.5-5.15 11.5-11.5c-.01-6.35-5.15-11.49-11.5-11.5z" fill="url(#ssvg-id-roboti)"/><linearGradient id="ssvg-id-robotj" gradientUnits="userSpaceOnUse" x1="72.45" y1="63.22" x2="97.45" y2="63.22" gradientTransform="matrix(1 0 0 -1 0 130)"><stop offset="0" stop-color="#333"/><stop offset=".55" stop-color="#666"/><stop offset="1" stop-color="#333"/></linearGradient><path d="M85 55.28c-6.35 0-11.5 5.15-11.5 11.5s5.15 11.5 11.5 11.5s11.5-5.15 11.5-11.5h0c-.01-6.35-5.15-11.49-11.5-11.5z" fill="none" stroke="url(#ssvg-id-robotj)" stroke-width="2" stroke-miterlimit="10"/></g></g>',
|
||||
width: 128,
|
||||
height: 128,
|
||||
'<g fill="currentColor"><path fill-rule="evenodd" clip-rule="evenodd" d="M13 8.9c.1.6.2 1.1.4 1.7l.6 1.7l-.5.7H10c0 .5-.2 1-.6 1.4c-.4.4-.9.6-1.4.6c-.5 0-1.1-.2-1.4-.6c-.4-.4-.6-.9-.6-1.4H2.5l-.5-.7l.6-1.7c.2-.8.4-1.6.4-2.4V6c0-.7.1-1.4.4-2c.3-.7.7-1.2 1.2-1.7s1.1-.8 1.8-1C6.9 1.1 7.5 1 8 1c-.2.3-.4.7-.6 1.1c-.2 0-.4 0-.7.2c-.5.1-1 .4-1.4.8c-.4.3-.8.8-1 1.3c-.2.5-.3 1-.3 1.6v2.2c0 .9-.2 1.8-.4 2.7L3.2 12h9.6l-.4-1.1c-.175-.526-.274-1.13-.363-1.674L12 9c.4 0 .7 0 1-.1zM8 14c.2 0 .5-.1.7-.3c.2-.2.3-.4.3-.7H7c0 .3.1.5.3.7c.2.2.5.3.7.3zm7-10a3 3 0 1 1-6 0a3 3 0 0 1 6 0z"></path></g>',
|
||||
});
|
||||
|
||||
// Add few mdi-light: icons
|
||||
addCollection({
|
||||
prefix: 'mdi-light',
|
||||
addOfflineCollection({
|
||||
prefix: 'offline-mdi-light',
|
||||
icons: {
|
||||
'account-alert': {
|
||||
body:
|
||||
@ -52,11 +55,27 @@ addCollection({
|
||||
width: 24,
|
||||
height: 24,
|
||||
});
|
||||
addOnlineCollection({
|
||||
prefix: '',
|
||||
icons: {
|
||||
alert1: {
|
||||
body:
|
||||
'<path d="M10.5 14c4.142 0 7.5 1.567 7.5 3.5V20H3v-2.5c0-1.933 3.358-3.5 7.5-3.5zm6.5 3.5c0-1.38-2.91-2.5-6.5-2.5S4 16.12 4 17.5V19h13v-1.5zM10.5 5a3.5 3.5 0 1 1 0 7a3.5 3.5 0 0 1 0-7zm0 1a2.5 2.5 0 1 0 0 5a2.5 2.5 0 0 0 0-5zM20 16v-1h1v1h-1zm0-3V7h1v6h-1z" fill="currentColor"/>',
|
||||
},
|
||||
link1: {
|
||||
body:
|
||||
'<path d="M8 13v-1h7v1H8zm7.5-6a5.5 5.5 0 1 1 0 11H13v-1h2.5a4.5 4.5 0 1 0 0-9H13V7h2.5zm-8 11a5.5 5.5 0 1 1 0-11H10v1H7.5a4.5 4.5 0 1 0 0 9H10v1H7.5z" fill="currentColor"/>',
|
||||
},
|
||||
},
|
||||
width: 24,
|
||||
height: 24,
|
||||
});
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div className="App">
|
||||
<OfflineUsageDemo />
|
||||
<FullOfflineUsageDemo />
|
||||
|
||||
<section>
|
||||
<h1>Checkbox</h1>
|
||||
@ -77,6 +96,7 @@ function App() {
|
||||
<InlineDemo />
|
||||
|
||||
<TestsOffline />
|
||||
<TestsFullOffline />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '@iconify/react/dist/offline';
|
||||
|
||||
export function InlineDemo() {
|
||||
return (
|
||||
<section className="inline-demo">
|
||||
<h1>Inline demo</h1>
|
||||
<div>
|
||||
Block icon (behaving like image):
|
||||
<Icon icon="experiment2" />
|
||||
</div>
|
||||
<div>
|
||||
Inline icon (behaving line text / icon font):
|
||||
<Icon icon="experiment2" inline={true} />
|
||||
</div>
|
||||
<div>
|
||||
Using "vertical-align: 0" to override inline attribute:
|
||||
<Icon icon="experiment2" style={{ verticalAlign: 0 }} />
|
||||
<Icon
|
||||
icon="experiment2"
|
||||
style={{ verticalAlign: 0 }}
|
||||
inline={true}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '@iconify/react/dist/offline';
|
||||
import successIcon from '@iconify-icons/uil/check-circle';
|
||||
import pendingIcon from '@iconify-icons/uil/question-circle';
|
||||
import failedIcon from '@iconify-icons/uil/times-circle';
|
||||
|
||||
export function TestIcon(props) {
|
||||
let icon = pendingIcon;
|
||||
let className = '';
|
||||
|
||||
switch (props.status) {
|
||||
case 'success':
|
||||
case 'default-success':
|
||||
case true:
|
||||
icon = successIcon;
|
||||
className = 'success';
|
||||
break;
|
||||
|
||||
case 'fail':
|
||||
case false:
|
||||
icon = failedIcon;
|
||||
className = 'fail';
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
|
||||
return <InlineIcon icon={icon} className={className} />;
|
||||
}
|
@ -1,285 +0,0 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '@iconify/react/dist/offline';
|
||||
import { TestIcon } from './TestIcon';
|
||||
|
||||
export class TestsOffline extends React.Component {
|
||||
constructor(props) {
|
||||
super();
|
||||
|
||||
const state = {
|
||||
ref_missing: 'default-success',
|
||||
};
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
render() {
|
||||
const state = this.state;
|
||||
const success = this._toggle.bind(this, 'success');
|
||||
const fail = this._toggle.bind(this, 'fail');
|
||||
return (
|
||||
<section className="tests">
|
||||
<h1>Tests (offline module)</h1>
|
||||
|
||||
<h2>References</h2>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcon status={state.ref} />
|
||||
<span>
|
||||
Getting reference
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
ref={(element) => {
|
||||
const key = 'ref';
|
||||
if (element && element.tagName === 'svg') {
|
||||
success(key);
|
||||
} else {
|
||||
fail(key);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcon status={state.ref_missing} />
|
||||
<span>
|
||||
Getting reference for empty icon
|
||||
<InlineIcon
|
||||
ref={(element) => {
|
||||
// Cannot be called because there is no SVG to render!
|
||||
fail('ref_missing');
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcon status={state.ref_missing} />
|
||||
<span>
|
||||
Getting reference for missing icon with fallback text{' '}
|
||||
<InlineIcon
|
||||
ref={(element) => {
|
||||
// Cannot be called because there is no SVG to render!
|
||||
fail('ref_missing');
|
||||
}}
|
||||
>
|
||||
😀
|
||||
</InlineIcon>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h2>Style</h2>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcon status={state.style} />
|
||||
<span>
|
||||
Inline style for icon
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
style={{
|
||||
color: '#1769aa',
|
||||
fontSize: '24px',
|
||||
lineHeight: '1em',
|
||||
verticalAlign: '-0.25em',
|
||||
}}
|
||||
ref={(element) => {
|
||||
const key = 'style';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(23, 105, 170)':
|
||||
case '#1769aa':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log(
|
||||
'Invalid color:',
|
||||
style.color
|
||||
);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (style.fontSize !== '24px') {
|
||||
console.log(
|
||||
'Invalid font-size:',
|
||||
style.fontSize
|
||||
);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (style.verticalAlign !== '-0.25em') {
|
||||
console.log(
|
||||
'Invalid vertical-align:',
|
||||
style.verticalAlign
|
||||
);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (errors) {
|
||||
fail(key);
|
||||
} else {
|
||||
success(key);
|
||||
}
|
||||
} else {
|
||||
fail(key);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcon status={state.color1} />
|
||||
<span>
|
||||
Green color from attribute:{' '}
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
color="green"
|
||||
ref={(element) => {
|
||||
const key = 'color1';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(0, 128, 0)':
|
||||
case '#008000':
|
||||
case 'green':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log(
|
||||
'Invalid color:',
|
||||
style.color
|
||||
);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (errors) {
|
||||
fail(key);
|
||||
} else {
|
||||
success(key);
|
||||
}
|
||||
} else {
|
||||
fail(key);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcon status={state.color2} />
|
||||
<span>
|
||||
Green color from style:{' '}
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
style={{
|
||||
color: 'green',
|
||||
}}
|
||||
ref={(element) => {
|
||||
const key = 'color2';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(0, 128, 0)':
|
||||
case '#008000':
|
||||
case 'green':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log(
|
||||
'Invalid color:',
|
||||
style.color
|
||||
);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (errors) {
|
||||
fail(key);
|
||||
} else {
|
||||
success(key);
|
||||
}
|
||||
} else {
|
||||
fail(key);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcon status={state.color3} />
|
||||
<span>
|
||||
Green color from attribute (overrides style) + red from
|
||||
style:{' '}
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
color="green"
|
||||
style={{
|
||||
color: 'red',
|
||||
}}
|
||||
ref={(element) => {
|
||||
const key = 'color3';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(0, 128, 0)':
|
||||
case '#008000':
|
||||
case 'green':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log(
|
||||
'Invalid color:',
|
||||
style.color
|
||||
);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (errors) {
|
||||
fail(key);
|
||||
} else {
|
||||
success(key);
|
||||
}
|
||||
} else {
|
||||
fail(key);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
_toggle(value, key) {
|
||||
setTimeout(() => {
|
||||
const oldValue = this.state[key];
|
||||
if (
|
||||
oldValue === value ||
|
||||
oldValue === 'success' ||
|
||||
oldValue === 'fail'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
[key]: value,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
36
packages/react-demo/src/demo-components/Inline.jsx
Normal file
36
packages/react-demo/src/demo-components/Inline.jsx
Normal file
@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import { Icon as OfflineIcon } from '@iconify/react/dist/offline';
|
||||
import { Icon as FullIcon } from '@iconify/react/dist/iconify';
|
||||
|
||||
export function InlineDemo() {
|
||||
return (
|
||||
<section className="inline-demo">
|
||||
<h1>Inline demo</h1>
|
||||
<div>
|
||||
Block icon (behaving like image):
|
||||
<OfflineIcon icon="experiment2" />
|
||||
<FullIcon icon="experiment2" />
|
||||
</div>
|
||||
<div>
|
||||
Inline icon (behaving line text / icon font):
|
||||
<OfflineIcon icon="experiment2" inline={true} />
|
||||
<FullIcon icon="experiment2" inline={true} />
|
||||
</div>
|
||||
<div>
|
||||
Using "vertical-align: 0" to override inline attribute:
|
||||
<OfflineIcon icon="experiment2" style={{ verticalAlign: 0 }} />
|
||||
<FullIcon icon="experiment2" style={{ verticalAlign: 0 }} />
|
||||
<OfflineIcon
|
||||
icon="experiment2"
|
||||
style={{ verticalAlign: 0 }}
|
||||
inline={true}
|
||||
/>
|
||||
<FullIcon
|
||||
icon="experiment2"
|
||||
style={{ verticalAlign: 0 }}
|
||||
inline={true}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
26
packages/react-demo/src/demo-components/UsageFullOffline.jsx
Normal file
26
packages/react-demo/src/demo-components/UsageFullOffline.jsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '@iconify/react/dist/iconify';
|
||||
import accountIcon from '@iconify-icons/mdi-light/account';
|
||||
import alertIcon from '@iconify-icons/mdi-light/alert';
|
||||
|
||||
export function FullOfflineUsageDemo() {
|
||||
return (
|
||||
<section className="icon-24">
|
||||
<h1>Usage (full module, offline mode)</h1>
|
||||
<div>
|
||||
Icon referenced by name: <Icon icon="demo" />
|
||||
</div>
|
||||
<div>
|
||||
Icon referenced by object: <Icon icon={accountIcon} />
|
||||
</div>
|
||||
<div>
|
||||
2 icons imported from icon set: <Icon icon="alert1" />
|
||||
<Icon icon="link1" />
|
||||
</div>
|
||||
<div className="alert">
|
||||
<Icon icon={alertIcon} />
|
||||
Important notice with alert icon!
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
@ -7,9 +7,6 @@ export function OfflineUsageDemo() {
|
||||
return (
|
||||
<section className="icon-24">
|
||||
<h1>Usage (offline module)</h1>
|
||||
<div>
|
||||
Empty icon: <Icon />
|
||||
</div>
|
||||
<div>
|
||||
Icon referenced by name: <Icon icon="demo" />
|
||||
</div>
|
||||
@ -18,8 +15,8 @@ export function OfflineUsageDemo() {
|
||||
</div>
|
||||
<div>
|
||||
2 icons imported from icon set:{' '}
|
||||
<Icon icon="mdi-light:account-alert" />
|
||||
<Icon icon="mdi-light:link" />
|
||||
<Icon icon="offline-mdi-light:account-alert" />
|
||||
<Icon icon="offline-mdi-light:link" />
|
||||
</div>
|
||||
<div className="alert">
|
||||
<Icon icon={alertIcon} />
|
78
packages/react-demo/src/test-components/TestIcons.jsx
Normal file
78
packages/react-demo/src/test-components/TestIcons.jsx
Normal file
@ -0,0 +1,78 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '@iconify/react/dist/offline';
|
||||
import successIcon from '@iconify-icons/uil/check-circle';
|
||||
import pendingIcon from '@iconify-icons/uil/question-circle';
|
||||
import failedIcon from '@iconify-icons/uil/times-circle';
|
||||
|
||||
function getStatus(status) {
|
||||
switch (status) {
|
||||
case 'success':
|
||||
case 'default-success':
|
||||
case true:
|
||||
return 'success';
|
||||
|
||||
case 'failed':
|
||||
case 'fail':
|
||||
case false:
|
||||
return 'failed';
|
||||
|
||||
default:
|
||||
return 'pending';
|
||||
}
|
||||
}
|
||||
|
||||
export function TestIcons(props) {
|
||||
if (!props.id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const id = 'test-icons-' + props.id;
|
||||
const icon = getStatus(props.status);
|
||||
|
||||
return (
|
||||
<span className="test-row-icons" id={id}>
|
||||
<InlineIcon
|
||||
icon={successIcon}
|
||||
className={
|
||||
'success ' + (icon === 'success' ? 'visible' : 'hidden')
|
||||
}
|
||||
/>
|
||||
<InlineIcon
|
||||
icon={pendingIcon}
|
||||
className={
|
||||
'pending ' + (icon === 'pending' ? 'visible' : 'hidden')
|
||||
}
|
||||
/>
|
||||
<InlineIcon
|
||||
icon={failedIcon}
|
||||
className={
|
||||
'failed ' + (icon === 'failed' ? 'visible' : 'hidden')
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export function toggleTest(id, status) {
|
||||
const node = document.getElementById('test-icons-' + id);
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get icon to show
|
||||
const icon = getStatus(status);
|
||||
|
||||
// Remove previous status
|
||||
const visible = node.querySelector('.visible');
|
||||
if (visible) {
|
||||
visible.classList.remove('visible');
|
||||
visible.classList.add('hidden');
|
||||
}
|
||||
|
||||
// Show new icon
|
||||
const toggle = node.querySelector('.' + icon);
|
||||
if (toggle) {
|
||||
toggle.classList.remove('hidden');
|
||||
toggle.classList.add('visible');
|
||||
}
|
||||
}
|
212
packages/react-demo/src/test-components/TestsFullOffline.jsx
Normal file
212
packages/react-demo/src/test-components/TestsFullOffline.jsx
Normal file
@ -0,0 +1,212 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '@iconify/react/dist/iconify';
|
||||
import { TestIcons, toggleTest } from './TestIcons';
|
||||
|
||||
export function TestsFullOffline() {
|
||||
return (
|
||||
<section className="tests">
|
||||
<h1>Tests (full module, without API)</h1>
|
||||
|
||||
<h2>References</h2>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="full-offline-ref1" />
|
||||
Getting reference
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
ref={(element) => {
|
||||
const key = 'full-offline-ref1';
|
||||
if (element && element.tagName === 'svg') {
|
||||
toggleTest(key, 'success');
|
||||
} else {
|
||||
toggleTest(key, 'failed');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="full-offline-ref-missing" status="success" />
|
||||
Getting reference for empty icon
|
||||
<InlineIcon
|
||||
ref={(element) => {
|
||||
// Cannot be called because there is no SVG to render!
|
||||
toggleTest('full-offline-ref-missing', 'failed');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="full-offline-ref-missing2" status="success" />
|
||||
Getting reference for missing icon with fallback text{' '}
|
||||
<InlineIcon
|
||||
ref={(element) => {
|
||||
// Cannot be called because there is no SVG to render!
|
||||
toggleTest('full-offline-ref-missing2', 'failed');
|
||||
}}
|
||||
>
|
||||
😀
|
||||
</InlineIcon>
|
||||
</div>
|
||||
|
||||
<h2>Style</h2>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="full-offline-style" />
|
||||
Inline style for icon
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
style={{
|
||||
color: '#1769aa',
|
||||
fontSize: '24px',
|
||||
lineHeight: '1em',
|
||||
verticalAlign: '-0.25em',
|
||||
}}
|
||||
ref={(element) => {
|
||||
const key = 'full-offline-style';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(23, 105, 170)':
|
||||
case '#1769aa':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Invalid color:', style.color);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (style.fontSize !== '24px') {
|
||||
console.log(
|
||||
'Invalid font-size:',
|
||||
style.fontSize
|
||||
);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (style.verticalAlign !== '-0.25em') {
|
||||
console.log(
|
||||
'Invalid vertical-align:',
|
||||
style.verticalAlign
|
||||
);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
toggleTest(key, !errors);
|
||||
} else {
|
||||
toggleTest(key, 'failed');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="full-offline-color1" />
|
||||
Green color from attribute:{' '}
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
color="green"
|
||||
ref={(element) => {
|
||||
const key = 'full-offline-color1';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(0, 128, 0)':
|
||||
case '#008000':
|
||||
case 'green':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Invalid color:', style.color);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
toggleTest(key, !errors);
|
||||
} else {
|
||||
toggleTest(key, 'failed');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="full-offline-color2" />
|
||||
Green color from style:{' '}
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
style={{
|
||||
color: 'green',
|
||||
}}
|
||||
ref={(element) => {
|
||||
const key = 'full-offline-color2';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(0, 128, 0)':
|
||||
case '#008000':
|
||||
case 'green':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Invalid color:', style.color);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
toggleTest(key, !errors);
|
||||
} else {
|
||||
toggleTest(key, 'failed');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="full-offline-color3" />
|
||||
Green color from attribute (overrides style) + red from style:{' '}
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
color="green"
|
||||
style={{
|
||||
color: 'red',
|
||||
}}
|
||||
ref={(element) => {
|
||||
const key = 'full-offline-color3';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(0, 128, 0)':
|
||||
case '#008000':
|
||||
case 'green':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Invalid color:', style.color);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
toggleTest(key, !errors);
|
||||
} else {
|
||||
toggleTest(key, 'failed');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
212
packages/react-demo/src/test-components/TestsOffline.jsx
Normal file
212
packages/react-demo/src/test-components/TestsOffline.jsx
Normal file
@ -0,0 +1,212 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '@iconify/react/dist/offline';
|
||||
import { TestIcons, toggleTest } from './TestIcons';
|
||||
|
||||
export function TestsOffline() {
|
||||
return (
|
||||
<section className="tests">
|
||||
<h1>Tests (offline module)</h1>
|
||||
|
||||
<h2>References</h2>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="offline-ref1" />
|
||||
Getting reference
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
ref={(element) => {
|
||||
const key = 'offline-ref1';
|
||||
if (element && element.tagName === 'svg') {
|
||||
toggleTest(key, 'success');
|
||||
} else {
|
||||
toggleTest(key, 'failed');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="offline-ref-missing" status="success" />
|
||||
Getting reference for empty icon
|
||||
<InlineIcon
|
||||
ref={(element) => {
|
||||
// Cannot be called because there is no SVG to render!
|
||||
toggleTest('offline-ref-missing', 'failed');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="offline-ref-missing2" status="success" />
|
||||
Getting reference for missing icon with fallback text{' '}
|
||||
<InlineIcon
|
||||
ref={(element) => {
|
||||
// Cannot be called because there is no SVG to render!
|
||||
toggleTest('offline-ref-missing2', 'failed');
|
||||
}}
|
||||
>
|
||||
😀
|
||||
</InlineIcon>
|
||||
</div>
|
||||
|
||||
<h2>Style</h2>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="offline-style" />
|
||||
Inline style for icon
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
style={{
|
||||
color: '#1769aa',
|
||||
fontSize: '24px',
|
||||
lineHeight: '1em',
|
||||
verticalAlign: '-0.25em',
|
||||
}}
|
||||
ref={(element) => {
|
||||
const key = 'offline-style';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(23, 105, 170)':
|
||||
case '#1769aa':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Invalid color:', style.color);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (style.fontSize !== '24px') {
|
||||
console.log(
|
||||
'Invalid font-size:',
|
||||
style.fontSize
|
||||
);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (style.verticalAlign !== '-0.25em') {
|
||||
console.log(
|
||||
'Invalid vertical-align:',
|
||||
style.verticalAlign
|
||||
);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
toggleTest(key, !errors);
|
||||
} else {
|
||||
toggleTest(key, 'failed');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="offline-color1" />
|
||||
Green color from attribute:{' '}
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
color="green"
|
||||
ref={(element) => {
|
||||
const key = 'offline-color1';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(0, 128, 0)':
|
||||
case '#008000':
|
||||
case 'green':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Invalid color:', style.color);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
toggleTest(key, !errors);
|
||||
} else {
|
||||
toggleTest(key, 'failed');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="offline-color2" />
|
||||
Green color from style:{' '}
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
style={{
|
||||
color: 'green',
|
||||
}}
|
||||
ref={(element) => {
|
||||
const key = 'offline-color2';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(0, 128, 0)':
|
||||
case '#008000':
|
||||
case 'green':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Invalid color:', style.color);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
toggleTest(key, !errors);
|
||||
} else {
|
||||
toggleTest(key, 'failed');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="test-row">
|
||||
<TestIcons id="offline-color3" />
|
||||
Green color from attribute (overrides style) + red from style:{' '}
|
||||
<InlineIcon
|
||||
icon="demo"
|
||||
color="green"
|
||||
style={{
|
||||
color: 'red',
|
||||
}}
|
||||
ref={(element) => {
|
||||
const key = 'offline-color3';
|
||||
if (element && element.tagName === 'svg') {
|
||||
let errors = false;
|
||||
|
||||
// Get style
|
||||
const style = element.style;
|
||||
|
||||
switch (style.color.toLowerCase()) {
|
||||
case 'rgb(0, 128, 0)':
|
||||
case '#008000':
|
||||
case 'green':
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Invalid color:', style.color);
|
||||
errors = true;
|
||||
}
|
||||
|
||||
toggleTest(key, !errors);
|
||||
} else {
|
||||
toggleTest(key, 'failed');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
1
packages/react/package-lock.json
generated
1
packages/react/package-lock.json
generated
@ -12,6 +12,7 @@
|
||||
"@babel/preset-env": "^7.13.15",
|
||||
"@babel/preset-react": "^7.13.13",
|
||||
"@iconify/core": "^1.0.0-rc.4",
|
||||
"@iconify/types": "^1.0.6",
|
||||
"@microsoft/api-extractor": "^7.13.5",
|
||||
"@rollup/plugin-buble": "^0.21.3",
|
||||
"@rollup/plugin-commonjs": "^18.0.0",
|
||||
|
@ -27,6 +27,7 @@
|
||||
"@babel/preset-env": "^7.13.15",
|
||||
"@babel/preset-react": "^7.13.13",
|
||||
"@iconify/core": "^1.0.0-rc.4",
|
||||
"@iconify/types": "^1.0.6",
|
||||
"@microsoft/api-extractor": "^7.13.5",
|
||||
"@rollup/plugin-buble": "^0.21.3",
|
||||
"@rollup/plugin-commonjs": "^18.0.0",
|
||||
|
@ -1,40 +1,293 @@
|
||||
import React from 'react';
|
||||
import type { IconifyIcon, IconifyJSON } from '@iconify/types';
|
||||
import type { IconifyJSON } from '@iconify/types';
|
||||
|
||||
// Core
|
||||
import { stringToIcon } from '@iconify/core/lib/icon/name';
|
||||
import type { IconifyIconName } from '@iconify/core/lib/icon/name';
|
||||
import type {
|
||||
IconifyIconSize,
|
||||
IconifyHorizontalIconAlignment,
|
||||
IconifyVerticalIconAlignment,
|
||||
IconifyIconSize,
|
||||
} from '@iconify/core/lib/customisations';
|
||||
import { fullIcon } from '@iconify/core/lib/icon';
|
||||
import { parseIconSet } from '@iconify/core/lib/icon/icon-set';
|
||||
import {
|
||||
IconifyStorageFunctions,
|
||||
storageFunctions,
|
||||
getIconData,
|
||||
allowSimpleNames,
|
||||
} from '@iconify/core/lib/storage/functions';
|
||||
import {
|
||||
IconifyBuilderFunctions,
|
||||
builderFunctions,
|
||||
} from '@iconify/core/lib/builder/functions';
|
||||
import { fullIcon, IconifyIcon } from '@iconify/core/lib/icon';
|
||||
|
||||
// Modules
|
||||
import { coreModules } from '@iconify/core/lib/modules';
|
||||
|
||||
// API
|
||||
import { API, IconifyAPIInternalStorage } from '@iconify/core/lib/api/';
|
||||
import {
|
||||
IconifyAPIFunctions,
|
||||
IconifyAPIInternalFunctions,
|
||||
APIFunctions,
|
||||
APIInternalFunctions,
|
||||
} from '@iconify/core/lib/api/functions';
|
||||
import {
|
||||
setAPIModule,
|
||||
IconifyAPIModule,
|
||||
IconifyAPISendQuery,
|
||||
IconifyAPIPrepareQuery,
|
||||
GetIconifyAPIModule,
|
||||
} from '@iconify/core/lib/api/modules';
|
||||
import { getAPIModule as getJSONPAPIModule } from '@iconify/core/lib/api/modules/jsonp';
|
||||
import {
|
||||
getAPIModule as getFetchAPIModule,
|
||||
setFetch,
|
||||
} from '@iconify/core/lib/api/modules/fetch';
|
||||
import {
|
||||
setAPIConfig,
|
||||
PartialIconifyAPIConfig,
|
||||
IconifyAPIConfig,
|
||||
getAPIConfig,
|
||||
GetAPIConfig,
|
||||
} from '@iconify/core/lib/api/config';
|
||||
import type {
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
} from '@iconify/core/lib/interfaces/loader';
|
||||
|
||||
// Cache
|
||||
import { storeCache, loadCache } from '@iconify/core/lib/browser-storage';
|
||||
import { toggleBrowserCache } from '@iconify/core/lib/browser-storage/functions';
|
||||
import type {
|
||||
IconifyBrowserCacheType,
|
||||
IconifyBrowserCacheFunctions,
|
||||
} from '@iconify/core/lib/browser-storage/functions';
|
||||
|
||||
// Properties
|
||||
import type {
|
||||
IconifyIconCustomisations,
|
||||
IconifyIconProps,
|
||||
IconProps,
|
||||
IconRef,
|
||||
} from './props';
|
||||
|
||||
// Render SVG
|
||||
import { render } from './render';
|
||||
|
||||
/**
|
||||
* Export stuff from props.ts
|
||||
*/
|
||||
export { IconifyIconCustomisations, IconifyIconProps, IconProps };
|
||||
|
||||
/**
|
||||
* Export types that could be used in component
|
||||
* Export required types
|
||||
*/
|
||||
// Function sets
|
||||
export {
|
||||
IconifyIcon,
|
||||
IconifyJSON,
|
||||
IconifyHorizontalIconAlignment,
|
||||
IconifyVerticalIconAlignment,
|
||||
IconifyIconSize,
|
||||
IconifyStorageFunctions,
|
||||
IconifyBuilderFunctions,
|
||||
IconifyBrowserCacheFunctions,
|
||||
IconifyAPIFunctions,
|
||||
IconifyAPIInternalFunctions,
|
||||
};
|
||||
|
||||
// JSON stuff
|
||||
export { IconifyIcon, IconifyJSON, IconifyIconName };
|
||||
|
||||
// Customisations
|
||||
export {
|
||||
IconifyIconCustomisations,
|
||||
IconifyIconSize,
|
||||
IconifyHorizontalIconAlignment,
|
||||
IconifyVerticalIconAlignment,
|
||||
IconifyIconProps,
|
||||
IconProps,
|
||||
};
|
||||
|
||||
// API
|
||||
export {
|
||||
IconifyAPIConfig,
|
||||
IconifyIconLoaderCallback,
|
||||
IconifyIconLoaderAbort,
|
||||
IconifyAPIInternalStorage,
|
||||
IconifyAPIModule,
|
||||
GetAPIConfig,
|
||||
IconifyAPIPrepareQuery,
|
||||
IconifyAPISendQuery,
|
||||
};
|
||||
|
||||
/* Browser cache */
|
||||
export { IconifyBrowserCacheType };
|
||||
|
||||
/**
|
||||
* Storage for icons referred by name
|
||||
* Enable and disable browser cache
|
||||
*/
|
||||
export const enableCache = (storage: IconifyBrowserCacheType) =>
|
||||
toggleBrowserCache(storage, true);
|
||||
|
||||
export const disableCache = (storage: IconifyBrowserCacheType) =>
|
||||
toggleBrowserCache(storage, false);
|
||||
|
||||
/* Storage functions */
|
||||
/**
|
||||
* Check if icon exists
|
||||
*/
|
||||
export const iconExists = storageFunctions.iconExists;
|
||||
|
||||
/**
|
||||
* Get icon data
|
||||
*/
|
||||
export const getIcon = storageFunctions.getIcon;
|
||||
|
||||
/**
|
||||
* List available icons
|
||||
*/
|
||||
export const listIcons = storageFunctions.listIcons;
|
||||
|
||||
/**
|
||||
* Add one icon
|
||||
*/
|
||||
export const addIcon = storageFunctions.addIcon;
|
||||
|
||||
/**
|
||||
* Add icon set
|
||||
*/
|
||||
export const addCollection = storageFunctions.addCollection;
|
||||
|
||||
/* Builder functions */
|
||||
/**
|
||||
* Calculate icon size
|
||||
*/
|
||||
export const calculateSize = builderFunctions.calculateSize;
|
||||
|
||||
/**
|
||||
* Replace unique ids in content
|
||||
*/
|
||||
export const replaceIDs = builderFunctions.replaceIDs;
|
||||
|
||||
/* API functions */
|
||||
/**
|
||||
* Load icons
|
||||
*/
|
||||
export const loadIcons = APIFunctions.loadIcons;
|
||||
|
||||
/**
|
||||
* Add API provider
|
||||
*/
|
||||
export const addAPIProvider = APIFunctions.addAPIProvider;
|
||||
|
||||
/**
|
||||
* Export internal functions that can be used by third party implementations
|
||||
*/
|
||||
export const _api = APIInternalFunctions;
|
||||
|
||||
/**
|
||||
* Initialise stuff
|
||||
*/
|
||||
// Enable short names
|
||||
allowSimpleNames(true);
|
||||
|
||||
// Set API
|
||||
coreModules.api = API;
|
||||
|
||||
let getAPIModule: GetIconifyAPIModule;
|
||||
try {
|
||||
getAPIModule =
|
||||
typeof fetch === 'function' && typeof Promise === 'function'
|
||||
? getFetchAPIModule
|
||||
: getJSONPAPIModule;
|
||||
} catch (err) {
|
||||
getAPIModule = getJSONPAPIModule;
|
||||
}
|
||||
setAPIModule('', getAPIModule(getAPIConfig));
|
||||
|
||||
/**
|
||||
* Enable node-fetch for getting icons on server side
|
||||
*/
|
||||
export function setNodeFetch(nodeFetch: typeof fetch) {
|
||||
setFetch(nodeFetch);
|
||||
if (getAPIModule !== getFetchAPIModule) {
|
||||
getAPIModule = getFetchAPIModule;
|
||||
setAPIModule('', getAPIModule(getAPIConfig));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Browser stuff
|
||||
*/
|
||||
if (typeof document !== 'undefined' && typeof window !== 'undefined') {
|
||||
// Set cache and load existing cache
|
||||
coreModules.cache = storeCache;
|
||||
loadCache();
|
||||
|
||||
const _window = window;
|
||||
|
||||
// Load icons from global "IconifyPreload"
|
||||
interface WindowWithIconifyPreload {
|
||||
IconifyPreload: IconifyJSON[] | IconifyJSON;
|
||||
}
|
||||
if (
|
||||
((_window as unknown) as WindowWithIconifyPreload).IconifyPreload !==
|
||||
void 0
|
||||
) {
|
||||
const preload = ((_window as unknown) as WindowWithIconifyPreload)
|
||||
.IconifyPreload;
|
||||
const err = 'Invalid IconifyPreload syntax.';
|
||||
if (typeof preload === 'object' && preload !== null) {
|
||||
(preload instanceof Array ? preload : [preload]).forEach((item) => {
|
||||
try {
|
||||
if (
|
||||
// Check if item is an object and not null/array
|
||||
typeof item !== 'object' ||
|
||||
item === null ||
|
||||
item instanceof Array ||
|
||||
// Check for 'icons' and 'prefix'
|
||||
typeof item.icons !== 'object' ||
|
||||
typeof item.prefix !== 'string' ||
|
||||
// Add icon set
|
||||
!addCollection(item)
|
||||
) {
|
||||
console.error(err);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Set API from global "IconifyProviders"
|
||||
interface WindowWithIconifyProviders {
|
||||
IconifyProviders: Record<string, PartialIconifyAPIConfig>;
|
||||
}
|
||||
if (
|
||||
((_window as unknown) as WindowWithIconifyProviders)
|
||||
.IconifyProviders !== void 0
|
||||
) {
|
||||
const providers = ((_window as unknown) as WindowWithIconifyProviders)
|
||||
.IconifyProviders;
|
||||
if (typeof providers === 'object' && providers !== null) {
|
||||
for (let key in providers) {
|
||||
const err = 'IconifyProviders[' + key + '] is invalid.';
|
||||
try {
|
||||
const value = providers[key];
|
||||
if (
|
||||
typeof value !== 'object' ||
|
||||
!value ||
|
||||
value.resources === void 0
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (!setAPIConfig(key, value)) {
|
||||
console.error(err);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Component
|
||||
*/
|
||||
const storage: Record<string, Required<IconifyIcon>> = Object.create(null);
|
||||
|
||||
/**
|
||||
* Generate icon
|
||||
@ -44,27 +297,32 @@ function component(
|
||||
inline: boolean,
|
||||
ref?: IconRef
|
||||
): JSX.Element {
|
||||
// Split properties
|
||||
const icon =
|
||||
typeof props.icon === 'string'
|
||||
? storage[props.icon]
|
||||
: typeof props.icon === 'object'
|
||||
? fullIcon(props.icon)
|
||||
: null;
|
||||
const icon = props.icon;
|
||||
|
||||
// Validate icon object
|
||||
if (
|
||||
icon === null ||
|
||||
typeof icon !== 'object' ||
|
||||
typeof icon.body !== 'string'
|
||||
) {
|
||||
return props.children
|
||||
? (props.children as JSX.Element)
|
||||
: React.createElement('span', {});
|
||||
// Check if icon is an object
|
||||
if (typeof icon === 'object' && typeof icon.body === 'string') {
|
||||
return render(fullIcon(icon), props, inline, ref);
|
||||
}
|
||||
|
||||
// Valid icon: render it
|
||||
return render(icon, props, inline, ref);
|
||||
// Check if icon is a string
|
||||
if (typeof icon === 'string') {
|
||||
const iconName = stringToIcon(icon, true, true);
|
||||
if (iconName) {
|
||||
// Valid icon name
|
||||
const iconData = getIconData(iconName);
|
||||
if (iconData) {
|
||||
// Icon is available
|
||||
return render(iconData, props, inline, ref);
|
||||
}
|
||||
|
||||
// TODO: icon is missing
|
||||
}
|
||||
}
|
||||
|
||||
// Error
|
||||
return props.children
|
||||
? (props.children as JSX.Element)
|
||||
: React.createElement('span', {});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,36 +347,3 @@ export const Icon: Component = React.forwardRef(
|
||||
export const InlineIcon: Component = React.forwardRef(
|
||||
(props: IconProps, ref?: IconRef) => component(props, true, ref)
|
||||
);
|
||||
|
||||
/**
|
||||
* Add icon to storage, allowing to call it by name
|
||||
*
|
||||
* @param name
|
||||
* @param data
|
||||
*/
|
||||
export function addIcon(name: string, data: IconifyIcon): void {
|
||||
storage[name] = fullIcon(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add collection to storage, allowing to call icons by name
|
||||
*
|
||||
* @param data Icon set
|
||||
* @param prefix Optional prefix to add to icon names, true if prefix from icon set should be used.
|
||||
*/
|
||||
export function addCollection(
|
||||
data: IconifyJSON,
|
||||
prefix?: string | boolean
|
||||
): void {
|
||||
const iconPrefix: string =
|
||||
typeof prefix === 'string'
|
||||
? prefix
|
||||
: prefix !== false && typeof data.prefix === 'string'
|
||||
? data.prefix + ':'
|
||||
: '';
|
||||
parseIconSet(data, (name, icon) => {
|
||||
if (icon !== null) {
|
||||
storage[iconPrefix + name] = icon;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
62
packages/react/tests/iconify/10-basic.test.js
Normal file
62
packages/react/tests/iconify/10-basic.test.js
Normal file
@ -0,0 +1,62 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body:
|
||||
'<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Creating component using object', () => {
|
||||
test('basic icon', () => {
|
||||
const component = renderer.create(<Icon icon={iconData} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink': 'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'preserveAspectRatio': 'xMidYMid meet',
|
||||
'viewBox': '0 0 ' + iconData.width + ' ' + iconData.height,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('inline icon', () => {
|
||||
const component = renderer.create(<InlineIcon icon={iconData} />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'svg',
|
||||
props: {
|
||||
'xmlns': 'http://www.w3.org/2000/svg',
|
||||
'xmlnsXlink': 'http://www.w3.org/1999/xlink',
|
||||
'aria-hidden': true,
|
||||
'role': 'img',
|
||||
'style': {
|
||||
verticalAlign: '-0.125em',
|
||||
},
|
||||
'dangerouslySetInnerHTML': {
|
||||
__html: iconData.body,
|
||||
},
|
||||
'width': '1em',
|
||||
'height': '1em',
|
||||
'preserveAspectRatio': 'xMidYMid meet',
|
||||
'viewBox': '0 0 ' + iconData.width + ' ' + iconData.height,
|
||||
},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
});
|
57
packages/react/tests/iconify/10-empty.test.js
Normal file
57
packages/react/tests/iconify/10-empty.test.js
Normal file
@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
describe('Empty icon', () => {
|
||||
test('basic test', () => {
|
||||
const component = renderer.create(<Icon />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'span',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('with child node', () => {
|
||||
const component = renderer.create(
|
||||
<Icon>
|
||||
<i class="fa fa-home" />
|
||||
</Icon>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject({
|
||||
type: 'i',
|
||||
props: {},
|
||||
children: null,
|
||||
});
|
||||
});
|
||||
|
||||
test('with text child node', () => {
|
||||
const component = renderer.create(<Icon>icon</Icon>);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatch('icon');
|
||||
});
|
||||
|
||||
test('with multiple childen', () => {
|
||||
const component = renderer.create(
|
||||
<Icon>
|
||||
<i class="fa fa-home" />
|
||||
Home
|
||||
</Icon>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree).toMatchObject([
|
||||
{
|
||||
type: 'i',
|
||||
props: {},
|
||||
children: null,
|
||||
},
|
||||
'Home',
|
||||
]);
|
||||
});
|
||||
});
|
88
packages/react/tests/iconify/20-attributes.test.js
Normal file
88
packages/react/tests/iconify/20-attributes.test.js
Normal file
@ -0,0 +1,88 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body:
|
||||
'<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Passing attributes', () => {
|
||||
test('title', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} title="Icon!" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.title).toStrictEqual('Icon!');
|
||||
});
|
||||
|
||||
test('aria-hidden', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} aria-hidden="false" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props['aria-hidden']).toStrictEqual(void 0);
|
||||
});
|
||||
|
||||
test('ariaHidden', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} ariaHidden="false" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props['aria-hidden']).toStrictEqual(void 0);
|
||||
});
|
||||
|
||||
test('style', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon
|
||||
icon={iconData}
|
||||
style={{ verticalAlign: '0', color: 'red' }}
|
||||
/>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style).toMatchObject({
|
||||
verticalAlign: '0',
|
||||
color: 'red',
|
||||
});
|
||||
});
|
||||
|
||||
test('color', () => {
|
||||
const component = renderer.create(<Icon icon={iconData} color="red" />);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style).toMatchObject({
|
||||
color: 'red',
|
||||
});
|
||||
});
|
||||
|
||||
test('color with style', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} color="red" style={{ color: 'green' }} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style).toMatchObject({
|
||||
color: 'red',
|
||||
});
|
||||
});
|
||||
|
||||
test('attributes that cannot change', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon
|
||||
icon={iconData}
|
||||
viewBox="0 0 0 0"
|
||||
preserveAspectRatio="none"
|
||||
/>
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.viewBox).toStrictEqual('0 0 24 24');
|
||||
expect(tree.props.preserveAspectRatio).toStrictEqual('xMidYMid meet');
|
||||
});
|
||||
});
|
42
packages/react/tests/iconify/20-dimensions.test.js
Normal file
42
packages/react/tests/iconify/20-dimensions.test.js
Normal file
@ -0,0 +1,42 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body:
|
||||
'<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Dimensions', () => {
|
||||
test('height', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} height="48" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual('48');
|
||||
expect(tree.props.width).toStrictEqual('48');
|
||||
});
|
||||
|
||||
test('width and height', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} width={32} height="48" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual('48');
|
||||
expect(tree.props.width).toStrictEqual('32');
|
||||
});
|
||||
|
||||
test('auto', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} height="auto" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.height).toStrictEqual('24');
|
||||
expect(tree.props.width).toStrictEqual('24');
|
||||
});
|
||||
});
|
57
packages/react/tests/iconify/20-ids.test.js
Normal file
57
packages/react/tests/iconify/20-ids.test.js
Normal file
@ -0,0 +1,57 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconDataWithID = {
|
||||
body:
|
||||
'<defs><path id="ssvg-id-1st-place-medala" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medald" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalf" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalh" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalj" d="M.93.01h120.55v58.36H.93z"/><path id="ssvg-id-1st-place-medalm" d="M.93.01h120.55v58.36H.93z"/><path d="M52.849 78.373v-3.908c3.681-.359 6.25-.958 7.703-1.798c1.454-.84 2.54-2.828 3.257-5.962h4.021v40.385h-5.437V78.373h-9.544z" id="ssvg-id-1st-place-medalp"/><linearGradient x1="49.998%" y1="-13.249%" x2="49.998%" y2="90.002%" id="ssvg-id-1st-place-medalb"><stop stop-color="#1E88E5" offset="13.55%"/><stop stop-color="#1565C0" offset="93.8%"/></linearGradient><linearGradient x1="26.648%" y1="2.735%" x2="77.654%" y2="105.978%" id="ssvg-id-1st-place-medalk"><stop stop-color="#64B5F6" offset="13.55%"/><stop stop-color="#2196F3" offset="94.62%"/></linearGradient><radialGradient cx="22.368%" cy="12.5%" fx="22.368%" fy="12.5%" r="95.496%" id="ssvg-id-1st-place-medalo"><stop stop-color="#FFEB3B" offset="29.72%"/><stop stop-color="#FBC02D" offset="95.44%"/></radialGradient></defs><g fill="none" fill-rule="evenodd"><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medalc" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medala"/></mask><path fill="url(#ssvg-id-1st-place-medalb)" fill-rule="nonzero" mask="url(#ssvg-id-1st-place-medalc)" d="M45.44 42.18h31.43l30-48.43H75.44z"/></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medale" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medald"/></mask><g opacity=".2" mask="url(#ssvg-id-1st-place-medale)" fill="#424242" fill-rule="nonzero"><path d="M101.23-3L75.2 39H50.85L77.11-3h24.12zm5.64-3H75.44l-30 48h31.42l30.01-48z"/></g></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medalg" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalf"/></mask><path d="M79 30H43c-4.42 0-8 3.58-8 8v16.04c0 2.17 1.8 3.95 4.02 3.96h.01c2.23-.01 4.97-1.75 4.97-3.96V44c0-1.1.9-2 2-2h30c1.1 0 2 .9 2 2v9.93c0 1.98 2.35 3.68 4.22 4.04c.26.05.52.08.78.08c2.21 0 4-1.79 4-4V38c0-4.42-3.58-8-8-8z" fill="#FDD835" fill-rule="nonzero" mask="url(#ssvg-id-1st-place-medalg)"/></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medali" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalh"/></mask><g opacity=".2" mask="url(#ssvg-id-1st-place-medali)" fill="#424242" fill-rule="nonzero"><path d="M79 32c3.31 0 6 2.69 6 6v16.04A2.006 2.006 0 0 1 82.59 56c-1.18-.23-2.59-1.35-2.59-2.07V44c0-2.21-1.79-4-4-4H46c-2.21 0-4 1.79-4 4v10.04c0 .88-1.64 1.96-2.97 1.96c-1.12-.01-2.03-.89-2.03-1.96V38c0-3.31 2.69-6 6-6h36zm0-2H43c-4.42 0-8 3.58-8 8v16.04c0 2.17 1.8 3.95 4.02 3.96h.01c2.23-.01 4.97-1.75 4.97-3.96V44c0-1.1.9-2 2-2h30c1.1 0 2 .9 2 2v9.93c0 1.98 2.35 3.68 4.22 4.04c.26.05.52.08.78.08c2.21 0 4-1.79 4-4V38c0-4.42-3.58-8-8-8z"/></g></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medall" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalj"/></mask><path fill="url(#ssvg-id-1st-place-medalk)" fill-rule="nonzero" mask="url(#ssvg-id-1st-place-medall)" d="M76.87 42.18H45.44l-30-48.43h31.43z"/></g><g transform="translate(3 4)"><mask id="ssvg-id-1st-place-medaln" fill="#fff"><use xlink:href="#ssvg-id-1st-place-medalm"/></mask><g opacity=".2" mask="url(#ssvg-id-1st-place-medaln)" fill="#424242" fill-rule="nonzero"><path d="M45.1-3l26.35 42H47.1L20.86-3H45.1zm1.77-3H15.44l30 48h31.42L46.87-6z"/></g></g><circle fill="url(#ssvg-id-1st-place-medalo)" fill-rule="nonzero" cx="64" cy="86" r="38"/><path d="M64 51c19.3 0 35 15.7 35 35s-15.7 35-35 35s-35-15.7-35-35s15.7-35 35-35zm0-3c-20.99 0-38 17.01-38 38s17.01 38 38 38s38-17.01 38-38s-17.01-38-38-38z" opacity=".2" fill="#424242" fill-rule="nonzero"/><path d="M47.3 63.59h33.4v44.4H47.3z"/><use fill="#000" xlink:href="#ssvg-id-1st-place-medalp"/><use fill="#FFA000" xlink:href="#ssvg-id-1st-place-medalp"/></g>',
|
||||
width: 128,
|
||||
height: 128,
|
||||
};
|
||||
|
||||
describe('Replacing IDs', () => {
|
||||
test('default behavior', () => {
|
||||
const component = renderer.create(<Icon icon={iconDataWithID} />);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconDataWithID.body);
|
||||
});
|
||||
|
||||
test('custom generator', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconDataWithID} id="test" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
// Generate expected body
|
||||
let expected = iconDataWithID.body;
|
||||
const replacements = {
|
||||
'ssvg-id-1st-place-medala': 'test-0',
|
||||
'ssvg-id-1st-place-medald': 'test-1',
|
||||
'ssvg-id-1st-place-medalf': 'test-2',
|
||||
'ssvg-id-1st-place-medalh': 'test-3',
|
||||
'ssvg-id-1st-place-medalj': 'test-4',
|
||||
'ssvg-id-1st-place-medalm': 'test-5',
|
||||
'ssvg-id-1st-place-medalp': 'test-6',
|
||||
'ssvg-id-1st-place-medalb': 'test-7',
|
||||
'ssvg-id-1st-place-medalk': 'test-8',
|
||||
'ssvg-id-1st-place-medalo': 'test-9',
|
||||
'ssvg-id-1st-place-medalc': 'test-10',
|
||||
'ssvg-id-1st-place-medale': 'test-11',
|
||||
'ssvg-id-1st-place-medalg': 'test-12',
|
||||
'ssvg-id-1st-place-medali': 'test-13',
|
||||
'ssvg-id-1st-place-medall': 'test-14',
|
||||
'ssvg-id-1st-place-medaln': 'test-15',
|
||||
};
|
||||
Object.keys(replacements).forEach((search) => {
|
||||
expected = expected.replace(
|
||||
new RegExp(search, 'g'),
|
||||
replacements[search]
|
||||
);
|
||||
});
|
||||
|
||||
expect(body).toStrictEqual(expected);
|
||||
});
|
||||
});
|
31
packages/react/tests/iconify/20-inline.test.js
Normal file
31
packages/react/tests/iconify/20-inline.test.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import { Icon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body:
|
||||
'<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Inline attribute', () => {
|
||||
test('string', () => {
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} inline="true" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style.verticalAlign).toStrictEqual('-0.125em');
|
||||
});
|
||||
|
||||
test('false string', () => {
|
||||
// "false" = true
|
||||
const component = renderer.create(
|
||||
<Icon icon={iconData} inline="false" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.style.verticalAlign).toStrictEqual('-0.125em');
|
||||
});
|
||||
});
|
135
packages/react/tests/iconify/20-transformations.test.js
Normal file
135
packages/react/tests/iconify/20-transformations.test.js
Normal file
@ -0,0 +1,135 @@
|
||||
import React from 'react';
|
||||
import { InlineIcon } from '../../dist/iconify';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body:
|
||||
'<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Rotation', () => {
|
||||
test('number', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} rotate={1} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('rotate(90 ');
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} rotate="180deg" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('rotate(180 ');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Flip', () => {
|
||||
test('boolean', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} hFlip={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(-1 1)');
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} flip="vertical" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(1 -1)');
|
||||
});
|
||||
|
||||
test('string and boolean', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} flip="horizontal" vFlip={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
// horizontal + vertical = 180deg rotation
|
||||
expect(body).toMatch('rotate(180 ');
|
||||
});
|
||||
|
||||
test('string for boolean attribute', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} hFlip="true" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(-1 1)');
|
||||
});
|
||||
|
||||
test('shorthand and boolean', () => {
|
||||
// 'flip' is processed after 'hFlip', overwriting value
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} flip="horizontal" hFlip={false} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
expect(body).toMatch('scale(-1 1)');
|
||||
});
|
||||
|
||||
test('shorthand and boolean as string', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} flip="vertical" hFlip="true" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toStrictEqual(iconData.body);
|
||||
// horizontal + vertical = 180deg rotation
|
||||
expect(body).toMatch('rotate(180 ');
|
||||
});
|
||||
|
||||
test('wrong case', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} vflip={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
const body = tree.props.dangerouslySetInnerHTML.__html;
|
||||
|
||||
expect(body).not.toMatch('scale(');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Alignment and slice', () => {
|
||||
test('vAlign and slice', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} vAlign="top" slice={true} />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.preserveAspectRatio).toStrictEqual('xMidYMin slice');
|
||||
});
|
||||
|
||||
test('string', () => {
|
||||
const component = renderer.create(
|
||||
<InlineIcon icon={iconData} align="left bottom" />
|
||||
);
|
||||
const tree = component.toJSON();
|
||||
|
||||
expect(tree.props.preserveAspectRatio).toStrictEqual('xMinYMax meet');
|
||||
});
|
||||
});
|
@ -1,14 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/offline';
|
||||
import { Icon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
body:
|
||||
'<path d="M4 19h16v2H4zm5-4h11v2H9zm-5-4h16v2H4zm0-8h16v2H4zm5 4h11v2H9z" fill="currentColor"/>',
|
||||
width: 24,
|
||||
height: 24,
|
||||
};
|
||||
|
||||
describe('Empty icon', () => {
|
||||
test('basic test', () => {
|
||||
const component = renderer.create(<Icon />);
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/offline';
|
||||
import { Icon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Icon, InlineIcon } from '../../dist/offline';
|
||||
import { InlineIcon } from '../../dist/offline';
|
||||
import renderer from 'react-test-renderer';
|
||||
|
||||
const iconData = {
|
||||
|
Loading…
Reference in New Issue
Block a user