From bac6763a80f69a1da66beed25eb98ffe0246be1f Mon Sep 17 00:00:00 2001 From: Gimle Larpes Date: Thu, 12 Jun 2025 23:05:21 +0200 Subject: [PATCH] add functionality --- src/app/components/editor/Elements.tsx | 2 +- src/app/plugins/react-custom-html-parser.tsx | 123 ++++++++++++++----- src/app/styles/CustomHtml.css.ts | 8 +- 3 files changed, 96 insertions(+), 37 deletions(-) diff --git a/src/app/components/editor/Elements.tsx b/src/app/components/editor/Elements.tsx index a7438ecd..6a6659b9 100644 --- a/src/app/components/editor/Elements.tsx +++ b/src/app/components/editor/Elements.tsx @@ -162,7 +162,7 @@ export function RenderElement({ attributes, element, children }: RenderElementPr visibility="Hover" hideTrack > -
{children}
+
{children}
); diff --git a/src/app/plugins/react-custom-html-parser.tsx b/src/app/plugins/react-custom-html-parser.tsx index 057b0dff..f0cf9609 100644 --- a/src/app/plugins/react-custom-html-parser.tsx +++ b/src/app/plugins/react-custom-html-parser.tsx @@ -4,6 +4,8 @@ import React, { ReactEventHandler, Suspense, lazy, + useCallback, + useMemo, useState, } from 'react'; import { @@ -202,45 +204,103 @@ export const highlightText = ( ); }); -export function CodeBlock(children: ChildNode[], opts: HTMLReactParserOptions) { - const [copied, setCopied] = useState(false); - const [collapsed, setCollapsed] = useState(false); - - //HANDLECOPY FUNCTION HERE? - const handleCopyClick = () => { - //const codeText = extractTextFromChildren(children); // IDK HOW THIS SHOULD BE DONE - //copyToClipboard(codeText); - - setCopied(true); - }; +type CodeBlockControlsProps = { + copied: boolean; + onCopy: () => void; + collapsible: boolean; + collapsed: boolean; + onToggle: () => void; +}; +function CodeBlockControls({ + copied, + onCopy, + collapsible, + collapsed, + onToggle, +}: CodeBlockControlsProps) { return ( - // Probably need a better copy icon - <> -
+ // Needs a better copy icon +
+ + + + {collapsible && ( { - handleCopyClick(); - }} - > - - - { - setCollapsed(!collapsed); - }} + onClick={onToggle} + aria-expanded={!collapsed} + aria-controls="code-block-content" + aria-label={collapsed ? 'Show Full Code Block' : 'Show Code Block Preview'} + style={collapsed ? { visibility: 'visible' } : {}} > -
- -
{domToReact(children, opts)}
+ )} +
+ ); +} + +export function CodeBlock(children: ChildNode[], opts: HTMLReactParserOptions) { + const LINE_LIMIT = 14; + + const extractTextFromChildren = useCallback((nodes: ChildNode[]): string => { + let text = ''; + + nodes.forEach((node) => { + if (node.type === 'text') { + text += node.data; + } else if (node instanceof Element && node.children) { + text += extractTextFromChildren(node.children); + } + }); + + return text; + }, []); + + const [copied, setCopied] = useState(false); + const collapsible = useMemo( + () => extractTextFromChildren(children).split('\n').length > LINE_LIMIT, + [children, extractTextFromChildren] + ); + const [collapsed, setCollapsed] = useState(collapsible); + + const handleCopy = useCallback(() => { + copyToClipboard(extractTextFromChildren(children)); + setCopied(true); + }, [children, extractTextFromChildren]); + + const toggleCollapse = useCallback(() => { + setCollapsed((prev) => !prev); + }, []); + + return ( + <> + + +
+ {domToReact(children, opts)} +
); @@ -321,8 +381,7 @@ export const getReactCustomHtmlParser = ( if (name === 'pre') { return ( - //SHOULD ALL OF THIS BE IN A renderCodeBlock function? not text, but one layr down - + {CodeBlock(children, opts)} ); diff --git a/src/app/styles/CustomHtml.css.ts b/src/app/styles/CustomHtml.css.ts index 95cb6dc5..e5e74b61 100644 --- a/src/app/styles/CustomHtml.css.ts +++ b/src/app/styles/CustomHtml.css.ts @@ -85,6 +85,7 @@ export const CodeBlock = style([ MarginSpaced, { fontStyle: 'normal', + position: 'relative', }, ]); export const CodeBlockInternal = recipe({ @@ -98,8 +99,7 @@ export const CodeBlockInternal = recipe({ variants: { collapsed: { true: { - maxHeight: config.space.S700, // should controls (collapse) be visible when collapsed? - yes, what's the best way to do this? - overflow: 'hidden', // collapse should also only be visible if the doc has more than 1 line + maxHeight: `calc(${config.size.ModalDrawerWidth} - ${config.lineHeight.T400} / 2)`, }, }, }, @@ -108,10 +108,10 @@ export const CodeBlockControls = style({ position: 'absolute', top: config.space.S200, right: config.space.S200, - display: 'none', + visibility: 'hidden', selectors: { [`${CodeBlock}:hover &`]: { - display: 'inline', + visibility: 'visible', }, }, });