diff --git a/packages/browser-repl/package.json b/packages/browser-repl/package.json index 8129c53ea..c67a0e7a5 100644 --- a/packages/browser-repl/package.json +++ b/packages/browser-repl/package.json @@ -10,14 +10,14 @@ "exports": { ".": { "types": "./lib/index.d.ts", - "require": "./lib/index.js" + "default": "./lib/index.js" }, "./shell": { "types": "./lib/components/shell.d.ts", - "require": "./lib/components/shell.js" + "default": "./lib/components/shell.js" }, "./package.json": { - "require": "./package.json" + "default": "./package.json" } }, "scripts": { diff --git a/packages/browser-repl/src/components/shell-input.tsx b/packages/browser-repl/src/components/shell-input.tsx index cb1c90479..f044ccb8e 100644 --- a/packages/browser-repl/src/components/shell-input.tsx +++ b/packages/browser-repl/src/components/shell-input.tsx @@ -20,6 +20,8 @@ interface ShellInputProps { prompt?: string; onSigInt?(): Promise; editorRef?: (editor: EditorRef | null) => void; + initialText?: string; + onTextChange?: (text: string) => void; } interface ShellInputState { @@ -29,7 +31,7 @@ interface ShellInputState { export class ShellInput extends Component { readonly state: ShellInputState = { - currentValue: '', + currentValue: this.props.initialText ?? '', readOnly: false, }; @@ -61,6 +63,7 @@ export class ShellInput extends Component { } private onChange = (value: string): void => { + this.props.onTextChange?.(value); this.setState({ currentValue: value }); }; diff --git a/packages/browser-repl/src/components/shell.spec.tsx b/packages/browser-repl/src/components/shell.spec.tsx index 0a5f29d55..b3adf57f2 100644 --- a/packages/browser-repl/src/components/shell.spec.tsx +++ b/packages/browser-repl/src/components/shell.spec.tsx @@ -516,4 +516,11 @@ describe('', function () { expect(wrapper.find('ShellInput').prop('prompt')).to.equal('abc>'); }); }); + + it('sets initial text for the shell input', function () { + wrapper = mount( + + ); + expect(wrapper.find('Editor').prop('value')).to.eq('db.coll.find({})'); + }); }); diff --git a/packages/browser-repl/src/components/shell.tsx b/packages/browser-repl/src/components/shell.tsx index 28eb84672..b407ae032 100644 --- a/packages/browser-repl/src/components/shell.tsx +++ b/packages/browser-repl/src/components/shell.tsx @@ -62,6 +62,11 @@ interface ShellProps { */ onHistoryChanged: (history: readonly string[]) => void; + /** + * A function called each time the text in the shell input is changed + */ + onInputChanged?: (input: string) => void; + /* If set, the shell will omit or redact entries containing sensitive * info from history. Defaults to `false`. */ @@ -85,6 +90,16 @@ interface ShellProps { */ onOperationEnd: () => void; + /** + * Initial value in the shell input field + */ + initialInput?: string; + + /** + * A set of input strings to evaluate right after shell is mounted + */ + initialEvaluate?: string | string[]; + /* An array of entries to be displayed in the output area. * * Can be used to restore the output between sessions, or to setup @@ -128,6 +143,7 @@ export class Shell extends Component { onOutputChanged: noop, maxOutputLength: 1000, maxHistoryLength: 1000, + initialInput: '', initialOutput: [], initialHistory: [], }; @@ -147,8 +163,16 @@ export class Shell extends Component { componentDidMount(): void { this.scrollToBottom(); - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.updateShellPrompt(); + void this.updateShellPrompt().then(async () => { + if (this.props.initialEvaluate) { + const evalLines = Array.isArray(this.props.initialEvaluate) + ? this.props.initialEvaluate + : [this.props.initialEvaluate]; + for (const input of evalLines) { + await this.onInput(input); + } + } + }); } componentDidUpdate(): void { @@ -351,7 +375,7 @@ export class Shell extends Component { this.editor = editor; }; - private focusEditor = (): void => { + focusEditor = (): void => { this.editor?.focus(); }; @@ -379,6 +403,8 @@ export class Shell extends Component { return ( { const [redactInfo, setRedactInfo] = useState(false); const [maxOutputLength, setMaxOutputLength] = useState(1000); const [maxHistoryLength, setMaxHistoryLength] = useState(1000); + const [initialInput, setInitialInput] = useState(''); + const [initialEvaluate, setInitialEvaluate] = useState([]); const [initialOutput] = useState([ { format: 'output', value: { foo: 1, bar: true, buz: function () {} } }, ]); @@ -171,8 +173,8 @@ const IframeRuntimeExample: React.FunctionComponent = () => { }, []); const key = useMemo(() => { - return initialHistory.join(''); - }, [initialHistory]); + return initialHistory.concat(initialInput, initialEvaluate).join(''); + }, [initialHistory, initialInput, initialEvaluate]); return (
@@ -183,6 +185,8 @@ const IframeRuntimeExample: React.FunctionComponent = () => { redactInfo={redactInfo} maxOutputLength={maxOutputLength} maxHistoryLength={maxHistoryLength} + initialInput={initialInput} + initialEvaluate={initialEvaluate.filter(Boolean)} initialOutput={initialOutput} initialHistory={initialHistory.filter(Boolean)} /> @@ -263,6 +267,38 @@ const IframeRuntimeExample: React.FunctionComponent = () => { className={cx(textarea, textInput)} /> + + + + Initial value in the shell input field + { + setInitialInput(evt.currentTarget.value); + }} + /> + + + + + + A set of input strings to evaluate right after shell is mounted + +