@apify/ui-library 1.95.0 → 1.97.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apify/ui-library",
3
- "version": "1.95.0",
3
+ "version": "1.97.0",
4
4
  "description": "React UI library used by apify.com",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -26,7 +26,7 @@
26
26
  "It's not nice, but helps us to get around the problem of multiple react instances."
27
27
  ],
28
28
  "dependencies": {
29
- "@apify/ui-icons": "^1.18.1",
29
+ "@apify/ui-icons": "^1.18.2",
30
30
  "@floating-ui/react": "^0.26.2",
31
31
  "@react-hook/resize-observer": "^2.0.2",
32
32
  "clsx": "^2.0.0",
@@ -54,17 +54,15 @@
54
54
  "devDependencies": {
55
55
  "@storybook/react-vite": "^9.0.16",
56
56
  "@types/lodash": "^4.14.200",
57
- "@types/node": "^22.10.5",
58
57
  "@types/react": "^18.2.74",
59
58
  "@types/styled-components": "^5.1.34",
60
59
  "recast": "^0.23.9",
61
- "style-dictionary": "^4.4.0",
62
- "typescript": "^5.1.6"
60
+ "style-dictionary": "^4.4.0"
63
61
  },
64
62
  "files": [
65
63
  "dist",
66
64
  "src",
67
65
  "style"
68
66
  ],
69
- "gitHead": "4e6b487ae68936e626d6c4309e646823125e4ad5"
67
+ "gitHead": "c7f6cc1c7b3913d392aab255e763280983256dc5"
70
68
  }
@@ -87,9 +87,9 @@ interface CopyButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>
87
87
  }
88
88
 
89
89
  export const CopyButton = ({ code, ...props }: CopyButtonProps) => {
90
- const [isCopied, handleClick] = useCopyToClipboard({ text: code });
90
+ const { isCopied, copyToClipboard } = useCopyToClipboard();
91
91
  return (
92
- <ActionButton onClick={handleClick} data-test='copy_to_clipboard' aria-label="Copy to clipboard" {...props}>
92
+ <ActionButton onClick={async () => copyToClipboard(code)} data-test='copy_to_clipboard' aria-label="Copy to clipboard" {...props}>
93
93
  {isCopied ? <CheckIcon size="16" /> : <CopyIcon size="16" />}
94
94
  </ActionButton>
95
95
  );
@@ -26,8 +26,8 @@ const CopyButtonWrapper = styled.div`
26
26
  `;
27
27
 
28
28
  const CopyButton: React.FC<{ text: string }> = ({ text }) => {
29
- const [isCopied, copyToClipboard] = useCopyToClipboard({ text });
30
- return <CopyButtonWrapper role='button' onClick={copyToClipboard} title='Copy to clipboard'>
29
+ const { isCopied, copyToClipboard } = useCopyToClipboard();
30
+ return <CopyButtonWrapper role='button' onClick={async () => copyToClipboard(text)} title='Copy to clipboard'>
31
31
  {isCopied ? <CheckIcon size="16" /> : <CopyIcon size="16" />}
32
32
  </CopyButtonWrapper>;
33
33
  };
@@ -71,15 +71,13 @@ export const MarkdownHeadingWrapper: React.FC<HeadingSharedProps> = ({
71
71
  }) => {
72
72
  const id = slugifyHeadingChildren(children);
73
73
 
74
- const [isCopied, handleClick] = useCopyToClipboard({
75
- text: id ?? '',
76
- // We want the whole URL to be copied, not just the ID
77
- transform: (text) => {
78
- const url = new URL(window.location.href);
79
- url.hash = `#${text}`;
80
- return url.toString();
81
- },
82
- });
74
+ const { isCopied, copyToClipboard } = useCopyToClipboard();
75
+
76
+ async function handleClick() {
77
+ const url = new URL(window.location.href);
78
+ url.hash = `#${id ?? ''}`;
79
+ await copyToClipboard(url.toString());
80
+ }
83
81
 
84
82
  return (
85
83
  <StyledMarkdownHeading
@@ -94,7 +94,7 @@ const StyledMarkdown = styled(ReactMarkdown) <StyledReadmeProps>`
94
94
  &.isCopied {
95
95
  opacity: 1;
96
96
  pointer-events: none;
97
-
97
+
98
98
  &::after {
99
99
  content: 'Copied!';
100
100
  opacity: 1;
@@ -513,15 +513,13 @@ const HeadingRendererWithAnchor = ({ node, children }: HeadingRendererProps) =>
513
513
  const Tag = node.tagName;
514
514
  const id = slugifyHeadingChildren(children);
515
515
 
516
- const [isCopied, handleClick] = useCopyToClipboard({
517
- text: id ?? '',
518
- // We want the whole URL to be copied, not just the ID
519
- transform: (text) => {
520
- const url = new URL(window.location.href);
521
- url.hash = `#${text}`;
522
- return url.toString();
523
- },
524
- });
516
+ const { isCopied, copyToClipboard } = useCopyToClipboard();
517
+
518
+ async function handleClick() {
519
+ const url = new URL(window.location.href);
520
+ url.hash = `#${id ?? ''}`;
521
+ await copyToClipboard(url.toString());
522
+ }
525
523
 
526
524
  return (
527
525
  <Tag id={id}>
@@ -1,24 +1,33 @@
1
- import { useEffect, useState } from 'react';
1
+ import { useEffect, useRef, useState } from 'react';
2
2
 
3
- interface UseCopyToClipboardProps {
4
- text: string;
5
- transform?: (text: string) => string;
3
+ interface UseCopyToClipboard {
4
+ isCopied: boolean;
5
+ copyToClipboard(textToCopy: string): Promise<void>;
6
6
  }
7
7
 
8
- export const useCopyToClipboard = ({ text, transform }: UseCopyToClipboardProps): [boolean, () => void] => {
9
- const [toCopy, setToCopy] = useState(text);
10
- const [isCopied, setCopied] = useState(false);
8
+ export function useCopyToClipboard(timeoutMs = 1000): UseCopyToClipboard {
9
+ const timeoutRef = useRef<NodeJS.Timeout | null>(null);
10
+ const [isCopied, setIsCopied] = useState<boolean>(false);
11
11
 
12
- const handleClick = async () => {
13
- await navigator.clipboard.writeText(toCopy);
14
- setCopied(true);
15
- setTimeout(() => setCopied(false), 1000);
16
- };
12
+ async function copyToClipboard(textToCopy: string) {
13
+ await navigator.clipboard.writeText(textToCopy);
14
+ setIsCopied(true);
15
+
16
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
17
+
18
+ timeoutRef.current = setTimeout(() => {
19
+ setIsCopied(false);
20
+ timeoutRef.current = null;
21
+ }, timeoutMs);
22
+ }
17
23
 
18
- // Need the useEffect because of SSR on web
19
24
  useEffect(() => {
20
- setToCopy(transform ? transform(text) : text);
21
- }, [text, transform]);
25
+ return () => {
26
+ if (!timeoutRef.current) return;
22
27
 
23
- return [isCopied, handleClick];
24
- };
28
+ clearTimeout(timeoutRef.current);
29
+ };
30
+ }, []);
31
+
32
+ return { copyToClipboard, isCopied };
33
+ }