All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.src.components.ClipboardCopy.ClipboardCopy.tsx Maven / Gradle / Ivy

Go to download

This library provides a set of common React components for use with the PatternFly reference implementation.

The newest version!
import * as React from 'react';
import styles from '@patternfly/react-styles/css/components/ClipboardCopy/clipboard-copy';
import { css } from '@patternfly/react-styles';
import { PickOptional } from '../../helpers/typeUtils';
import { TooltipPosition } from '../Tooltip';
import { TextInput } from '../TextInput';
import { GenerateId } from '../../helpers/GenerateId/GenerateId';
import { ClipboardCopyButton } from './ClipboardCopyButton';
import { ClipboardCopyToggle } from './ClipboardCopyToggle';
import { ClipboardCopyExpanded } from './ClipboardCopyExpanded';
import { getOUIAProps, OUIAProps } from '../../helpers';

export const clipboardCopyFunc = (event: React.ClipboardEvent, text?: React.ReactNode) => {
  navigator.clipboard.writeText(text.toString());
};

export enum ClipboardCopyVariant {
  inline = 'inline',
  expansion = 'expansion',
  inlineCompact = 'inline-compact'
}

export interface ClipboardCopyState {
  text: string;
  expanded: boolean;
  copied: boolean;
  textWhenExpanded: string;
}

export interface ClipboardCopyProps extends Omit, 'onChange'>, OUIAProps {
  /** Additional classes added to the clipboard copy container. */
  className?: string;
  /** Tooltip message to display when hover the copy button */
  hoverTip?: string;
  /** Tooltip message to display when clicking the copy button */
  clickTip?: string;
  /** Aria-label to use on the TextInput. */
  textAriaLabel?: string;
  /** Aria-label to use on the ClipboardCopyToggle. */
  toggleAriaLabel?: string;
  /** Flag to show if the input is read only. */
  isReadOnly?: boolean;
  /** Flag to determine if clipboard copy is in the expanded state initially */
  isExpanded?: boolean;
  /** Flag to determine if clipboard copy content includes code */
  isCode?: boolean;
  /** Flag to determine if inline clipboard copy should be block styling */
  isBlock?: boolean;
  /** Adds Clipboard Copy variant styles. */
  variant?: typeof ClipboardCopyVariant | 'inline' | 'expansion' | 'inline-compact';
  /** Copy button tooltip position. */
  position?:
    | TooltipPosition
    | 'auto'
    | 'top'
    | 'bottom'
    | 'left'
    | 'right'
    | 'top-start'
    | 'top-end'
    | 'bottom-start'
    | 'bottom-end'
    | 'left-start'
    | 'left-end'
    | 'right-start'
    | 'right-end';
  /** Maximum width of the tooltip (default 150px). */
  maxWidth?: string;
  /** Delay in ms before the tooltip disappears. */
  exitDelay?: number;
  /** Delay in ms before the tooltip appears. */
  entryDelay?: number;
  /** A function that is triggered on clicking the copy button. */
  onCopy?: (event: React.ClipboardEvent, text?: React.ReactNode) => void;
  /** A function that is triggered on changing the text. */
  onChange?: (event: React.FormEvent, text?: string) => void;
  /** The text which is copied. */
  children: React.ReactNode;
  /** Additional actions for inline-compact clipboard copy. Should be wrapped with ClipboardCopyAction. */
  additionalActions?: React.ReactNode;
  /** Value to overwrite the randomly generated data-ouia-component-id.*/
  ouiaId?: number | string;
  /** Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false. */
  ouiaSafe?: boolean;
}

class ClipboardCopy extends React.Component {
  static displayName = 'ClipboardCopy';
  timer = null as number;
  constructor(props: ClipboardCopyProps) {
    super(props);
    const text = Array.isArray(this.props.children) ? this.props.children.join('') : (this.props.children as string);
    this.state = {
      text,
      expanded: this.props.isExpanded,
      copied: false,
      textWhenExpanded: text
    };
  }

  static defaultProps: PickOptional = {
    hoverTip: 'Copy to clipboard',
    clickTip: 'Successfully copied to clipboard!',
    isReadOnly: false,
    isExpanded: false,
    isCode: false,
    variant: 'inline',
    position: TooltipPosition.top,
    maxWidth: '150px',
    exitDelay: 1500,
    entryDelay: 300,
    onCopy: clipboardCopyFunc,
    onChange: (): any => undefined,
    textAriaLabel: 'Copyable input',
    toggleAriaLabel: 'Show content',
    additionalActions: null,
    ouiaSafe: true
  };

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  componentDidUpdate = (prevProps: ClipboardCopyProps, prevState: ClipboardCopyState) => {
    if (prevProps.children !== this.props.children) {
      const newText = this.props.children as string;
      this.setState({ text: newText, textWhenExpanded: newText });
    }
  };

  componentWillUnmount = () => {
    if (this.timer) {
      window.clearTimeout(this.timer);
    }
  };

  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  expandContent = (_event: React.MouseEvent) => {
    this.setState((prevState) => ({
      expanded: !prevState.expanded
    }));
  };

  updateText = (event: React.FormEvent, text: string) => {
    this.setState({ text });
    this.props.onChange(event, text);
  };

  updateTextWhenExpanded = (event: React.FormEvent, text: string) => {
    this.setState({ textWhenExpanded: text });
    this.props.onChange(event, text);
  };

  render = () => {
    const {
      /* eslint-disable @typescript-eslint/no-unused-vars */
      isExpanded,
      onChange, // Don't pass to 
/* eslint-enable @typescript-eslint/no-unused-vars */ isReadOnly, isCode, isBlock, exitDelay, maxWidth, entryDelay, onCopy, hoverTip, clickTip, textAriaLabel, toggleAriaLabel, variant, position, className, additionalActions, ouiaId, ouiaSafe, ...divProps } = this.props; const textIdPrefix = 'text-input-'; const toggleIdPrefix = 'toggle-'; const contentIdPrefix = 'content-'; return (
{variant === 'inline-compact' && ( {(id) => ( {!isCode && ( {this.state.text} )} {isCode && ( {this.state.text} )} { onCopy(event, this.state.text); this.setState({ copied: true }); }} onTooltipHidden={() => this.setState({ copied: false })} > {this.state.copied ? clickTip : hoverTip} {additionalActions && additionalActions} )} )} {variant !== 'inline-compact' && ( {(id) => (
{variant === 'expansion' && ( { this.expandContent(_event); if (this.state.expanded) { this.setState({ text: this.state.textWhenExpanded }); } else { this.setState({ textWhenExpanded: this.state.text }); } }} id={`${toggleIdPrefix}${id}`} textId={`${textIdPrefix}${id}`} contentId={`${contentIdPrefix}${id}`} aria-label={toggleAriaLabel} /> )} { onCopy(event, this.state.expanded ? this.state.textWhenExpanded : this.state.text); this.setState({ copied: true }); }} onTooltipHidden={() => this.setState({ copied: false })} > {this.state.copied ? clickTip : hoverTip}
{this.state.expanded && ( {this.state.text} )}
)}
)}
); }; } export { ClipboardCopy };




© 2015 - 2024 Weber Informatics LLC | Privacy Policy