Skip to content

Commit

Permalink
feat: add share code capabilities for the playground
Browse files Browse the repository at this point in the history
  • Loading branch information
YossiSaadi committed Mar 18, 2024
1 parent 2a6ac0a commit c2a7432
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 5 deletions.
10 changes: 10 additions & 0 deletions src/components/Editor/EditorToolbar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useCallback } from "react";
import {
useCopyToClipboard,
useShare,
useToolbarActions,
usePlaygroundArgs,
usePlaygroundState,
Expand Down Expand Up @@ -38,6 +39,7 @@ const EditorToolbar: React.FC = () => {
);

const { onCopy, isCopied, shouldAllowCopy } = useCopyToClipboard(code);
const { onShare, isShareCopied, shouldAllowShare } = useShare(code);

const { onFormatCode, onReset } = useToolbarActions(
code,
Expand All @@ -61,6 +63,14 @@ const EditorToolbar: React.FC = () => {
disabled={isCopied || !shouldAllowCopy}
onClick={onCopy}
/>
<EditorToolbarButton
tooltip={shouldAllowShare ? "" : "Editor is empty"}
text={isShareCopied ? "Copied!" : "Share"}
icon={isShareCopied ? "check" : "share"}
color={isShareCopied ? "green" : undefined}
disabled={isShareCopied || !shouldAllowShare}
onClick={onShare}
/>
<EditorToolbarButton
text="Format"
icon="paintbrush"
Expand Down
1 change: 1 addition & 0 deletions src/consts/editor-consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const SNIPPET_SHARE_QUERY_ID = "snippet";
1 change: 1 addition & 0 deletions src/consts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./addon-consts";
export * from "./parameter-consts";
export * from "./state-consts";
export * from "./events-consts";
export * from "./editor-consts";
1 change: 1 addition & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { default as usePlaygroundArgs } from "./usePlaygroundArgs";
export { default as usePlaygroundState } from "./usePlaygroundState";
export { default as useToolbarActions } from "./useToolbarActions";
export { default as useCopyToClipboard } from "./useCopyToClipboard";
export { default as useShare } from "./useShare";
export { default as useInitialCode } from "./useInitialCode";
export { default as useAutoOpenPlayground } from "./useAutoOpenPlayground";
export { default as useBroadcastEditorChanges } from "./useBroadcastEditorChanges";
Expand Down
30 changes: 25 additions & 5 deletions src/hooks/useInitialCode.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { useEffect, useMemo } from "react";
import { useAddonState, useParameter } from "@storybook/manager-api";
import {
useAddonState,
useParameter,
useStorybookApi,
} from "@storybook/manager-api";
import {
ADDON_ID_FOR_PARAMETERS,
DEFAULT_ADDON_PARAMETERS,
DEFAULT_ADDON_STATE,
PANEL_ID,
SNIPPET_SHARE_QUERY_ID,
} from "@/consts";
import { Code, PlaygroundParameters, PlaygroundState } from "@/types";
import { decodeAndDecompress } from "@/utils";

const useInitialCode = () => {
const { getQueryParam } = useStorybookApi();
const [state, setState] = useAddonState<PlaygroundState>(
PANEL_ID,
DEFAULT_ADDON_STATE
Expand All @@ -19,10 +26,23 @@ const useInitialCode = () => {
DEFAULT_ADDON_PARAMETERS
);

const initialCodeToSet = useMemo(
() => (hasValidCode(introCode) ? introCode : DEFAULT_ADDON_STATE.code),
[introCode]
);
const sharedCode = useMemo(() => {
const shared = getQueryParam(SNIPPET_SHARE_QUERY_ID);
if (!shared) {
return null;
}
return decodeAndDecompress(shared);
}, [getQueryParam]);

const initialCodeToSet = useMemo(() => {
if (hasValidCode(sharedCode)) {
return sharedCode;
}
if (hasValidCode(introCode)) {
return introCode;
}
return DEFAULT_ADDON_STATE.code;
}, [sharedCode, introCode]);

useEffect(() => {
if (hasInitialCodeLoaded || introCode === null) {
Expand Down
37 changes: 37 additions & 0 deletions src/hooks/useShare.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useCallback, useMemo, useState } from "react";
import { Code } from "@/types";
import { compressAndEncode } from "@/utils";
import { SNIPPET_SHARE_QUERY_ID } from "@/consts";
import usePlaygroundState from "./usePlaygroundState";

interface UseShareReturnType {
onShare: () => Promise<void>;
isShareCopied: boolean;
shouldAllowShare: boolean;
}

const useShare = (code: Code): UseShareReturnType => {
const { playgroundStoryBaseUrl } = usePlaygroundState();
const [isShareCopied, setShareCopied] = useState(false);

const shouldAllowShare = useMemo(
() => !code?.jsx && !code?.css,
[code?.css, code?.jsx]
);

const onShare = useCallback(async () => {
if (!shouldAllowShare) {
return;
}
const encoded = compressAndEncode(code);
const url = new URL(await playgroundStoryBaseUrl);
url.searchParams.append(SNIPPET_SHARE_QUERY_ID, encoded);
navigator.clipboard.writeText(url.href);
setShareCopied(true);
setTimeout(() => setShareCopied(false), 2000);
}, [code, playgroundStoryBaseUrl, shouldAllowShare]);

return { onShare, isShareCopied, shouldAllowShare };
};

export default useShare;

0 comments on commit c2a7432

Please sign in to comment.