Skip to content

Commit

Permalink
Merge pull request #2 from likhith-deriv/likhith/74994/migrated-clipb…
Browse files Browse the repository at this point in the history
…oard-component-to-tsx

likhith/migrated clipboard component to tsx
  • Loading branch information
suisin-deriv committed Oct 28, 2022
2 parents 5f78284 + 98a4239 commit 471f971
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,16 @@ const ApiTokenClipboard = ({ scopes, text_copy, info_message, success_message, p
if (!is_copied) setIsPopoverOpen(false);
};

const copyToClipboard = text => {
const copyToClipboard = async text => {
const textField = document.createElement('textarea');
textField.innerText = text;
document.body.appendChild(textField);
textField.select();
document.execCommand('copy');
if ('clipboard' in navigator) {
await navigator.clipboard.writeText(text);
} else {
document.execCommand('copy');
}
textField.remove();
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import React from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { useIsMounted } from '@deriv/shared';
import Popover from '../popover';
import Icon from '../icon';
import { TPopoverProps } from '../types';

type TClipboard = {
text_copy: string;
icon?: string;
info_message?: string;
success_message?: string;
className?: string;
popoverClassName?: string;
popoverAlignment?: 'top' | 'right' | 'bottom' | 'left';
popover_props?: Partial<TPopoverProps>;
};

const Clipboard = ({
text_copy,
Expand All @@ -14,30 +25,38 @@ const Clipboard = ({
popoverClassName,
popover_props = {},
popoverAlignment = 'bottom',
}) => {
}: TClipboard) => {
const [is_copied, setIsCopied] = React.useState(false);
const isMounted = useIsMounted();
let timeout_clipboard = null;
let timeout_clipboard: NodeJS.Timeout;

const copyToClipboard = async text => {
await navigator.clipboard.writeText(text);
const copyToClipboard = async (text: string) => {
const textField = document.createElement('textarea');
textField.innerText = text;
document.body.appendChild(textField);
textField.select();
if ('clipboard' in navigator) {
await navigator.clipboard.writeText(text);
} else {
document.execCommand('copy');
}
textField.remove();
};

const onClick = event => {
copyToClipboard(text_copy).then(() => {
setIsCopied(true);
timeout_clipboard = setTimeout(() => {
if (isMounted()) {
setIsCopied(false);
}
}, 2000);
event.stopPropagation();
});
const onClick = (event: { stopPropagation: () => void }) => {
copyToClipboard(text_copy);
setIsCopied(true);
timeout_clipboard = setTimeout(() => {
if (isMounted()) {
setIsCopied(false);
}
}, 2000);
event.stopPropagation();
};

React.useEffect(() => {
return () => clearTimeout(timeout_clipboard);
}, [timeout_clipboard]);
}, []);

return (
<>
Expand Down Expand Up @@ -67,14 +86,5 @@ const Clipboard = ({
</>
);
};
Clipboard.propTypes = {
text_copy: PropTypes.string,
icon: PropTypes.string,
info_message: PropTypes.string,
success_message: PropTypes.string,
className: PropTypes.string,
popoverClassName: PropTypes.string,
popoverAlignment: PropTypes.oneOf(['top', 'right', 'bottom', 'left']),
popover_props: PropTypes.object,
};

export default Clipboard;
2 changes: 1 addition & 1 deletion packages/components/src/components/clipboard/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Clipboard from './clipboard.jsx';
import Clipboard from './clipboard';
import './clipboard.scss';

export default Clipboard;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React from 'react';
import { isMobile } from '@deriv/shared';
import Button from '../button/button';
import Modal from '../modal/modal';
import Popover from '../popover/popover.jsx';
import Popover from '../popover/popover';
import Text from '../text/text';
import './popover-mobile.scss';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Popover from './popover.jsx';
import Popover from './popover';
import './popover.scss';

export default Popover;
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import classNames from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import React, { RefObject } from 'react';
import TinyPopover, { ArrowContainer } from 'react-tiny-popover';
import Icon from '../icon';
import Text from '../text';
import { useHover, useHoverCallback } from '../../hooks/use-hover';
import { TPopoverProps } from '../types';

const Popover = ({
alignment,
Expand All @@ -21,19 +21,19 @@ const Popover = ({
id,
is_open,
is_bubble_hover_enabled,
margin,
margin = 0,
message,
onBubbleClose,
onBubbleOpen,
onClick = () => {},
relative_render,
should_disable_pointer_events,
onClick = () => undefined,
relative_render = false,
should_disable_pointer_events = false,
should_show_cursor,
window_border,
zIndex,
}) => {
const ref = React.useRef();
const [popover_ref, setPopoverRef] = React.useState(undefined);
zIndex = '1',
}: React.PropsWithChildren<Partial<TPopoverProps>>) => {
const ref = React.useRef<HTMLDivElement | undefined>();
const [popover_ref, setPopoverRef] = React.useState<HTMLDivElement | undefined>(undefined);
const [hover_ref, is_hovered] = useHover(null, true);
const [bubble_hover_ref, is_bubble_hovered] = useHoverCallback();

Expand All @@ -54,18 +54,22 @@ const Popover = ({
const icon_class_name = classNames(classNameTargetIcon, icon);

return (
<div ref={hover_ref} className={classNames({ 'dc-popover__wrapper': relative_render })} onClick={onClick}>
<div
ref={hover_ref as RefObject<HTMLDivElement>}
className={classNames({ 'dc-popover__wrapper': relative_render })}
onClick={onClick}
>
{relative_render && (
<div className='dc-popover__container' style={{ zIndex }}>
<div ref={ref} className='dc-popover__container-relative' />
<div ref={ref as RefObject<HTMLDivElement>} className='dc-popover__container-relative' />
</div>
)}
{(popover_ref || !relative_render) && (
<TinyPopover
isOpen={
is_bubble_hover_enabled
(is_bubble_hover_enabled
? is_open ?? ((is_hovered && message) || (is_bubble_hover_enabled && is_bubble_hovered))
: is_open ?? (is_hovered && message)
: is_open ?? (is_hovered && message)) as boolean
}
position={alignment}
transitionDuration={0.25}
Expand Down Expand Up @@ -148,7 +152,7 @@ const Popover = ({
className={classNames(classNameBubble, 'dc-popover__bubble', {
'dc-popover__bubble--error': has_error,
})}
ref={bubble_hover_ref}
ref={bubble_hover_ref as (node: HTMLDivElement) => void}
>
{!disable_message_icon && icon === 'info' && (
<i className='dc-popover__bubble__icon'>
Expand Down Expand Up @@ -193,38 +197,4 @@ const Popover = ({
);
};

Popover.defaultProps = {
margin: 0,
relative_render: false,
should_disable_pointer_events: false,
zIndex: 1,
};

Popover.propTypes = {
alignment: PropTypes.string,
children: PropTypes.node,
className: PropTypes.string,
classNameBubble: PropTypes.string,
classNameTarget: PropTypes.string,
classNameTargetIcon: PropTypes.string,
counter: PropTypes.number,
disable_message_icon: PropTypes.bool,
disable_target_icon: PropTypes.bool,
has_error: PropTypes.bool,
icon: PropTypes.oneOf(['info', 'question', 'dot', 'counter']),
id: PropTypes.string,
is_bubble_hover_enabled: PropTypes.bool,
is_open: PropTypes.bool,
relative_render: PropTypes.bool,
margin: PropTypes.number,
message: PropTypes.oneOfType([PropTypes.node, PropTypes.object, PropTypes.string]),
onBubbleOpen: PropTypes.func,
onBubbleClose: PropTypes.func,
onClick: PropTypes.func,
should_disable_pointer_events: PropTypes.bool,
should_show_cursor: PropTypes.bool,
zIndex: PropTypes.number,
window_border: PropTypes.number,
};

export default Popover;
3 changes: 2 additions & 1 deletion packages/components/src/components/types/icons.types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { MouseEventHandler } from 'react';
import { TGenericObjectType } from './common.types';

export type TIconsManifest = Readonly<{
Expand All @@ -24,7 +25,7 @@ export type TIconProps = {
data_testid?: string;
height?: number | string;
icon: string;
onClick?: () => void;
onClick?: MouseEventHandler;
onMouseEnter?: () => void;
onMouseLeave?: () => void;
size?: number | string;
Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/components/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { TIconsManifest, TIconProps } from './icons.types';
import { TAccordionProps, TAccordionItem } from './accordion.types';
import { TPopoverProps } from './popover.types';

export type { TIconsManifest, TIconProps, TAccordionProps, TAccordionItem };
export type { TIconsManifest, TIconProps, TAccordionProps, TAccordionItem, TPopoverProps };
28 changes: 28 additions & 0 deletions packages/components/src/components/types/popover.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from 'react';
import { Position } from 'react-tiny-popover';

export type TPopoverProps = {
alignment: Position;
className?: string;
classNameBubble?: string;
classNameTarget?: string;
classNameTargetIcon?: string;
counter?: number;
disable_message_icon?: boolean;
disable_target_icon?: boolean;
has_error?: boolean;
icon: 'info' | 'question' | 'dot' | 'counter';
id: string;
is_bubble_hover_enabled?: boolean;
is_open?: boolean;
relative_render?: boolean;
margin: number;
message: React.ReactNode;
onBubbleOpen: () => void;
onBubbleClose: () => void;
onClick: () => void;
should_disable_pointer_events?: boolean;
should_show_cursor?: boolean;
zIndex: string;
window_border: number;
};

0 comments on commit 471f971

Please sign in to comment.