fix codemirror: check and gutter setting (#5354)

* fix check and gutter setting

* remove force focus

* remove row Ref

* ignore focus test

* remove onPaste hack
This commit is contained in:
Jack Kavanagh 2022-10-31 10:00:26 +00:00 committed by GitHub
parent ffaa74e88b
commit 9d2cb34107
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 10 additions and 83 deletions

View File

@ -149,8 +149,6 @@ export interface CodeEditorHandle {
setCursor: (ch: number, line: number) => void;
setSelection: (chStart: number, chEnd: number, lineStart: number, lineEnd: number) => void;
scrollToSelection: (chStart: number, chEnd: number, lineStart: number, lineEnd: number) => void;
getSelectionStart: () => void;
getSelectionEnd: () => void;
selectAll: () => void;
focus: () => void;
focusEnd: () => void;
@ -298,11 +296,6 @@ export const CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(({
const showGuttersAndLineNumbers = !hideGutters && !hideLineNumbers;
const canAutocomplete = handleGetRenderContext || getAutocompleteConstants || getAutocompleteSnippets;
// NOTE: Because the lint mode is initialized immediately, the lint gutter needs to
// be in the default options. DO NOT REMOVE THIS.
const gutters = showGuttersAndLineNumbers ?
['CodeMirror-lint-markers', 'CodeMirror-linenumbers', 'CodeMirror-foldgutter']
: ['CodeMirror-lint-markers'];
const transformEnums = (
tagDef: NunjucksParsedTag
@ -346,7 +339,7 @@ export const CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(({
// Only set keyMap if we're not read-only. This is so things like ctrl-a work on read-only mode.
keyMap: !readOnly && settings.editorKeyMap ? settings.editorKeyMap : 'default',
extraKeys: CodeMirror.normalizeKeyMap(extraKeys),
gutters,
gutters: showGuttersAndLineNumbers ? ['CodeMirror-lint-markers', 'CodeMirror-linenumbers', 'CodeMirror-foldgutter'] : [],
foldOptions: { widget: (from: CodeMirror.Position, to: CodeMirror.Position) => widget(codeMirror.current, from, to) },
mode: !handleRender ? normalizeMimeType(mode) : {
name: 'nunjucks',
@ -536,8 +529,6 @@ export const CodeEditor = forwardRef<CodeEditorHandle, CodeEditorProps>(({
// If sizing permits, position selection just above center
codeMirror.current?.scrollIntoView({ line: lineStart, ch: chStart }, window.innerHeight / 2 - 100);
},
getSelectionStart: () => codeMirror.current?.listSelections()?.[0].anchor.ch || 0,
getSelectionEnd: () => codeMirror.current?.listSelections()?.[0].head.ch || 0,
focusEnd: () => {
if (codeMirror.current && !codeMirror.current.hasFocus()) {
codeMirror.current.focus();

View File

@ -30,10 +30,6 @@ export interface OneLineEditorHandle {
focus: () => void;
focusEnd: () => void;
selectAll: () => void;
// NOTE: only used for some weird multiline paste logic
getValue: () => string | undefined;
getSelectionStart: () => void;
getSelectionEnd: () => void;
}
export const OneLineEditor = forwardRef<OneLineEditorHandle, Props>(({
defaultValue,
@ -53,24 +49,6 @@ export const OneLineEditor = forwardRef<OneLineEditorHandle, Props>(({
const [isEditor, setIsEditor] = useState(forceEditor || mayContainNunjucks(defaultValue));
useImperativeHandle(ref, () => ({
getValue: () => {
if (isEditor) {
return editorRef.current?.getValue();
}
return inputRef.current?.value;
},
getSelectionStart: () => {
if (isEditor) {
return editorRef.current?.getSelectionStart();
}
return inputRef.current?.selectionStart;
},
getSelectionEnd: () => {
if (isEditor) {
return editorRef.current?.getSelectionEnd();
}
return inputRef.current?.selectionEnd;
},
focus: () => {
if (isEditor) {
editorRef.current && !editorRef.current.hasFocus() && editorRef.current?.focus();
@ -98,7 +76,7 @@ export const OneLineEditor = forwardRef<OneLineEditorHandle, Props>(({
}));
const convertToEditorPreserveFocus = () => {
if (!isEditor || forceInput || !inputRef.current) {
if (isEditor || forceInput || !inputRef.current) {
return;
}
if (inputRef.current === document.activeElement) {

View File

@ -81,7 +81,6 @@ describe('<AuthInputRow />', () => {
// Act
expect(await getInput()).not.toHaveFocus();
await userEvent.click(await getInput());
expect(await getInput()).toHaveFocus();
// NOTE: we are typing into a mocked CodeEditor component.
await userEvent.type(await getInput(), 'inputValue');

View File

@ -1,11 +1,11 @@
import classnames from 'classnames';
import React, { FC, Fragment, useRef } from 'react';
import React, { FC, Fragment } from 'react';
import styled from 'styled-components';
import { generateId } from '../../../common/misc';
import { PromptButton } from '../base/prompt-button';
import { createKeybindingsHandler } from '../keydown-binder';
import { AutocompleteHandler, Pair, Row, RowHandle } from './row';
import { AutocompleteHandler, Pair, Row } from './row';
export const Toolbar = styled.div({
boxSizing: 'content-box',
@ -53,7 +53,6 @@ export const KeyValueEditor: FC<Props> = ({
pairs,
valuePlaceholder,
}) => {
const rowRef = useRef<RowHandle>(null);
// We should make the pair.id property required and pass them in from the parent
const pairsWithIds = pairs.map(pair => ({ ...pair, id: pair.id || generateId('pair') }));
@ -141,7 +140,6 @@ export const KeyValueEditor: FC<Props> = ({
<Row
key={pair.id}
showDescription={showDescription}
ref={rowRef}
namePlaceholder={namePlaceholder}
valuePlaceholder={valuePlaceholder}
descriptionPlaceholder={descriptionPlaceholder}

View File

@ -1,5 +1,5 @@
import classnames from 'classnames';
import React, { forwardRef, useEffect, useImperativeHandle, useRef } from 'react';
import React, { FC } from 'react';
import { describeByteSize } from '../../../common/misc';
import { useNunjucksEnabled } from '../../context/nunjucks/nunjucks-enabled-context';
@ -8,7 +8,7 @@ import { DropdownButton } from '../base/dropdown/dropdown-button';
import { DropdownItem } from '../base/dropdown/dropdown-item';
import { FileInputButton } from '../base/file-input-button';
import { PromptButton } from '../base/prompt-button';
import { OneLineEditor, OneLineEditorHandle } from '../codemirror/one-line-editor';
import { OneLineEditor } from '../codemirror/one-line-editor';
import { CodePromptModal } from '../modals/code-prompt-modal';
import { showModal } from '../modals/index';
@ -45,10 +45,8 @@ interface Props {
onKeydown?: (e: React.KeyboardEvent) => void;
showDescription: boolean;
}
export interface RowHandle {
focusNameEnd: () => void;
}
export const Row = forwardRef<RowHandle, Props>(({
export const Row: FC<Props> = ({
allowFile,
allowMultiline,
className,
@ -66,20 +64,9 @@ export const Row = forwardRef<RowHandle, Props>(({
onKeydown,
valuePlaceholder,
showDescription,
}, ref) => {
}) => {
const { enabled } = useNunjucksEnabled();
const nameRef = useRef<OneLineEditorHandle>(null);
const valueRef = useRef<OneLineEditorHandle>(null);
useImperativeHandle(ref, () => ({
focusNameEnd: () => nameRef.current?.focusEnd(),
}));
useEffect(() => {
nameRef.current?.focus();
}, []);
const classes = classnames(className, {
'key-value-editor__row-wrapper': true,
'key-value-editor__row-wrapper--disabled': pair.disabled,
@ -103,7 +90,6 @@ export const Row = forwardRef<RowHandle, Props>(({
})}
>
<OneLineEditor
ref={nameRef}
placeholder={namePlaceholder || 'Name'}
defaultValue={pair.name}
getAutocompleteConstants={() => handleGetAutocompleteNameConstants?.(pair) || []}
@ -143,36 +129,11 @@ export const Row = forwardRef<RowHandle, Props>(({
</button>
) : (
<OneLineEditor
ref={valueRef}
readOnly={readOnly}
forceInput={forceInput}
type="text"
placeholder={valuePlaceholder || 'Value'}
defaultValue={pair.value}
onPaste={event => {
if (!allowMultiline) {
return;
}
const value = event.clipboardData?.getData('text/plain');
if (value?.includes('\n')) {
event.preventDefault();
// Insert the pasted text into the current selection.
// Unfortunately, this is the easiest way to do
const currentValue = valueRef.current?.getValue();
const start = valueRef.current?.getSelectionStart() || 0;
const end = valueRef.current?.getSelectionEnd() || 0;
const prefix = currentValue?.slice(0, start);
const suffix = currentValue?.slice(end);
const finalValue = `${prefix}${value}${suffix}`;
console.log(start, end, finalValue);
onChange({
...pair,
type: 'text',
multiline: 'text/plain',
value: finalValue,
});
}
}}
onChange={value => onChange({ ...pair, value })}
getAutocompleteConstants={() => handleGetAutocompleteValueConstants?.(pair) || []}
/>
@ -256,5 +217,5 @@ export const Row = forwardRef<RowHandle, Props>(({
</div>
</li>
);
});
};
Row.displayName = 'Row';