Skip to content

Commit

Permalink
fix(CodeEditor): use codeEditorControls and clean up overall (#7931)
Browse files Browse the repository at this point in the history
* fix(CodeEditor): use codeEditorControls and clean up overall

* fix lint errors

* use better variable names

* clean up per PR comments

* add back useCallback

* clean up

* clean up

* fix lint errors

* add console warnings when using deprecated props

* fix lint errors

* update warning messages

* fix lint again
  • Loading branch information
nicolethoen committed Oct 21, 2022
1 parent 01da036 commit 69d5937
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 130 deletions.
102 changes: 44 additions & 58 deletions packages/react-code-editor/src/components/CodeEditor/CodeEditor.tsx
Expand Up @@ -13,7 +13,6 @@ import {
Popover,
PopoverProps,
Title,
Tooltip,
TooltipPosition
} from '@patternfly/react-core';
import MonacoEditor, { ChangeHandler, EditorDidMount } from 'react-monaco-editor';
Expand All @@ -25,6 +24,7 @@ import CodeIcon from '@patternfly/react-icons/dist/esm/icons/code-icon';
import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';
import Dropzone from 'react-dropzone';
import { CodeEditorContext } from './CodeEditorUtils';
import { CodeEditorControl } from './CodeEditorControl';

export interface Shortcut {
description: string;
Expand Down Expand Up @@ -440,18 +440,8 @@ export class CodeEditor extends React.Component<CodeEditorProps, CodeEditorState
};

copyCode = () => {
if (this.timer) {
window.clearTimeout(this.timer);
this.setState({ copied: false });
}
this.editor?.focus();
document.execCommand('copy');
this.setState({ copied: true }, () => {
this.timer = window.setTimeout(() => {
this.setState({ copied: false });
this.timer = null;
}, 2500);
});
navigator.clipboard.writeText(this.state.value);
this.setState({ copied: true });
};

download = () => {
Expand Down Expand Up @@ -555,55 +545,51 @@ export class CodeEditor extends React.Component<CodeEditorProps, CodeEditorState
</EmptyState>
));

const tooltipProps = {
position: toolTipPosition,
exitDelay: toolTipDelay,
entryDelay: toolTipDelay,
maxWidth: toolTipMaxWidth,
trigger: 'mouseenter focus'
};

