diff --git a/packages/redux-devtools-ui/package.json b/packages/redux-devtools-ui/package.json index fff0bf8f..8a57517c 100644 --- a/packages/redux-devtools-ui/package.json +++ b/packages/redux-devtools-ui/package.json @@ -42,13 +42,15 @@ }, "dependencies": { "@babel/runtime": "^7.28.4", + "@codemirror/lang-javascript": "^6.2.4", + "@codemirror/view": "^6.39.7", "@rjsf/core": "^6.1.2", "@rjsf/utils": "^6.1.2", "@rjsf/validator-ajv8": "^6.1.2", "@types/codemirror": "^5.60.17", "@types/json-schema": "^7.0.15", "@types/simple-element-resize-detector": "^1.3.3", - "codemirror": "^5.65.20", + "@uiw/react-codemirror": "^4.25.4", "color": "^5.0.3", "react-base16-styling": "workspace:^", "react-icons": "^5.5.0", @@ -75,6 +77,7 @@ "@types/jest": "^30.0.0", "@types/react": "^19.2.7", "babel-loader": "^10.0.0", + "codemirror": "^6.0.2", "csstype": "^3.2.3", "jest": "^30.2.0", "jest-environment-jsdom": "^30.2.0", diff --git a/packages/redux-devtools-ui/src/Editor/Editor.stories.tsx b/packages/redux-devtools-ui/src/Editor/Editor.stories.tsx index e453b302..3471464c 100644 --- a/packages/redux-devtools-ui/src/Editor/Editor.stories.tsx +++ b/packages/redux-devtools-ui/src/Editor/Editor.stories.tsx @@ -24,14 +24,12 @@ export const Default: Story = { args: { value, lineNumbers: true, - lineWrapping: false, foldGutter: true, readOnly: false, autofocus: true, }, argTypes: { autofocus: { control: { disable: true } }, - mode: { control: { disable: true } }, theme: { control: { disable: true } }, onChange: { control: { disable: true } }, }, @@ -45,8 +43,6 @@ export const WithTabs: StoryObj = { }, argTypes: { value: { control: { disable: true } }, - mode: { control: { disable: true } }, - lineWrapping: { control: { disable: true } }, readOnly: { control: { disable: true } }, theme: { control: { disable: true } }, foldGutter: { control: { disable: true } }, diff --git a/packages/redux-devtools-ui/src/Editor/Editor.tsx b/packages/redux-devtools-ui/src/Editor/Editor.tsx index 1e2b9b46..86e7a60f 100644 --- a/packages/redux-devtools-ui/src/Editor/Editor.tsx +++ b/packages/redux-devtools-ui/src/Editor/Editor.tsx @@ -1,18 +1,13 @@ -import React, { Component } from 'react'; +import React from 'react'; import styled from '@emotion/styled'; -import CodeMirror, { EditorChange } from 'codemirror'; +import CodeMirror from '@uiw/react-codemirror'; +import { javascript } from '@codemirror/lang-javascript'; import type { Base16Theme } from 'react-base16-styling'; import { defaultStyle, themedStyle } from './styles'; import { Theme } from '../themes/default'; - -import 'codemirror/mode/javascript/javascript'; -import 'codemirror/addon/fold/foldgutter'; -import 'codemirror/addon/fold/foldcode'; -import 'codemirror/addon/fold/brace-fold'; +import type { ViewUpdate } from '@codemirror/view'; import '../../fonts/index.css'; -import 'codemirror/lib/codemirror.css'; -import 'codemirror/addon/fold/foldgutter.css'; const EditorContainer = styled.div( '' as unknown as TemplateStringsArray, @@ -23,86 +18,34 @@ const EditorContainer = styled.div( ); export interface EditorProps { - value: string; - mode: string; - lineNumbers: boolean; - lineWrapping: boolean; - readOnly: boolean; + value?: string; + lineNumbers?: boolean; + readOnly?: boolean; theme?: Base16Theme; - foldGutter: boolean; - autofocus: boolean; - onChange?: (value: string, change: EditorChange) => void; + foldGutter?: boolean; + autofocus?: boolean; + onChange?: (value: string, viewUpdate: ViewUpdate) => void; } -/** - * Based on [CodeMirror](http://codemirror.net/). - */ -export default class Editor extends Component { - cm?: CodeMirror.Editor | null; - node?: HTMLDivElement | null; - - componentDidMount() { - this.cm = CodeMirror(this.node!, { - value: this.props.value, - mode: this.props.mode, - lineNumbers: this.props.lineNumbers, - lineWrapping: this.props.lineWrapping, - readOnly: this.props.readOnly, - autofocus: this.props.autofocus, - foldGutter: this.props.foldGutter, - gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'], - }); - - if (this.props.onChange) { - this.cm.on('change', (doc, change) => { - this.props.onChange!(doc.getValue(), change); - }); - } - } - - UNSAFE_componentWillReceiveProps(nextProps: EditorProps) { - if (nextProps.value !== this.cm!.getValue()) { - this.cm!.setValue(nextProps.value); - } - if (nextProps.readOnly !== this.props.readOnly) { - this.cm!.setOption('readOnly', nextProps.readOnly); - } - if (nextProps.lineNumbers !== this.props.lineNumbers) { - this.cm!.setOption('lineNumbers', nextProps.lineNumbers); - } - if (nextProps.lineWrapping !== this.props.lineWrapping) { - this.cm!.setOption('lineWrapping', nextProps.lineWrapping); - } - if (nextProps.foldGutter !== this.props.foldGutter) { - this.cm!.setOption('foldGutter', nextProps.foldGutter); - } - } - - shouldComponentUpdate() { - return false; - } - - componentWillUnmount() { - const node = this.node!; - node.removeChild(node.children[0]); - this.cm = null; - } - - getRef: React.RefCallback = (node) => { - this.node = node; - }; - - render() { - return ; - } - - static defaultProps = { - value: '', - mode: 'javascript', - lineNumbers: true, - lineWrapping: false, - readOnly: false, - foldGutter: true, - autofocus: false, - }; +export default function Editor({ + value = '', + lineNumbers = true, + readOnly = false, + foldGutter = true, + autofocus = false, + onChange, +}: EditorProps) { + return ( + + ); } diff --git a/packages/redux-devtools-ui/test/Editor.test.tsx b/packages/redux-devtools-ui/test/Editor.test.tsx index 82269b85..5f717bae 100644 --- a/packages/redux-devtools-ui/test/Editor.test.tsx +++ b/packages/redux-devtools-ui/test/Editor.test.tsx @@ -1,40 +1,11 @@ import React from 'react'; import { render } from '@testing-library/react'; import { Editor } from '../src'; -import 'codemirror/mode/javascript/javascript'; describe('Editor', function () { - const getBoundingClientRect = jest.fn(); - const getClientRects = jest.fn(); - - // See https://github.com/jsdom/jsdom/issues/3002 - document.createRange = () => { - const range = new Range(); - - range.getBoundingClientRect = getBoundingClientRect; - - range.getClientRects = () => { - getClientRects(); - return { - item: () => null, - length: 0, - [Symbol.iterator]: jest.fn(), - }; - }; - - return range; - }; const { container } = render(); it('renders correctly', () => { expect(container.firstChild).toMatchSnapshot(); }); - - it('calls getBoundingClientRect', () => { - expect(getBoundingClientRect).toHaveBeenCalled(); - }); - - it('calls getClientRects', () => { - expect(getClientRects).toHaveBeenCalled(); - }); }); diff --git a/packages/redux-devtools-ui/test/__snapshots__/Editor.test.tsx.snap b/packages/redux-devtools-ui/test/__snapshots__/Editor.test.tsx.snap index 30b18b8f..8b5855f4 100644 --- a/packages/redux-devtools-ui/test/__snapshots__/Editor.test.tsx.snap +++ b/packages/redux-devtools-ui/test/__snapshots__/Editor.test.tsx.snap @@ -2,137 +2,105 @@ exports[`Editor renders correctly 1`] = `
-