chore: switch to react

This commit is contained in:
Miralem Drek
2019-04-23 10:49:37 +02:00
parent afa026eb2f
commit a2de631be5
25 changed files with 190 additions and 671 deletions

View File

@@ -9,11 +9,6 @@
"extends": [ "extends": [
"airbnb" "airbnb"
], ],
"settings": {
"react": {
"pragma": "preact"
}
},
"rules": { "rules": {
"max-len": 0, "max-len": 0,
"no-plusplus": 0, "no-plusplus": 0,

View File

@@ -5,7 +5,7 @@ module.exports = {
['@babel/preset-env', { targets: { node: 'current' } }], ['@babel/preset-env', { targets: { node: 'current' } }],
], ],
plugins: [ plugins: [
['@babel/plugin-transform-react-jsx', { pragma: 'preact.h' }], ['@babel/plugin-transform-react-jsx'],
[ [
'istanbul', 'istanbul',
{ {

View File

@@ -1,5 +1,6 @@
import preact from 'preact'; /* eslint object-property-newline:0 */
import render from 'preact-render-to-string'; import React from 'react';
import renderer from 'react-test-renderer';
import { AppSelections } from '../../src/components/AppSelections'; import { AppSelections } from '../../src/components/AppSelections';
@@ -60,17 +61,18 @@ describe('<AppSelections />', () => {
['**/Grid.jsx', () => Grid], ['**/Grid.jsx', () => Grid],
['**/Text.jsx', () => Button], ['**/Text.jsx', () => Button],
], ['../../src/components/AppSelections']); ], ['../../src/components/AppSelections']);
const html = render.render(<AS api={api} />); const r = renderer.create(<AS api={api} />);
expect(html).to.equal(`
<t> expect(r.toJSON()).to.eql({
<g> type: 't', props: {}, children: [{
<g> type: 'g', props: {}, children: [{
<b d>Back</b> type: 'g', props: {}, children: [
<b>Forward</b> { type: 'b', props: { d: true }, children: ['Back'] },
<b>Clear</b> { type: 'b', props: { d: false }, children: ['Forward'] },
</g> { type: 'b', props: { d: false }, children: ['Clear'] },
<g></g> ],
</g> }, { type: 'g', props: {}, children: null }],
</t>`.replace(/\n(\s+)/g, '')); }],
});
}); });
}); });

View File

@@ -1,34 +1,67 @@
import preact from 'preact'; import React from 'react';
import render from 'preact-render-to-string'; import renderer from 'react-test-renderer';
import looksLike from 'html-looks-like';
import Header from '../../src/components/Header'; import Header from '../../src/components/Header';
describe('<Header />', () => { describe('<Header />', () => {
it('should be empty when input is falsy', () => { it('should be empty when input is falsy', () => {
expect(render(<Header />)).to.equal(''); expect(renderer.create(<Header />).toJSON()).to.equal(null);
expect(render(<Header layout={{ showTitles: true }} />)).to.equal(''); expect(renderer.create(<Header layout={{ showTitles: true }} />).toJSON()).to.equal(null);
}); });
it('should render a title', () => { it('should render a title', () => {
const layout = { showTitles: true, title: 'foo' }; const layout = { showTitles: true, title: 'foo' };
const html = render(<Header layout={layout} />); const [{ default: MockedHeader }] = aw.mock([
looksLike(html, ` ['**/Text.jsx', () => ({ children, ...p }) => <span {...p}>{children}</span>],
<div> ], ['../../src/components/Header']);
<span>foo</span> const tree = renderer.create(<MockedHeader layout={layout} />).toJSON();
<span></span> expect(tree).to.eql({
</div> type: 'div',
`); props: {
style: { background: 'transparent', padding: '0 8px' },
},
children: [{
type: 'span',
props: { block: true, nowrap: true, size: 'large' },
children: ['foo'],
}, {
type: 'span',
props: {
faded: true,
block: true,
nowrap: true,
size: 'small',
},
children: null,
}],
});
}); });
it('should render a subtitle', () => { it('should render a subtitle', () => {
const layout = { showTitles: true, subtitle: 'foo' }; const layout = { showTitles: true, subtitle: 'foo' };
const html = render(<Header layout={layout} />); const [{ default: MockedHeader }] = aw.mock([
looksLike(html, ` ['**/Text.jsx', () => ({ children, ...p }) => <span {...p}>{children}</span>],
<div> ], ['../../src/components/Header']);
<span></span> const tree = renderer.create(<MockedHeader layout={layout} />).toJSON();
<span>foo</span> expect(tree).to.eql({
</div> type: 'div',
`); props: {
style: { background: 'transparent', padding: '0 8px' },
},
children: [{
type: 'span',
props: { block: true, nowrap: true, size: 'large' },
children: null,
}, {
type: 'span',
props: {
faded: true,
block: true,
nowrap: true,
size: 'small',
},
children: ['foo'],
}],
});
}); });
}); });

View File