const editorHeader = (
<div className={css(styles.codeEditorHeader)}>
{
<div className={css(styles.codeEditorControls)}>
{isCopyEnabled && (!showEmptyState || !!value) && (
<Tooltip
trigger="mouseenter"
content={<div>{copied ? copyButtonSuccessTooltipText : copyButtonToolTipText}</div>}
exitDelay={copied ? toolTipCopyExitDelay : toolTipDelay}
entryDelay={toolTipDelay}
maxWidth={toolTipMaxWidth}
position={toolTipPosition}
>
<Button onClick={this.copyCode} variant="control" aria-label={copyButtonAriaLabel}>
<CopyIcon />
</Button>
</Tooltip>
)}
{isUploadEnabled && (
<Tooltip
trigger="mouseenter focus click"
content={<div>{uploadButtonToolTipText}</div>}
entryDelay={toolTipDelay}
exitDelay={toolTipDelay}
maxWidth={toolTipMaxWidth}
position={toolTipPosition}
>
<Button onClick={open} variant="control" aria-label={uploadButtonAriaLabel}>
<UploadIcon />
</Button>
</Tooltip>
)}
{isDownloadEnabled && (!showEmptyState || !!value) && (
<Tooltip
trigger="mouseenter focus click"
content={<div>{downloadButtonToolTipText}</div>}
entryDelay={toolTipDelay}
exitDelay={toolTipDelay}
maxWidth={toolTipMaxWidth}
position={toolTipPosition}
>
<Button onClick={this.download} variant="control" aria-label={downloadButtonAriaLabel}>
<DownloadIcon />
</Button>
</Tooltip>
)}
{customControls && (
<CodeEditorContext.Provider value={{ code: value }}>{customControls}</CodeEditorContext.Provider>
)}
<CodeEditorContext.Provider value={{ code: value }}>
{isCopyEnabled && (!showEmptyState || !!value) && (
<CodeEditorControl
icon={<CopyIcon />}
aria-label={copyButtonAriaLabel}
tooltipProps={{
...tooltipProps,
'aria-live': 'polite',
content: <div>{copied ? copyButtonSuccessTooltipText : copyButtonToolTipText}</div>,
exitDelay: copied ? toolTipCopyExitDelay : toolTipDelay,
onTooltipHidden: () => this.setState({ copied: false })
}}
onClick={this.copyCode}
/>
)}
{isUploadEnabled && (
<CodeEditorControl
icon={<UploadIcon />}
aria-label={uploadButtonAriaLabel}
tooltipProps={{ content: <div>{uploadButtonToolTipText}</div>, ...tooltipProps }}
onClick={open}
/>
)}
{isDownloadEnabled && (!showEmptyState || !!value) && (
<CodeEditorControl
icon={<DownloadIcon />}
aria-label={downloadButtonAriaLabel}
tooltipProps={{ content: <div>{downloadButtonToolTipText}</div>, ...tooltipProps }}
onClick={this.download}
/>
)}
{customControls && customControls}
</CodeEditorContext.Provider>
</div>
}
{<div className={css(styles.codeEditorHeaderMain)}>{headerMainContent}</div>}
Expand Down
Expand Up @@ -7,19 +7,19 @@ import { CodeEditorContext } from './CodeEditorUtils';
*/

export interface CodeEditorControlProps extends Omit<ButtonProps, 'onClick'> {
/** Accessible label for the code editor control. */
/** Accessible label for the code editor control */
'aria-label'?: string;
/** Additional classes added to the code editor control. */
className?: string;
/** Delay in ms before the tooltip appears. */
/** @deprecated Delay in ms before the tooltip appears. */
entryDelay?: number;
/** Delay in ms before the tooltip disappears. */
/** @deprecated Delay in ms before the tooltip disappears. */
exitDelay?: number;
/** Icon rendered inside the code editor control. */
icon: React.ReactNode;
/** Maximum width of the tooltip (default 150px). */
/** @deprecated Maximum width of the tooltip (default 150px). */
maxWidth?: string;
/** Copy button popover position. */
/** @deprecated Copy button popover position. */
position?:
| PopoverPosition
| 'auto'
Expand All @@ -35,41 +35,82 @@ export interface CodeEditorControlProps extends Omit<ButtonProps, 'onClick'> {
| 'left-end'
| 'right-start'
| 'right-end';
/** Text to display in the tooltip. */
toolTipText: React.ReactNode;
/** Event handler for the click of the button. */
/** @deprecated Text to display in the tooltip*/
toolTipText?: React.ReactNode;
/** Event handler for the click of the button */
onClick: (code: string, event?: any) => void;
/** Flag indicating that the button is visible above the code editor. */
isVisible?: boolean;
/** Additional tooltip props forwarded to the Tooltip component */
tooltipProps?: any;
}

export const CodeEditorControl: React.FunctionComponent<CodeEditorControlProps> = ({
icon,
className,
'aria-label': ariaLabel,
toolTipText,
exitDelay = 0,
entryDelay = 300,
maxWidth = '100px',
position = 'top',
exitDelay,
entryDelay,
maxWidth,
position,
onClick = () => {},
isVisible = true,
tooltipProps = {},
...props
}: CodeEditorControlProps) => {
const context = React.useContext(CodeEditorContext);

if (entryDelay !== undefined) {
// eslint-disable-next-line no-console
console.warn(
'CodeEditorControl: entryDelay prop has been deprecated. ' +
'Pass the entryDelay via the tooltipProps prop instead.'
);
}

if (exitDelay !== undefined) {
// eslint-disable-next-line no-console
console.warn(
'CodeEditorControl: exitDelay prop has been deprecated. ' +
'Pass the exitDelay via the tooltipProps prop instead.'
);
}

if (maxWidth !== undefined) {
// eslint-disable-next-line no-console
console.warn(
'CodeEditorControl: maxWidth prop has been deprecated. ' + 'Pass the maxWidth via the tooltipProps prop instead.'
);
}

if (position !== undefined) {
// eslint-disable-next-line no-console
console.warn(
'CodeEditorControl: position prop has been deprecated. ' + 'Pass the position via the tooltipProps prop instead.'
);
}

if (toolTipText !== undefined) {
// eslint-disable-next-line no-console
console.warn(
'CodeEditorControl: toolTipText prop has been deprecated. ' +
'Pass the toolTipText by setting the content field in tooltipProps prop instead.'
);
}

const onCustomClick = (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
onClick(context.code, event);
};

return isVisible ? (
<Tooltip
trigger="mouseenter focus click"
exitDelay={exitDelay}
entryDelay={entryDelay}
maxWidth={maxWidth}
position={position}
content={<div>{toolTipText}</div>}
{...tooltipProps}
>
<Button className={className} onClick={onCustomClick} variant="control" aria-label={ariaLabel} {...props}>
{icon}
Expand Down
Expand Up @@ -18,7 +18,7 @@ export const CodeEditorCustomControl: React.FunctionComponent = () => {
<CodeEditorControl
icon={<PlayIcon />}
aria-label="Execute code"
toolTipText="Execute code"
tooltipProps={{ content: 'Execute code' }}
onClick={onExecuteCode}
isVisible={code !== ''}
/>
Expand Down
Expand Up @@ -36,22 +36,22 @@ export const CodeEditorShortcutMainHeader: React.FunctionComponent = () => {
];
const shortcutsPopoverProps = {
bodyContent: (
<Grid span={6} hasGutter>
{shortcuts.map(s => (
<>
<Grid span={6} hasGutter key="grid">
{shortcuts.map((shortcut, index) => (
<React.Fragment key={index}>
<GridItem style={{ textAlign: 'right', marginRight: '1em' }}>
{s.keys
.map(k => (
<Chip key={k} isReadOnly>
{k}
{shortcut.keys
.map(key => (
<Chip key={key} isReadOnly>
{key}
</Chip>
))
.reduce((prev, curr) => (
<>{[prev, ' + ', curr]}</>
))}
</GridItem>
<GridItem>{s.description}</GridItem>
</>
<GridItem>{shortcut.description}</GridItem>
</React.Fragment>
))}
</Grid>
),
Expand All @@ -60,7 +60,6 @@ export const CodeEditorShortcutMainHeader: React.FunctionComponent = () => {

return (
<CodeEditor
headerMainContent="Shortcut Example"
shortcutsPopoverProps={shortcutsPopoverProps}
isLanguageLabelVisible
code="Some example content"
Expand Down

0 comments on commit 69d5937

Please sign in to comment.