@vendure-io/ui 2.0.0-beta.7 → 2.0.0-beta.8
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 +2 -2
- package/src/components/molecules/anonymized-token.tsx +2 -2
- package/src/components/molecules/code-block.tsx +14 -5
- package/src/components/molecules/copy-feedback-provider.tsx +33 -0
- package/src/components/molecules/copyable-text.tsx +16 -6
- package/src/components/molecules/id-chip.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vendure-io/ui",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.8",
|
|
4
4
|
"description": "React component library for Vendure, built on shadcn/ui and Tailwind v4",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"homepage": "https://github.com/vendurehq/design/tree/main/packages/ui",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@shikijs/themes": "^3.23.0",
|
|
50
50
|
"@shikijs/transformers": "^3.22.0",
|
|
51
51
|
"@tanstack/react-table": "^8.21.3",
|
|
52
|
-
"@vendure-io/design-tokens": "^2.0.0-beta.
|
|
52
|
+
"@vendure-io/design-tokens": "^2.0.0-beta.7",
|
|
53
53
|
"class-variance-authority": "^0.7.1",
|
|
54
54
|
"clsx": "^2.1.1",
|
|
55
55
|
"cmdk": "^1.1.1",
|
|
@@ -53,9 +53,9 @@ interface AnonymizedTokenProps extends Omit<React.ComponentProps<'span'>, 'child
|
|
|
53
53
|
copyable?: boolean;
|
|
54
54
|
/** How long the check-mark feedback stays visible, in ms. */
|
|
55
55
|
timeout?: CopyButtonProps['timeout'];
|
|
56
|
-
/** Called after a successful copy. Wire your toast here. */
|
|
56
|
+
/** Called after a successful copy. Wire your toast here. Falls back to `CopyFeedbackProvider`. */
|
|
57
57
|
onCopied?: CopyButtonProps['onCopied'];
|
|
58
|
-
/** Called when the clipboard write fails. */
|
|
58
|
+
/** Called when the clipboard write fails. Falls back to `CopyFeedbackProvider`. */
|
|
59
59
|
onCopyError?: CopyButtonProps['onCopyError'];
|
|
60
60
|
/** Accessible label before copying. @default "Copy token" */
|
|
61
61
|
copyLabel?: CopyButtonProps['copyLabel'];
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { Button } from '@vendure-io/ui/components/atoms/button';
|
|
11
11
|
import { ScrollArea, ScrollBar } from '@vendure-io/ui/components/atoms/scroll-area';
|
|
12
12
|
import { Tooltip, TooltipContent, TooltipTrigger } from '@vendure-io/ui/components/atoms/tooltip';
|
|
13
|
+
import { useCopyFeedback } from '@vendure-io/ui/components/molecules/copy-feedback-provider';
|
|
13
14
|
import { useCopy } from '@vendure-io/ui/hooks/use-copy';
|
|
14
15
|
import { cn } from '@vendure-io/ui/lib/utils';
|
|
15
16
|
import {
|
|
@@ -56,9 +57,14 @@ type CodeBlockProps = PropsWithChildren<ComponentProps<'div'>> & {
|
|
|
56
57
|
packageManagerSwitcher?: boolean;
|
|
57
58
|
/** Extra toolbar actions rendered before the built-in copy button. Compose with CodeBlockAction. */
|
|
58
59
|
actions?: ReactNode;
|
|
59
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Called after a successful copy. Wire your toast here. The DS never toasts.
|
|
62
|
+
* Function props can't cross an RSC boundary — when rendering from a server
|
|
63
|
+
* component, omit this and mount `CopyFeedbackProvider` instead; it is the
|
|
64
|
+
* fallback when no prop is passed.
|
|
65
|
+
*/
|
|
60
66
|
onCopied?: () => void;
|
|
61
|
-
/** Called when the clipboard write fails. */
|
|
67
|
+
/** Called when the clipboard write fails. Falls back to `CopyFeedbackProvider`. */
|
|
62
68
|
onCopyError?: (error: Error) => void;
|
|
63
69
|
};
|
|
64
70
|
|
|
@@ -975,7 +981,9 @@ function SyntaxHighlightedContent({ code, language }: SyntaxHighlightedContentPr
|
|
|
975
981
|
* long snippets, and an optional npm→pnpm/yarn/bun package-manager switcher.
|
|
976
982
|
* Highlighting is lazy (a shared highlighter singleton + per-snippet cache), and
|
|
977
983
|
* line/diff/focus/word decorations use Shiki's `[!code ...]` notations. The DS
|
|
978
|
-
* never toasts. Wire `onCopied`/`onCopyError` to your own feedback
|
|
984
|
+
* never toasts. Wire `onCopied`/`onCopyError` to your own feedback — or, when
|
|
985
|
+
* rendering from server components (where function props can't be passed),
|
|
986
|
+
* mount `CopyFeedbackProvider` once and leave the props off.
|
|
979
987
|
*/
|
|
980
988
|
export function CodeBlock({
|
|
981
989
|
className,
|
|
@@ -990,6 +998,7 @@ export function CodeBlock({
|
|
|
990
998
|
...props
|
|
991
999
|
}: CodeBlockProps) {
|
|
992
1000
|
const { copied, copy } = useCopy();
|
|
1001
|
+
const copyFeedback = useCopyFeedback();
|
|
993
1002
|
const [activePackageManager, setActivePackageManager] = usePackageManager();
|
|
994
1003
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
995
1004
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
@@ -1035,8 +1044,8 @@ export function CodeBlock({
|
|
|
1035
1044
|
|
|
1036
1045
|
const handleCopy = async () => {
|
|
1037
1046
|
const ok = await copy(displayCode);
|
|
1038
|
-
if (ok) onCopied?.();
|
|
1039
|
-
else onCopyError?.(new Error('Failed to copy to the clipboard'));
|
|
1047
|
+
if (ok) (onCopied ?? copyFeedback.onCopied)?.();
|
|
1048
|
+
else (onCopyError ?? copyFeedback.onCopyError)?.(new Error('Failed to copy to the clipboard'));
|
|
1040
1049
|
};
|
|
1041
1050
|
|
|
1042
1051
|
const toolbar = <CodeBlockToolbar onCopy={handleCopy} isCopied={copied} actions={actions} />;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createContext, type ReactNode, useContext, useMemo } from 'react';
|
|
4
|
+
|
|
5
|
+
// Function props can't cross a server→client boundary, so a copy surface
|
|
6
|
+
// rendered from RSC (e.g. MDX docs) could never receive an `onCopied` callback
|
|
7
|
+
// for toast wiring. This context is the RSC-safe alternative: mount
|
|
8
|
+
// CopyFeedbackProvider once in a client component (wire your toast there — the
|
|
9
|
+
// DS never toasts), and copy surfaces resolve their feedback in a fixed order —
|
|
10
|
+
// explicit prop → this context → nothing beyond the built-in copied icon.
|
|
11
|
+
interface CopyFeedbackContextValue {
|
|
12
|
+
/** Called after a successful copy. Wire your toast here — the DS never toasts. */
|
|
13
|
+
onCopied?: () => void;
|
|
14
|
+
/** Called when the clipboard write fails. */
|
|
15
|
+
onCopyError?: (error: Error) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const CopyFeedbackContext = createContext<CopyFeedbackContextValue>({});
|
|
19
|
+
|
|
20
|
+
function CopyFeedbackProvider({
|
|
21
|
+
children,
|
|
22
|
+
onCopied,
|
|
23
|
+
onCopyError,
|
|
24
|
+
}: CopyFeedbackContextValue & { children: ReactNode }) {
|
|
25
|
+
const value = useMemo(() => ({ onCopied, onCopyError }), [onCopied, onCopyError]);
|
|
26
|
+
return <CopyFeedbackContext.Provider value={value}>{children}</CopyFeedbackContext.Provider>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function useCopyFeedback(): CopyFeedbackContextValue {
|
|
30
|
+
return useContext(CopyFeedbackContext);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { CopyFeedbackProvider, useCopyFeedback, type CopyFeedbackContextValue };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { Button } from '@vendure-io/ui/components/atoms/button';
|
|
4
|
+
import { useCopyFeedback } from '@vendure-io/ui/components/molecules/copy-feedback-provider';
|
|
4
5
|
import { useCopy } from '@vendure-io/ui/hooks/use-copy';
|
|
5
6
|
import { cn } from '@vendure-io/ui/lib/utils';
|
|
6
7
|
import { CheckIcon, CopyIcon } from 'lucide-react';
|
|
@@ -11,9 +12,16 @@ interface CopyButtonProps extends Omit<React.ComponentProps<typeof Button>, 'val
|
|
|
11
12
|
value: string;
|
|
12
13
|
/** How long the check-mark feedback stays visible, in ms. @default 2000 */
|
|
13
14
|
timeout?: number;
|
|
14
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* Called after a successful copy. Wire your toast here — the DS never toasts.
|
|
17
|
+
* Falls back to `CopyFeedbackProvider` when omitted (the RSC-safe path, since
|
|
18
|
+
* function props can't be passed from server components).
|
|
19
|
+
*/
|
|
15
20
|
onCopied?: () => void;
|
|
16
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Called when the clipboard write fails (e.g. permissions, insecure context).
|
|
23
|
+
* Falls back to `CopyFeedbackProvider` when omitted.
|
|
24
|
+
*/
|
|
17
25
|
onCopyError?: (error: Error) => void;
|
|
18
26
|
/** Accessible label before copying. @default "Copy" */
|
|
19
27
|
copyLabel?: string;
|
|
@@ -40,6 +48,7 @@ function CopyButton({
|
|
|
40
48
|
...props
|
|
41
49
|
}: CopyButtonProps) {
|
|
42
50
|
const { copied, copy } = useCopy({ timeout });
|
|
51
|
+
const copyFeedback = useCopyFeedback();
|
|
43
52
|
|
|
44
53
|
return (
|
|
45
54
|
<Button
|
|
@@ -53,8 +62,9 @@ function CopyButton({
|
|
|
53
62
|
onClick?.(event);
|
|
54
63
|
if (event.defaultPrevented) return;
|
|
55
64
|
const ok = await copy(value);
|
|
56
|
-
if (ok) onCopied?.();
|
|
57
|
-
else
|
|
65
|
+
if (ok) (onCopied ?? copyFeedback.onCopied)?.();
|
|
66
|
+
else
|
|
67
|
+
(onCopyError ?? copyFeedback.onCopyError)?.(new Error('Failed to copy to the clipboard'));
|
|
58
68
|
}}
|
|
59
69
|
{...props}
|
|
60
70
|
>
|
|
@@ -71,9 +81,9 @@ interface CopyableTextProps {
|
|
|
71
81
|
className?: string;
|
|
72
82
|
/** How long the check-mark feedback stays visible, in ms. @default 2000 */
|
|
73
83
|
timeout?: number;
|
|
74
|
-
/** Called after a successful copy. Wire your toast here — the DS never toasts. */
|
|
84
|
+
/** Called after a successful copy. Wire your toast here — the DS never toasts. Falls back to `CopyFeedbackProvider`. */
|
|
75
85
|
onCopied?: () => void;
|
|
76
|
-
/** Called when the clipboard write fails. */
|
|
86
|
+
/** Called when the clipboard write fails. Falls back to `CopyFeedbackProvider`. */
|
|
77
87
|
onCopyError?: (error: Error) => void;
|
|
78
88
|
}
|
|
79
89
|
|
|
@@ -40,7 +40,7 @@ interface IdChipProps {
|
|
|
40
40
|
/** Render the copy affordance. @default true */
|
|
41
41
|
copyable?: boolean;
|
|
42
42
|
className?: string;
|
|
43
|
-
/** Called after a successful copy. Wire your toast here — the DS never toasts. */
|
|
43
|
+
/** Called after a successful copy. Wire your toast here — the DS never toasts. Falls back to `CopyFeedbackProvider`. */
|
|
44
44
|
onCopied?: () => void;
|
|
45
45
|
}
|
|
46
46
|
|