mirror of
https://github.com/maputnik/editor.git
synced 2025-12-07 23:00:01 +00:00
Migration of jsx files to tsx 1 (#848)
In this PR I have changed some of the jsx files to tsx file. I'm starting off with the "leafs" so that migration of the rest will be easier, hopefully. What I'm basically doing is taking a jsx file, copy paste it into: https://mskelton.dev/ratchet And after that I'm fixing the types as needed. It's not a very long process. Hopefully more PRs will follow and this will be over soon. I don't plan to migrate the storybook as I generally don't understand why is it useful, I'll open an issue to see if anyone thinks differently.
This commit is contained in:
176
src/components/InputJson.tsx
Normal file
176
src/components/InputJson.tsx
Normal file
@@ -0,0 +1,176 @@
|
||||
import React from 'react'
|
||||
import classnames from 'classnames';
|
||||
import CodeMirror, { ModeSpec } from 'codemirror';
|
||||
|
||||
import 'codemirror/mode/javascript/javascript'
|
||||
import 'codemirror/addon/lint/lint'
|
||||
import 'codemirror/addon/edit/matchbrackets'
|
||||
import 'codemirror/lib/codemirror.css'
|
||||
import 'codemirror/addon/lint/lint.css'
|
||||
import stringifyPretty from 'json-stringify-pretty-compact'
|
||||
import '../util/codemirror-mgl';
|
||||
|
||||
|
||||
export type InputJsonProps = {
|
||||
layer: any
|
||||
maxHeight?: number
|
||||
onChange?(...args: unknown[]): unknown
|
||||
lineNumbers?: boolean
|
||||
lineWrapping?: boolean
|
||||
getValue(data: any): string
|
||||
gutters?: string[]
|
||||
className?: string
|
||||
onFocus?(...args: unknown[]): unknown
|
||||
onBlur?(...args: unknown[]): unknown
|
||||
onJSONValid?(...args: unknown[]): unknown
|
||||
onJSONInvalid?(...args: unknown[]): unknown
|
||||
mode?: ModeSpec<any>
|
||||
lint?: boolean | object
|
||||
};
|
||||
|
||||
type InputJsonState = {
|
||||
isEditing: boolean
|
||||
showMessage: boolean
|
||||
prevValue: string
|
||||
};
|
||||
|
||||
export default class InputJson extends React.Component<InputJsonProps, InputJsonState> {
|
||||
static defaultProps = {
|
||||
lineNumbers: true,
|
||||
lineWrapping: false,
|
||||
gutters: ["CodeMirror-lint-markers"],
|
||||
getValue: (data: any) => {
|
||||
return stringifyPretty(data, {indent: 2, maxLength: 40});
|
||||
},
|
||||
onFocus: () => {},
|
||||
onBlur: () => {},
|
||||
onJSONInvalid: () => {},
|
||||
onJSONValid: () => {},
|
||||
}
|
||||
_keyEvent: string;
|
||||
_doc: CodeMirror.Editor | undefined;
|
||||
_el: HTMLDivElement | null = null;
|
||||
_cancelNextChange: boolean = false;
|
||||
|
||||
constructor(props: InputJsonProps) {
|
||||
super(props);
|
||||
this._keyEvent = "keyboard";
|
||||
this.state = {
|
||||
isEditing: false,
|
||||
showMessage: false,
|
||||
prevValue: this.props.getValue(this.props.layer),
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this._doc = CodeMirror(this._el!, {
|
||||
value: this.props.getValue(this.props.layer),
|
||||
mode: this.props.mode || {
|
||||
name: "mgl",
|
||||
},
|
||||
lineWrapping: this.props.lineWrapping,
|
||||
tabSize: 2,
|
||||
theme: 'maputnik',
|
||||
viewportMargin: Infinity,
|
||||
lineNumbers: this.props.lineNumbers,
|
||||
lint: this.props.lint || {
|
||||
context: "layer"
|
||||
},
|
||||
matchBrackets: true,
|
||||
gutters: this.props.gutters,
|
||||
scrollbarStyle: "null",
|
||||
});
|
||||
|
||||
this._doc.on('change', this.onChange);
|
||||
this._doc.on('focus', this.onFocus);
|
||||
this._doc.on('blur', this.onBlur);
|
||||
}
|
||||
|
||||
onPointerDown = () => {
|
||||
this._keyEvent = "pointer";
|
||||
}
|
||||
|
||||
onFocus = () => {
|
||||
if (this.props.onFocus) this.props.onFocus();
|
||||
this.setState({
|
||||
isEditing: true,
|
||||
showMessage: (this._keyEvent === "keyboard"),
|
||||
});
|
||||
}
|
||||
|
||||
onBlur = () => {
|
||||
this._keyEvent = "keyboard";
|
||||
if (this.props.onBlur) this.props.onBlur();
|
||||
this.setState({
|
||||
isEditing: false,
|
||||
showMessage: false,
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnMount () {
|
||||
this._doc!.off('change', this.onChange);
|
||||
this._doc!.off('focus', this.onFocus);
|
||||
this._doc!.off('blur', this.onBlur);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: InputJsonProps) {
|
||||
if (!this.state.isEditing && prevProps.layer !== this.props.layer) {
|
||||
this._cancelNextChange = true;
|
||||
this._doc!.setValue(
|
||||
this.props.getValue(this.props.layer),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
onChange = (_e: unknown) => {
|
||||
if (this._cancelNextChange) {
|
||||
this._cancelNextChange = false;
|
||||
this.setState({
|
||||
prevValue: this._doc!.getValue(),
|
||||
})
|
||||
return;
|
||||
}
|
||||
const newCode = this._doc!.getValue();
|
||||
|
||||
if (this.state.prevValue !== newCode) {
|
||||
let parsedLayer, err;
|
||||
try {
|
||||
parsedLayer = JSON.parse(newCode);
|
||||
} catch(_err) {
|
||||
err = _err;
|
||||
console.warn(_err)
|
||||
}
|
||||
|
||||
if (err && this.props.onJSONInvalid) {
|
||||
this.props.onJSONInvalid();
|
||||
}
|
||||
else {
|
||||
if (this.props.onChange) this.props.onChange(parsedLayer)
|
||||
if (this.props.onJSONValid) this.props.onJSONValid();
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
prevValue: newCode,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {showMessage} = this.state;
|
||||
const style = {} as {maxHeight?: number};
|
||||
if (this.props.maxHeight) {
|
||||
style.maxHeight = this.props.maxHeight;
|
||||
}
|
||||
|
||||
return <div className="JSONEditor" onPointerDown={this.onPointerDown} aria-hidden="true">
|
||||
<div className={classnames("JSONEditor__message", {"JSONEditor__message--on": showMessage})}>
|
||||
Press <kbd>ESC</kbd> to lose focus
|
||||
</div>
|
||||
<div
|
||||
className={classnames("codemirror-container", this.props.className)}
|
||||
ref={(el) => this._el = el}
|
||||
style={style}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user