@@ -1,5 +1,5 @@
import preact from 'preact'; import React from 'react';
import render from 'preact-render-to-string'; import renderer from 'react-test-renderer';
import SelectionToolbar from '../../src/components/SelectionToolbar'; import SelectionToolbar from '../../src/components/SelectionToolbar';
@@ -25,7 +25,13 @@ describe('<SelectionToolbar />', () => {
selectionToolbar: { items: [{ key: 'mine', type: 'random' }] }, selectionToolbar: { items: [{ key: 'mine', type: 'random' }] },
}, },
}; };
st = new SelectionToolbar(props); const STItem = () => '';
const styled = () => ['classes'];
const [{ default: STB }] = aw.mock([
['**/SelectionToolbarItem.jsx', () => STItem],
['**/styled.js', () => styled],
], ['../../src/components/SelectionToolbar']);
st = new STB(props);
}); });
it('should have a confirm item', () => { it('should have a confirm item', () => {
@@ -108,13 +114,17 @@ describe('<SelectionToolbar />', () => {
selectionToolbar: { items: [{ key: 'mine' }] }, selectionToolbar: { items: [{ key: 'mine' }] },
}, },
}; };
const STItem = ({ key, isCustom }) => `-${key}:${isCustom}-`; const STItem = ({ isCustom }) => `-${isCustom}-`;
const styled = () => ['a']; const styled = () => ['a'];
const [{ default: STB }] = aw.mock([ const [{ default: STB }] = aw.mock([
['**/SelectionToolbarItem.jsx', () => STItem], ['**/SelectionToolbarItem.jsx', () => STItem],
['**/styled.js', () => styled], ['**/styled.js', () => styled],
], ['../../src/components/SelectionToolbar']); ], ['../../src/components/SelectionToolbar']);
const html = render.render(<STB sn={props.sn} />); const c = renderer.create(<STB sn={props.sn} />);
expect(html).to.equal('<div class="a">-mine:true--clear:false--cancel:false--confirm:false-</div>'); expect(c.toJSON()).to.eql({
type: 'div',
props: { className: 'a' },
children: ['-true-', '-false-', '-false-', '-false-'],
});
}); });
}); });

View File

@@ -22,9 +22,10 @@
"devDependencies": { "devDependencies": {
"@nebula.js/supernova": "^0.1.0", "@nebula.js/supernova": "^0.1.0",
"@nebula.js/ui": "^0.1.0", "@nebula.js/ui": "^0.1.0",
"html-looks-like": "^1.0.3",
"node-event-emitter": "^0.0.1", "node-event-emitter": "^0.0.1",
"preact": "^8.4.2", "react": "^16.8.6",
"preact-render-to-string": "^4.1.0" "react-dom": "^16.8.6",
"react-leonardo-ui": "^0.15.0",
"react-test-renderer": "^16.8.6"
} }
} }

View File

