1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- import React, {CSSProperties} from 'react';
- import classNames from 'classnames';
- import {isRenderFunc} from 'app/utils/isRenderFunc';
- import {selectText} from 'app/utils/selectText';
- type ChildRenderProps = {
- doSelect: () => void;
- doMount: (el: HTMLElement) => void;
- };
- type ChildFunction = (props: ChildRenderProps) => React.ReactNode;
- type Props = {
- /**
- * Can be a `node` for a simple auto select div container.
- * When children is a render function, it is passed 2 functions:
- * - `doMount` - should be applied on parent element's `ref` whose
- * children is the text to be copied
- * - `doSelect` - selects text
- */
- children: React.ReactNode | ChildFunction;
- className?: string;
- style?: CSSProperties;
- };
- class AutoSelectText extends React.Component<Props> {
- private el: HTMLElement | undefined;
- selectText = () => {
- if (!this.el) {
- return;
- }
- selectText(this.el);
- };
- handleMount = (el: HTMLElement) => {
- this.el = el;
- };
- render() {
- const {children, className, ...props} = this.props;
- if (isRenderFunc<ChildFunction>(children)) {
- return children({
- doMount: this.handleMount,
- doSelect: this.selectText,
- });
- }
- // use an inner span here for the selection as otherwise the selectText
- // function will create a range that includes the entire part of the
- // div (including the div itself) which causes newlines to be selected
- // in chrome.
- return (
- <div
- {...props}
- onClick={this.selectText}
- className={classNames('auto-select-text', className)}
- >
- <span ref={this.handleMount}>{children}</span>
- </div>
- );
- }
- }
- export default AutoSelectText;
|