refactor(client): abstract RawTextArea for variable input (#2204)

This commit is contained in:
Junyi 2023-07-07 10:52:56 +07:00 committed by GitHub
parent 6496c65fc4
commit 6646007dd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 60 deletions

View File

@ -25,7 +25,7 @@ export const Json = React.forwardRef<typeof Input.TextArea, JSONTextAreaProps>(
{...props} {...props}
className={cx( className={cx(
css` css`
font-size: 90%; font-size: 80%;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
`, `,
props.className, props.className,

View File

@ -1,64 +1,8 @@
import React, { useRef, useState } from 'react'; import React from 'react';
import { Button } from 'antd';
import { css } from '@emotion/css';
import { cloneDeep } from 'lodash';
import { Input } from '../input'; import { Input } from '../input';
import { VariableSelect } from './VariableSelect'; import { RawTextArea } from './RawTextArea';
// NOTE: https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js/46012210#46012210
function setNativeInputValue(input, value) {
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(input.constructor.prototype, 'value')?.set;
nativeInputValueSetter?.call(input, value);
input.dispatchEvent(
new Event('input', {
bubbles: true,
}),
);
}
export function JSONInput(props) { export function JSONInput(props) {
const inputRef = useRef<any>(null); return <RawTextArea {...props} component={Input.JSON} />;
const { scope, changeOnSelect, ...others } = props;
const [options, setOptions] = useState(scope ? cloneDeep(scope) : []);
function onInsert(selected) {
if (!inputRef.current) {
return;
}
const variable = `{{${selected.join('.')}}}`;
const { textArea } = inputRef.current.resizableTextArea;
const nextValue =
textArea.value.slice(0, textArea.selectionStart) + variable + textArea.value.slice(textArea.selectionEnd);
const nextPos = [textArea.selectionStart, textArea.selectionStart + variable.length];
setNativeInputValue(textArea, nextValue);
textArea.setSelectionRange(...nextPos);
textArea.focus();
}
return (
<div
className={css`
position: relative;
.ant-input {
width: 100%;
}
`}
>
<Input.JSON {...others} ref={inputRef} />
<Button.Group
className={css`
position: absolute;
right: 0;
top: 0;
.ant-btn-sm {
font-size: 85%;
}
`}
>
<VariableSelect options={options} setOptions={setOptions} onInsert={onInsert} changeOnSelect={changeOnSelect} />
</Button.Group>
</div>
);
} }

View File

@ -0,0 +1,63 @@
import React, { useRef, useState } from 'react';
import { css } from '@emotion/css';
import { Button, Input } from 'antd';
import { cloneDeep } from 'lodash';
import { VariableSelect } from './VariableSelect';
// NOTE: https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js/46012210#46012210
function setNativeInputValue(input, value) {
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(input.constructor.prototype, 'value')?.set;
nativeInputValueSetter?.call(input, value);
input.dispatchEvent(
new Event('input', {
bubbles: true,
}),
);
}
export function RawTextArea(props): JSX.Element {
const inputRef = useRef<any>(null);
const { scope, changeOnSelect, component: Component = Input.TextArea, ...others } = props;
const [options, setOptions] = useState(scope ? cloneDeep(scope) : []);
function onInsert(selected) {
if (!inputRef.current) {
return;
}
const variable = `{{${selected.join('.')}}}`;
const { textArea } = inputRef.current.resizableTextArea;
const nextValue =
textArea.value.slice(0, textArea.selectionStart) + variable + textArea.value.slice(textArea.selectionEnd);
const nextPos = [textArea.selectionStart, textArea.selectionStart + variable.length];
setNativeInputValue(textArea, nextValue);
textArea.setSelectionRange(...nextPos);
textArea.focus();
}
return (
<div
className={css`
position: relative;
.ant-input {
width: 100%;
}
`}
>
<Component {...others} ref={inputRef} />
<Button.Group
className={css`
position: absolute;
right: 0;
top: 0;
.ant-btn-sm {
font-size: 85%;
}
`}
>
<VariableSelect options={options} setOptions={setOptions} onInsert={onInsert} changeOnSelect={changeOnSelect} />
</Button.Group>
</div>
);
}

View File

@ -3,6 +3,7 @@ import { connect, mapReadPretty } from '@formily/react';
import { IField } from '../../../collection-manager'; import { IField } from '../../../collection-manager';
import { Input } from './Input'; import { Input } from './Input';
import { JSONInput } from './JSONInput'; import { JSONInput } from './JSONInput';
import { RawTextArea } from './RawTextArea';
import { TextArea } from './TextArea'; import { TextArea } from './TextArea';
export function Variable() { export function Variable() {
@ -13,6 +14,8 @@ Variable.Input = connect(Input);
Variable.TextArea = connect(TextArea, mapReadPretty(TextArea.ReadPretty)); Variable.TextArea = connect(TextArea, mapReadPretty(TextArea.ReadPretty));
Variable.RawTextArea = connect(RawTextArea);
Variable.JSON = connect(JSONInput); Variable.JSON = connect(JSONInput);
export default Variable; export default Variable;