@@ -1,4 +1,5 @@
import preact from 'preact'; import React from 'react';
import ReactDOM from 'react-dom';
import SelectionsBack from '@nebula.js/ui/icons/SelectionsBack'; import SelectionsBack from '@nebula.js/ui/icons/SelectionsBack';
import SelectionsForward from '@nebula.js/ui/icons/SelectionsForward'; import SelectionsForward from '@nebula.js/ui/icons/SelectionsForward';
@@ -121,7 +122,7 @@ function MultiState({
); );
} }
export class AppSelections extends preact.Component { export class AppSelections extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -201,7 +202,7 @@ export default function mount({
element, element,
api, api,
}) { }) {
const reference = preact.render( ReactDOM.render(
<AppSelections <AppSelections
api={api} api={api}
/>, />,
@@ -209,7 +210,7 @@ export default function mount({
); );
const unmount = () => { const unmount = () => {
preact.render('', element, reference); ReactDOM.unmountComponentAtNode(element);
}; };
return () => { return () => {

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
import Grid from '@nebula.js/ui/components/Grid'; import Grid from '@nebula.js/ui/components/Grid';
import styled from '@nebula.js/ui/components/styled'; import styled from '@nebula.js/ui/components/styled';
@@ -42,7 +42,7 @@ const Content = ({ children }) => (
</div> </div>
); );
class Cell extends preact.Component { class Cell extends React.Component {
constructor(...args) { constructor(...args) {
super(...args); super(...args);
this.styledClasses = ['nebulajs', ...styled({ this.styledClasses = ['nebulajs', ...styled({
@@ -52,6 +52,7 @@ class Cell extends preact.Component {
fontFamily: '$fontFamily', fontFamily: '$fontFamily',
color: '$grey25', color: '$grey25',
})].join(' '); })].join(' ');
this.state = {};
} }
componentDidCatch() { componentDidCatch() {

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
import { prefixer } from '../utils/utils'; import { prefixer } from '../utils/utils';

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
import Text from '@nebula.js/ui/components/Text'; import Text from '@nebula.js/ui/components/Text';
import Grid from '@nebula.js/ui/components/Grid'; import Grid from '@nebula.js/ui/components/Grid';

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
import Text from '@nebula.js/ui/components/Text'; import Text from '@nebula.js/ui/components/Text';
const Header = ({ const Header = ({

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
const Component = () => ( const Component = () => (
<div>&nbsp;</div> <div>&nbsp;</div>

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
const Component = () => ( const Component = () => (
<div>More stuff required</div> <div>More stuff required</div>

View File

@@ -1,9 +1,9 @@
import preact from 'preact'; import React from 'react';
import styled from '@nebula.js/ui/components/styled'; import styled from '@nebula.js/ui/components/styled';
import Item from './SelectionToolbarItem'; import Item from './SelectionToolbarItem';
class Component extends preact.Component { class Component extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
const api = props.sn.component.selections; const api = props.sn.component.selections;
@@ -24,7 +24,7 @@ class Component extends preact.Component {
background: '$grey100', background: '$grey100',
display: 'flex', display: 'flex',
justifyContent: 'flex-end', justifyContent: 'flex-end',
}); }).join(' ');
const items = []; const items = [];

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
import ButtonInline from '@nebula.js/ui/components/ButtonInline'; import ButtonInline from '@nebula.js/ui/components/ButtonInline';
@@ -12,7 +12,7 @@ const ICONS = {
'clear-selections': ClearSelections, 'clear-selections': ClearSelections,
}; };
export default class Item extends preact.Component { export default class Item extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
const constrainElement = (el, d) => { const constrainElement = (el, d) => {
/* eslint-disable no-param-reassign */ /* eslint-disable no-param-reassign */
@@ -88,7 +88,7 @@ const scheduleRender = (props, prev, initial, contentElement) => {
return prom; return prom;
}; };
class Supernova extends preact.Component { class Supernova extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.initial = { this.initial = {

View File

@@ -1,11 +1,12 @@
import preact from 'preact'; import React from 'react';
import ReactDOM from 'react-dom';
import Cell from './Cell'; import Cell from './Cell';
export default function boot({ export default function boot({
element, element,
model, model,
}, props, config) { }, props, config) {
const reference = preact.render( ReactDOM.render(
<Cell <Cell
{...props} {...props}
model={model} model={model}
@@ -14,14 +15,14 @@ export default function boot({
); );
const unmount = () => { const unmount = () => {
preact.render('', element, reference); ReactDOM.unmountComponentAtNode(element);
}; };
const update = (p) => { const update = (p) => {
preact.render(<Cell ReactDOM.render(<Cell
{...p} {...p}
model={model} model={model}
/>, element, reference); />, element);
}; };
model.once('closed', unmount); model.once('closed', unmount);
@@ -31,6 +32,5 @@ export default function boot({
update(p); update(p);
}, },
unmount, unmount,
reference,
}); });
} }

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
import styled from './styled'; import styled from './styled';

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
import styled from './styled'; import styled from './styled';

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
import styled from './styled'; import styled from './styled';

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
import styled from './styled'; import styled from './styled';

View File

@@ -1,4 +1,4 @@
import preact from 'preact'; import React from 'react';
function getFontSize(size) { function getFontSize(size) {
if (size === 'large') { if (size === 'large') {

View File

@@ -8,6 +8,6 @@
"keywords": [], "keywords": [],
"scripts": {}, "scripts": {},
"devDependencies": { "devDependencies": {
"preact": "^8.4.2" "react": "^16.8.6"
} }
} }

View File

@@ -29,15 +29,23 @@ const browserList = [
]; ];
const GLOBALS = { const GLOBALS = {
react: 'React',
'react-dom': 'ReactDOM',
}; };
const EXTERNALS = [
'react',
'react-dom',
'react-leonardo-ui',
];
const config = (isEsm) => { const config = (isEsm) => {
const outputFile = isEsm ? pkg.module : pkg.main; const outputFile = isEsm ? pkg.module : pkg.main;
const basename = path.basename(outputFile); const basename = path.basename(outputFile);
const dir = path.dirname(outputFile); const dir = path.dirname(outputFile);
const umdName = basename.replace(/-([a-z])/g, (m, p1) => p1.toUpperCase()).split('.js').join(''); const umdName = basename.replace(/-([a-z])/g, (m, p1) => p1.toUpperCase()).split('.js').join('');
const external = isEsm ? Object.keys(pkg.dependencies || {}) : []; const external = [...EXTERNALS, ...(isEsm ? Object.keys(pkg.dependencies || {}) : [])];
const globals = {}; const globals = {};
external.forEach((e) => { external.forEach((e) => {
if ([GLOBALS[e]]) { if ([GLOBALS[e]]) {
@@ -76,7 +84,7 @@ const config = (isEsm) => {
}], }],
], ],
plugins: [ plugins: [
['@babel/plugin-transform-react-jsx', { pragma: 'preact.h' }], ['@babel/plugin-transform-react-jsx'],
], ],
}), }),
], ],

650
yarn.lock

File diff suppressed because it is too large Load Diff