Skip to content

Commit

Permalink
fix: Add support for React 18 (#265)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaeltaranto committed Dec 8, 2022
1 parent d1d99a8 commit b846abb
Show file tree
Hide file tree
Showing 18 changed files with 940 additions and 178 deletions.
12 changes: 8 additions & 4 deletions cypress/integration/smoke.js
@@ -1,4 +1,8 @@
import { getFirstFrame, loadPlayroom } from '../support/utils';
import {
assertPreviewContains,
getFirstFrame,
loadPlayroom,
} from '../support/utils';

describe('Smoke', () => {
it('frames are interactive', () => {
Expand All @@ -9,8 +13,8 @@ describe('Smoke', () => {
it('preview mode loads correctly', () => {
cy.visit(
'http://localhost:9000/preview#?code=N4Igxg9gJgpiBcIA8AxCEB8r1YEIEMAnAei2LUyXJxAF8g'
)
.get('body')
.then((el) => expect(el.get(0).innerText).to.eq('Foo\nFoo\nBar'));
);

assertPreviewContains('Foo\nFoo\nBar');
});
});
11 changes: 8 additions & 3 deletions cypress/support/utils.js
Expand Up @@ -114,9 +114,14 @@ export const assertFramesMatch = (matches) =>
});

export const assertPreviewContains = (text) =>
cy.get('body').then((el) => {
expect(el.get(0).innerText).to.eq(text);
});
cy
.then(() => {
cy.get('[data-testid="splashscreen"]').should('not.be.visible');
})
.get('body')
.then((el) => {
expect(el.get(0).innerText).to.eq(text);
});

export const loadPlayroom = () =>
cy
Expand Down
27 changes: 27 additions & 0 deletions lib/makeWebpackConfig.js
@@ -1,3 +1,4 @@
const fs = require('fs');
const path = require('path');
const webpack = require('webpack');
const { merge } = require('webpack-merge');
Expand All @@ -18,6 +19,22 @@ module.exports = async (playroomConfig, options) => {
const relativeResolve = (requirePath) =>
require.resolve(requirePath, { paths: [playroomConfig.cwd] });

let isLegacyReact = true;

try {
// eslint-disable-next-line no-sync
const pkgContents = fs.readFileSync(
relativeResolve('react-dom/package.json'),
{
encoding: 'utf-8',
}
);
const { version } = JSON.parse(pkgContents);
isLegacyReact = !(version.startsWith('18') || version.startsWith('0.0.0'));
} catch (e) {
throw new Error('Unable to read `react-dom` package json');
}

const staticTypes = await getStaticTypes(playroomConfig);

const ourConfig = {
Expand Down Expand Up @@ -158,6 +175,16 @@ module.exports = async (playroomConfig, options) => {
new VanillaExtractPlugin(),
new MiniCssExtractPlugin({ ignoreOrder: true }),
...(options.production ? [] : [new FriendlyErrorsWebpackPlugin()]),
// If using a version of React earlier than 18, ignore the
// react-dom/client import. This hack can be removed when
// support for older versions of React is removed.
...(isLegacyReact
? [
new webpack.IgnorePlugin({
resourceRegExp: /react-dom\/client$/,
}),
]
: []),
],
devtool: !options.production && 'eval-source-map',
};
Expand Down
17 changes: 8 additions & 9 deletions package.json
Expand Up @@ -75,8 +75,8 @@
"@types/lodash": "^4.14.168",
"@types/lz-string": "^1.3.34",
"@types/prettier": "^2.2.3",
"@types/react": "^17.0.3",
"@types/react-dom": "^17.0.2",
"@types/react": "^18.0.9",
"@types/react-dom": "^18.0.4",
"@vanilla-extract/babel-plugin": "^1.1.5",
"@vanilla-extract/css": "^1.7.0",
"@vanilla-extract/css-utils": "^0.1.2",
Expand Down Expand Up @@ -108,10 +108,9 @@
"prettier": "^2.2.1",
"prop-types": "^15.7.2",
"query-string": "^6.14.1",
"re-resizable": "^6.9.0",
"react-codemirror2": "^7.2.1",
"re-resizable": "^6.9.6",
"react-docgen-typescript": "^2.1.0",
"react-use": "^17.2.1",
"react-use": "^17.4.0",
"read-pkg-up": "^7.0.1",
"scope-eval": "^1.0.0",
"typescript": "^4.3.2",
Expand All @@ -135,16 +134,16 @@
"husky": "^4.3.8",
"jest": "^26.6.3",
"lint-staged": "^10.5.4",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react": "^18.0.1",
"react-dom": "^18.0.1",
"semantic-release": "^17.4.2",
"serve": "^11.3.2",
"start-server-and-test": "^1.12.0",
"surge": "^0.22.1"
},
"peerDependencies": {
"react": "^16.8 || ^17.0",
"react-dom": "^16.8 || ^17.0"
"react": "^16.8 || ^17 || ^18",
"react-dom": "^16.8 || ^17 || ^18"
},
"volta": {
"node": "12.22.12",
Expand Down
28 changes: 8 additions & 20 deletions src/Playroom/CodeEditor/CodeEditor.tsx
@@ -1,6 +1,6 @@
import React, { useRef, useContext, useEffect, useCallback } from 'react';
import { useDebouncedCallback } from 'use-debounce';
import { Editor } from 'codemirror';
import CodeMirror, { Editor } from 'codemirror';
import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/neo.css';

Expand All @@ -10,7 +10,7 @@ import { compileJsx } from '../../utils/compileJsx';

import * as styles from './CodeEditor.css';

import { UnControlled as ReactCodeMirror } from 'react-codemirror2';
import { UnControlled as ReactCodeMirror } from './CodeMirror2';
import 'codemirror/mode/jsx/jsx';
import 'codemirror/addon/edit/closetag';
import 'codemirror/addon/edit/closebrackets';
Expand All @@ -21,36 +21,27 @@ import 'codemirror/addon/fold/foldcode';
import 'codemirror/addon/fold/foldgutter';
import 'codemirror/addon/fold/brace-fold';

const completeAfter = (cm: Editor, predicate: () => boolean) => {
const CodeMirror = cm.constructor;
const completeAfter = (cm: Editor, predicate?: () => boolean) => {
if (!predicate || predicate()) {
setTimeout(() => {
if (!cm.state.completionActive) {
// @ts-ignore
cm.showHint({ completeSingle: false });
}
}, 100);
}

// @ts-ignore
return CodeMirror.Pass;
};

const completeIfAfterLt = (cm: Editor) => {
const CodeMirror = cm.constructor;

return completeAfter(cm, () => {
const completeIfAfterLt = (cm: Editor) =>
completeAfter(cm, () => {
const cur = cm.getCursor();
// @ts-ignore
// eslint-disable-next-line new-cap
return cm.getRange(CodeMirror.Pos(cur.line, cur.ch - 1), cur) === '<';
});
};

const completeIfInTag = (cm: Editor) => {
const CodeMirror = cm.constructor;

return completeAfter(cm, () => {
const completeIfInTag = (cm: Editor) =>
completeAfter(cm, () => {
const tok = cm.getTokenAt(cm.getCursor());
if (
tok.type === 'string' &&
Expand All @@ -59,11 +50,9 @@ const completeIfInTag = (cm: Editor) => {
) {
return false;
}
// @ts-ignore
const inner = CodeMirror.innerMode(cm.getMode(), tok.state).state;
return inner.tagName;
});
};

const validateCode = (editorInstance: Editor, code: string) => {
editorInstance.clearGutter('errorGutter');
Expand Down Expand Up @@ -228,7 +217,6 @@ export const CodeEditor = ({ code, onChange, previewCode, hints }: Props) => {
}, [highlightLineNumber]);

return (
// @ts-ignore
<ReactCodeMirror
editorDidMount={(editorInstance) => {
editorInstanceRef.current = editorInstance;
Expand Down Expand Up @@ -259,6 +247,7 @@ export const CodeEditor = ({ code, onChange, previewCode, hints }: Props) => {
autoCloseBrackets: true,
theme: 'neo',
gutters: ['errorGutter', 'CodeMirror-linenumbers', styles.foldGutter],
// @ts-expect-error
hintOptions: { schemaInfo: hints },
viewportMargin: 50,
lineNumbers: true,
Expand All @@ -275,7 +264,6 @@ export const CodeEditor = ({ code, onChange, previewCode, hints }: Props) => {
extraKeys: {
Tab: (cm) => {
if (cm.somethingSelected()) {
// @ts-ignore
cm.indentSelection('add');
} else {
const indent = cm.getOption('indentUnit') as number;
Expand Down

0 comments on commit b846abb

Please sign in to comment.