@kushagradhawan/kookie-blocks 0.1.9 → 0.1.10
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.
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var I=Object.create;var
|
|
1
|
+
"use strict";var I=Object.create;var y=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var _=Object.getOwnPropertyNames;var z=Object.getPrototypeOf,D=Object.prototype.hasOwnProperty;var $=(r,o)=>{for(var t in o)y(r,t,{get:o[t],enumerable:!0})},S=(r,o,t,s)=>{if(o&&typeof o=="object"||typeof o=="function")for(let l of _(o))!D.call(r,l)&&l!==t&&y(r,l,{get:()=>o[l],enumerable:!(s=A(o,l))||s.enumerable});return r};var M=(r,o,t)=>(t=r!=null?I(z(r)):{},S(o||!r||!r.__esModule?y(t,"default",{value:r,enumerable:!0}):t,r)),W=r=>S(y({},"__esModule",{value:!0}),r);var X={};$(X,{CodeBlock:()=>J,useCodeBlockContext:()=>Q});module.exports=W(X);var e=M(require("react")),n=require("@kushagradhawan/kookie-ui"),w=require("@hugeicons/react"),f=require("@hugeicons/core-free-icons"),B=require("shiki"),x=require("./types"),v=require("./useCodeCard"),T=require("./LanguageBadge");const L=(0,e.createContext)(!1),O=360,U="one-light",j="one-dark-pro";function G({children:r,background:o="none",backgroundProps:t={}}){const{dotSize:s=24,color:l="var(--gray-10)",backgroundColor:c="var(--gray-2)",height:i,width:u="100%",radius:d="3"}=t,a=(0,e.useMemo)(()=>{if(o!=="none")return o==="dots"?{backgroundImage:`radial-gradient(circle, ${l} 1px, transparent 1px)`,borderRadius:`var(--radius-${d})`,backgroundSize:`${s}px ${s}px`,backgroundPosition:"center",backgroundColor:c,width:u,...i&&{height:i}}:{backgroundImage:`url(${o})`,backgroundSize:"cover",backgroundPosition:"center",backgroundRepeat:"no-repeat",borderRadius:`var(--radius-${d})`,width:u,...i&&{height:i}}},[o,l,c,s,i,u,d]);return e.default.createElement(n.Card,{size:"1",variant:"soft"},e.default.createElement(n.Flex,{justify:"center",align:"center",py:"4",style:a},e.default.createElement(n.Theme,{fontFamily:"sans"},r)))}function K(){return e.default.createElement(n.Box,{className:"code-skeleton"},["85%","70%","90%","60%","75%","80%"].map((o,t)=>e.default.createElement(n.Box,{key:t,className:"code-skeleton-line",style:{width:o}})))}const P=(0,e.memo)(function({code:o,language:t,showCopy:s,showLanguage:l,showLineNumbers:c,collapsible:i,collapsedHeight:u,file:d,isLoading:a=!1,children:p}){const{isExpanded:g,shouldShowToggle:h,copied:C,contentRef:m,contentMaxHeight:b,handleToggle:N,handleCopy:H}=(0,v.useCodeCard)({code:o,collapsedHeight:u}),k=i&&h,E=g?"rotate(180deg)":"rotate(0deg)",F=c?"code-content":"code-content hide-line-numbers";return e.default.createElement(n.Box,{position:"relative"},e.default.createElement(n.Card,{size:"1",variant:"soft"},e.default.createElement(n.Flex,{direction:"column"},e.default.createElement(n.Flex,{justify:"between",align:"start",gap:"2"},e.default.createElement(n.Flex,{align:"center",gap:"2"},l&&e.default.createElement(T.LanguageBadge,{language:t}),d&&e.default.createElement(n.Text,{size:"1",color:"gray",highContrast:!0},d)),e.default.createElement(n.Flex,{align:"center",className:"code-action-buttons"},k&&e.default.createElement(n.IconButton,{size:"2",variant:"ghost",color:"gray",onClick:N,tooltip:g?"Collapse":"Expand","aria-label":g?"Collapse code":"Expand code"},e.default.createElement(w.HugeiconsIcon,{icon:f.ArrowDown01Icon,style:{transform:E},className:"code-chevron",strokeWidth:1.75})),s&&e.default.createElement(n.Button,{size:"2",variant:"ghost",color:"gray",onClick:H,tooltip:C?"Copied!":"Copy","aria-label":C?"Copied!":"Copy code"},e.default.createElement(w.HugeiconsIcon,{icon:C?f.Tick01Icon:f.Copy01Icon,strokeWidth:1.75})," Copy"))),e.default.createElement(n.Box,{ref:m,style:{maxHeight:i?`${b}px`:void 0},className:F},e.default.createElement(n.ScrollArea,{type:"auto",scrollbars:"horizontal"},a?e.default.createElement(K,null):p)),k&&!g&&e.default.createElement(n.Box,{className:"code-scroll-shadow visible"}))))}),V=(0,e.memo)(function({code:o,language:t,showCopy:s,showLanguage:l,showLineNumbers:c,collapsible:i,collapsedHeight:u,file:d,shikiConfig:a}){const[p,g]=(0,e.useState)(null),h=(0,e.useMemo)(()=>{const m=a?.themes?.light||U,b=a?.themes?.dark||j;return{lang:t,themes:{light:m,dark:b},defaultColor:!1,langAlias:a?.langAlias,transformers:a?.transformers,meta:a?.meta?{__raw:a.meta}:void 0}},[t,a?.themes?.light,a?.themes?.dark,a?.langAlias,a?.transformers,a?.meta]);return(0,e.useEffect)(()=>{let m=!1;return(0,B.codeToHtml)(o,h).then(b=>{m||g(b)}).catch(b=>{}),()=>{m=!0}},[o,h]),e.default.createElement(P,{code:o,language:t,showCopy:s,showLanguage:l,showLineNumbers:c,collapsible:i,collapsedHeight:u,file:d,isLoading:p===null},p?e.default.createElement(n.Box,{dangerouslySetInnerHTML:{__html:p}}):null)}),q=(0,e.memo)(function({children:o,showCopy:t,showLanguage:s,showLineNumbers:l,collapsible:c,collapsedHeight:i,file:u}){const d=(0,x.extractTextFromChildren)(o),a=(0,x.extractLanguageFromChildren)(o);return e.default.createElement(P,{code:d,language:a,showCopy:t,showLanguage:s,showLineNumbers:l,collapsible:c,collapsedHeight:i,file:u},o)});function J({children:r,code:o,language:t,preview:s,showCopy:l=!0,showLanguage:c=!0,showLineNumbers:i=!0,shikiConfig:u,background:d,backgroundProps:a,collapsible:p=!0,collapsedHeight:g=O,file:h}){const C=t||(0,x.extractLanguageFromChildren)(r)||"text";return e.default.createElement(L.Provider,{value:!0},e.default.createElement(n.Box,{className:"docs-code-block",mt:"6",mb:"8"},e.default.createElement(n.Flex,{direction:"column",gap:"2"},s&&e.default.createElement(G,{background:d,backgroundProps:a},s),o&&e.default.createElement(V,{code:o,language:C,showCopy:l,showLanguage:c,showLineNumbers:i,collapsible:p,collapsedHeight:g,file:h,shikiConfig:u}),r&&!o&&e.default.createElement(q,{showCopy:l,showLanguage:c,showLineNumbers:i,collapsible:p,collapsedHeight:g,file:h},r))))}function Q(){return(0,e.useContext)(L)}
|
|
2
2
|
//# sourceMappingURL=CodeBlock.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/code/CodeBlock.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { useState, useEffect, useMemo, memo, createContext, useContext, type ReactNode } from \"react\";\nimport { Box, Card, Code, Flex, Button, Text, Theme, ScrollArea, IconButton } from \"@kushagradhawan/kookie-ui\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { Copy01Icon, Tick01Icon, ArrowDown01Icon } from \"@hugeicons/core-free-icons\";\nimport { codeToHtml, type BundledLanguage, type BundledTheme } from \"shiki\";\nimport type { CodeBlockProps, ShikiConfig, PreviewBackgroundProps } from \"./types\";\nimport { extractTextFromChildren, extractLanguageFromChildren } from \"./types\";\nimport { useCodeCard } from \"./useCodeCard\";\nimport { LanguageBadge } from \"./LanguageBadge\";\n\nconst CodeBlockContext = createContext<boolean>(false);\n\nconst DEFAULT_COLLAPSED_HEIGHT = 360;\nconst DEFAULT_LIGHT_THEME = \"one-light\";\nconst DEFAULT_DARK_THEME = \"one-dark-pro\";\n\ninterface PreviewSectionProps {\n children: ReactNode;\n background?: \"none\" | \"dots\" | string;\n backgroundProps?: PreviewBackgroundProps;\n}\n\nfunction PreviewSection({ children, background = \"none\", backgroundProps = {} }: PreviewSectionProps) {\n const { dotSize = 24, color = \"var(--gray-10)\", backgroundColor = \"var(--gray-2)\", height, width = \"100%\", radius = \"3\" } = backgroundProps;\n\n const backgroundStyle = useMemo((): React.CSSProperties | undefined => {\n if (background === \"none\") return undefined;\n\n if (background === \"dots\") {\n return {\n backgroundImage: `radial-gradient(circle, ${color} 1px, transparent 1px)`,\n borderRadius: `var(--radius-${radius})`,\n backgroundSize: `${dotSize}px ${dotSize}px`,\n backgroundPosition: \"center\",\n backgroundColor,\n width,\n ...(height && { height }),\n };\n }\n\n // Image background\n return {\n backgroundImage: `url(${background})`,\n backgroundSize: \"cover\",\n backgroundPosition: \"center\",\n backgroundRepeat: \"no-repeat\",\n borderRadius: `var(--radius-${radius})`,\n width,\n ...(height && { height }),\n };\n }, [background, color, backgroundColor, dotSize, height, width, radius]);\n\n return (\n <Card size=\"1\" variant=\"soft\">\n <Flex justify=\"center\" align=\"center\" py=\"4\" style={backgroundStyle}>\n <Theme fontFamily=\"sans\">{children}</Theme>\n </Flex>\n </Card>\n );\n}\n\ninterface CodeCardProps {\n code: string;\n language: string;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n isLoading?: boolean;\n children: ReactNode;\n}\n\nfunction CodeSkeleton() {\n // Generate varied line widths for visual interest\n const lineWidths = [\"85%\", \"70%\", \"90%\", \"60%\", \"75%\", \"80%\"];\n\n return (\n <Box className=\"code-skeleton\">\n {lineWidths.map((width, index) => (\n <Box key={index} className=\"code-skeleton-line\" style={{ width }} />\n ))}\n </Box>\n );\n}\n\nconst CodeCard = memo(function CodeCard({\n code,\n language,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n isLoading = false,\n children,\n}: CodeCardProps) {\n const { isExpanded, shouldShowToggle, copied, contentRef, contentMaxHeight, handleToggle, handleCopy } = useCodeCard({\n code,\n collapsedHeight,\n });\n\n const showToggle = collapsible && shouldShowToggle;\n const chevronRotation = isExpanded ? \"rotate(180deg)\" : \"rotate(0deg)\";\n const contentClassName = showLineNumbers ? \"code-content\" : \"code-content hide-line-numbers\";\n\n return (\n <Box position=\"relative\">\n <Card size=\"1\" variant=\"soft\">\n <Flex direction=\"column\">\n <Flex justify=\"between\" align=\"start\" gap=\"2\">\n <Flex align=\"center\" gap=\"2\">\n {showLanguage && <LanguageBadge language={language} />}\n {file && (\n <Text size=\"1\" color=\"gray\" highContrast>\n {file}\n </Text>\n )}\n </Flex>\n\n <Flex align=\"center\" className=\"code-action-buttons\">\n {showToggle && (\n <IconButton\n size=\"2\"\n variant=\"ghost\"\n color=\"gray\"\n onClick={handleToggle}\n tooltip={isExpanded ? \"Collapse\" : \"Expand\"}\n aria-label={isExpanded ? \"Collapse code\" : \"Expand code\"}\n >\n <HugeiconsIcon icon={ArrowDown01Icon} style={{ transform: chevronRotation }} className=\"code-chevron\" strokeWidth={1.75} />\n </IconButton>\n )}\n {showCopy && (\n <Button\n size=\"2\"\n variant=\"ghost\"\n color=\"gray\"\n onClick={handleCopy}\n tooltip={copied ? \"Copied!\" : \"Copy\"}\n aria-label={copied ? \"Copied!\" : \"Copy code\"}\n >\n <HugeiconsIcon icon={copied ? Tick01Icon : Copy01Icon} strokeWidth={1.75} /> Copy\n </Button>\n )}\n </Flex>\n </Flex>\n\n <Box ref={contentRef} style={{ maxHeight: collapsible ? `${contentMaxHeight}px` : undefined }} className={contentClassName}>\n <ScrollArea type=\"auto\" scrollbars=\"horizontal\">\n {isLoading ? <CodeSkeleton /> : children}\n </ScrollArea>\n </Box>\n\n {showToggle && !isExpanded && <Box className=\"code-scroll-shadow visible\" />}\n </Flex>\n </Card>\n </Box>\n );\n});\n\ninterface RuntimeCodeSectionProps {\n code: string;\n language: string;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n shikiConfig?: ShikiConfig;\n}\n\nconst RuntimeCodeSection = memo(function RuntimeCodeSection({\n code,\n language,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n shikiConfig,\n}: RuntimeCodeSectionProps) {\n const [highlighted, setHighlighted] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n\n // Memoize Shiki config to prevent unnecessary re-highlights\n const shikiOptions = useMemo(() => {\n const lightTheme = shikiConfig?.themes?.light || DEFAULT_LIGHT_THEME;\n const darkTheme = shikiConfig?.themes?.dark || DEFAULT_DARK_THEME;\n\n return {\n lang: language as BundledLanguage,\n themes: {\n light: lightTheme as BundledTheme,\n dark: darkTheme as BundledTheme,\n },\n defaultColor: false as const,\n langAlias: shikiConfig?.langAlias,\n transformers: shikiConfig?.transformers,\n meta: shikiConfig?.meta ? { __raw: shikiConfig.meta } : undefined,\n };\n }, [language, shikiConfig?.themes?.light, shikiConfig?.themes?.dark, shikiConfig?.langAlias, shikiConfig?.transformers, shikiConfig?.meta]);\n\n useEffect(() => {\n let cancelled = false;\n setIsLoading(true);\n\n codeToHtml(code, shikiOptions)\n .then((html) => {\n if (!cancelled) {\n setHighlighted(html);\n setIsLoading(false);\n }\n })\n .catch((error) => {\n if (!cancelled) {\n setHighlighted(null);\n setIsLoading(false);\n if (process.env.NODE_ENV === \"development\") {\n console.error(\"[CodeBlock] Shiki highlighting failed:\", error);\n }\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [code, shikiOptions]);\n\n return (\n <CodeCard\n code={code}\n language={language}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n isLoading={isLoading}\n >\n {highlighted ? <Box dangerouslySetInnerHTML={{ __html: highlighted }} /> : null}\n </CodeCard>\n );\n});\n\ninterface ChildrenCodeSectionProps {\n children: ReactNode;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n}\n\nconst ChildrenCodeSection = memo(function ChildrenCodeSection({\n children,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n}: ChildrenCodeSectionProps) {\n const code = extractTextFromChildren(children);\n const language = extractLanguageFromChildren(children);\n\n return (\n <CodeCard\n code={code}\n language={language}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n >\n {children}\n </CodeCard>\n );\n});\n\nexport function CodeBlock({\n children,\n code,\n language,\n preview,\n showCopy = true,\n showLanguage = true,\n showLineNumbers = true,\n shikiConfig,\n background,\n backgroundProps,\n collapsible = true,\n collapsedHeight = DEFAULT_COLLAPSED_HEIGHT,\n file,\n}: CodeBlockProps) {\n const displayLanguage = language || extractLanguageFromChildren(children) || \"text\";\n\n return (\n <CodeBlockContext.Provider value={true}>\n <Box className=\"docs-code-block\" mt=\"6\" mb=\"8\">\n <Flex direction=\"column\" gap=\"2\">\n {preview && (\n <PreviewSection background={background} backgroundProps={backgroundProps}>\n {preview}\n </PreviewSection>\n )}\n\n {code && (\n <RuntimeCodeSection\n code={code}\n language={displayLanguage}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n shikiConfig={shikiConfig}\n />\n )}\n\n {children && !code && (\n <ChildrenCodeSection\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n >\n {children}\n </ChildrenCodeSection>\n )}\n </Flex>\n </Box>\n </CodeBlockContext.Provider>\n );\n}\n\nexport function useCodeBlockContext() {\n return useContext(CodeBlockContext);\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
6
|
-
"names": ["CodeBlock_exports", "__export", "CodeBlock", "useCodeBlockContext", "__toCommonJS", "import_react", "import_kookie_ui", "import_core_free_icons", "import_shiki", "import_types", "import_useCodeCard", "import_LanguageBadge", "CodeBlockContext", "DEFAULT_COLLAPSED_HEIGHT", "DEFAULT_LIGHT_THEME", "DEFAULT_DARK_THEME", "PreviewSection", "children", "background", "backgroundProps", "dotSize", "color", "backgroundColor", "height", "width", "radius", "backgroundStyle", "React", "CodeSkeleton", "index", "CodeCard", "code", "language", "showCopy", "showLanguage", "showLineNumbers", "collapsible", "collapsedHeight", "file", "isLoading", "isExpanded", "shouldShowToggle", "copied", "contentRef", "contentMaxHeight", "handleToggle", "handleCopy", "showToggle", "chevronRotation", "contentClassName", "RuntimeCodeSection", "shikiConfig", "highlighted", "setHighlighted", "
|
|
4
|
+
"sourcesContent": ["import React, { useState, useEffect, useMemo, memo, createContext, useContext, type ReactNode } from \"react\";\nimport { Box, Card, Code, Flex, Button, Text, Theme, ScrollArea, IconButton } from \"@kushagradhawan/kookie-ui\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { Copy01Icon, Tick01Icon, ArrowDown01Icon } from \"@hugeicons/core-free-icons\";\nimport { codeToHtml, type BundledLanguage, type BundledTheme } from \"shiki\";\nimport type { CodeBlockProps, ShikiConfig, PreviewBackgroundProps } from \"./types\";\nimport { extractTextFromChildren, extractLanguageFromChildren } from \"./types\";\nimport { useCodeCard } from \"./useCodeCard\";\nimport { LanguageBadge } from \"./LanguageBadge\";\n\nconst CodeBlockContext = createContext<boolean>(false);\n\nconst DEFAULT_COLLAPSED_HEIGHT = 360;\nconst DEFAULT_LIGHT_THEME = \"one-light\";\nconst DEFAULT_DARK_THEME = \"one-dark-pro\";\n\ninterface PreviewSectionProps {\n children: ReactNode;\n background?: \"none\" | \"dots\" | string;\n backgroundProps?: PreviewBackgroundProps;\n}\n\nfunction PreviewSection({ children, background = \"none\", backgroundProps = {} }: PreviewSectionProps) {\n const { dotSize = 24, color = \"var(--gray-10)\", backgroundColor = \"var(--gray-2)\", height, width = \"100%\", radius = \"3\" } = backgroundProps;\n\n const backgroundStyle = useMemo((): React.CSSProperties | undefined => {\n if (background === \"none\") return undefined;\n\n if (background === \"dots\") {\n return {\n backgroundImage: `radial-gradient(circle, ${color} 1px, transparent 1px)`,\n borderRadius: `var(--radius-${radius})`,\n backgroundSize: `${dotSize}px ${dotSize}px`,\n backgroundPosition: \"center\",\n backgroundColor,\n width,\n ...(height && { height }),\n };\n }\n\n // Image background\n return {\n backgroundImage: `url(${background})`,\n backgroundSize: \"cover\",\n backgroundPosition: \"center\",\n backgroundRepeat: \"no-repeat\",\n borderRadius: `var(--radius-${radius})`,\n width,\n ...(height && { height }),\n };\n }, [background, color, backgroundColor, dotSize, height, width, radius]);\n\n return (\n <Card size=\"1\" variant=\"soft\">\n <Flex justify=\"center\" align=\"center\" py=\"4\" style={backgroundStyle}>\n <Theme fontFamily=\"sans\">{children}</Theme>\n </Flex>\n </Card>\n );\n}\n\ninterface CodeCardProps {\n code: string;\n language: string;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n isLoading?: boolean;\n children: ReactNode;\n}\n\nfunction CodeSkeleton() {\n // Generate varied line widths for visual interest\n const lineWidths = [\"85%\", \"70%\", \"90%\", \"60%\", \"75%\", \"80%\"];\n\n return (\n <Box className=\"code-skeleton\">\n {lineWidths.map((width, index) => (\n <Box key={index} className=\"code-skeleton-line\" style={{ width }} />\n ))}\n </Box>\n );\n}\n\nconst CodeCard = memo(function CodeCard({\n code,\n language,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n isLoading = false,\n children,\n}: CodeCardProps) {\n const { isExpanded, shouldShowToggle, copied, contentRef, contentMaxHeight, handleToggle, handleCopy } = useCodeCard({\n code,\n collapsedHeight,\n });\n\n const showToggle = collapsible && shouldShowToggle;\n const chevronRotation = isExpanded ? \"rotate(180deg)\" : \"rotate(0deg)\";\n const contentClassName = showLineNumbers ? \"code-content\" : \"code-content hide-line-numbers\";\n\n return (\n <Box position=\"relative\">\n <Card size=\"1\" variant=\"soft\">\n <Flex direction=\"column\">\n <Flex justify=\"between\" align=\"start\" gap=\"2\">\n <Flex align=\"center\" gap=\"2\">\n {showLanguage && <LanguageBadge language={language} />}\n {file && (\n <Text size=\"1\" color=\"gray\" highContrast>\n {file}\n </Text>\n )}\n </Flex>\n\n <Flex align=\"center\" className=\"code-action-buttons\">\n {showToggle && (\n <IconButton\n size=\"2\"\n variant=\"ghost\"\n color=\"gray\"\n onClick={handleToggle}\n tooltip={isExpanded ? \"Collapse\" : \"Expand\"}\n aria-label={isExpanded ? \"Collapse code\" : \"Expand code\"}\n >\n <HugeiconsIcon icon={ArrowDown01Icon} style={{ transform: chevronRotation }} className=\"code-chevron\" strokeWidth={1.75} />\n </IconButton>\n )}\n {showCopy && (\n <Button\n size=\"2\"\n variant=\"ghost\"\n color=\"gray\"\n onClick={handleCopy}\n tooltip={copied ? \"Copied!\" : \"Copy\"}\n aria-label={copied ? \"Copied!\" : \"Copy code\"}\n >\n <HugeiconsIcon icon={copied ? Tick01Icon : Copy01Icon} strokeWidth={1.75} /> Copy\n </Button>\n )}\n </Flex>\n </Flex>\n\n <Box ref={contentRef} style={{ maxHeight: collapsible ? `${contentMaxHeight}px` : undefined }} className={contentClassName}>\n <ScrollArea type=\"auto\" scrollbars=\"horizontal\">\n {isLoading ? <CodeSkeleton /> : children}\n </ScrollArea>\n </Box>\n\n {showToggle && !isExpanded && <Box className=\"code-scroll-shadow visible\" />}\n </Flex>\n </Card>\n </Box>\n );\n});\n\ninterface RuntimeCodeSectionProps {\n code: string;\n language: string;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n shikiConfig?: ShikiConfig;\n}\n\nconst RuntimeCodeSection = memo(function RuntimeCodeSection({\n code,\n language,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n shikiConfig,\n}: RuntimeCodeSectionProps) {\n const [highlighted, setHighlighted] = useState<string | null>(null);\n\n // Memoize Shiki config to prevent unnecessary re-highlights\n const shikiOptions = useMemo(() => {\n const lightTheme = shikiConfig?.themes?.light || DEFAULT_LIGHT_THEME;\n const darkTheme = shikiConfig?.themes?.dark || DEFAULT_DARK_THEME;\n\n return {\n lang: language as BundledLanguage,\n themes: {\n light: lightTheme as BundledTheme,\n dark: darkTheme as BundledTheme,\n },\n defaultColor: false as const,\n langAlias: shikiConfig?.langAlias,\n transformers: shikiConfig?.transformers,\n meta: shikiConfig?.meta ? { __raw: shikiConfig.meta } : undefined,\n };\n }, [language, shikiConfig?.themes?.light, shikiConfig?.themes?.dark, shikiConfig?.langAlias, shikiConfig?.transformers, shikiConfig?.meta]);\n\n useEffect(() => {\n let cancelled = false;\n\n codeToHtml(code, shikiOptions)\n .then((html) => {\n if (!cancelled) {\n setHighlighted(html);\n }\n })\n .catch((error) => {\n if (!cancelled) {\n // Keep previous highlighted content on error (stale while revalidate)\n if (process.env.NODE_ENV === \"development\") {\n console.error(\"[CodeBlock] Shiki highlighting failed:\", error);\n }\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [code, shikiOptions]);\n\n // Only show loading skeleton on initial render (no highlighted content yet)\n // During updates, keep showing previous highlighted content (stale while revalidate)\n const isInitialLoading = highlighted === null;\n\n return (\n <CodeCard\n code={code}\n language={language}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n isLoading={isInitialLoading}\n >\n {highlighted ? <Box dangerouslySetInnerHTML={{ __html: highlighted }} /> : null}\n </CodeCard>\n );\n});\n\ninterface ChildrenCodeSectionProps {\n children: ReactNode;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n}\n\nconst ChildrenCodeSection = memo(function ChildrenCodeSection({\n children,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n}: ChildrenCodeSectionProps) {\n const code = extractTextFromChildren(children);\n const language = extractLanguageFromChildren(children);\n\n return (\n <CodeCard\n code={code}\n language={language}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n >\n {children}\n </CodeCard>\n );\n});\n\nexport function CodeBlock({\n children,\n code,\n language,\n preview,\n showCopy = true,\n showLanguage = true,\n showLineNumbers = true,\n shikiConfig,\n background,\n backgroundProps,\n collapsible = true,\n collapsedHeight = DEFAULT_COLLAPSED_HEIGHT,\n file,\n}: CodeBlockProps) {\n const displayLanguage = language || extractLanguageFromChildren(children) || \"text\";\n\n return (\n <CodeBlockContext.Provider value={true}>\n <Box className=\"docs-code-block\" mt=\"6\" mb=\"8\">\n <Flex direction=\"column\" gap=\"2\">\n {preview && (\n <PreviewSection background={background} backgroundProps={backgroundProps}>\n {preview}\n </PreviewSection>\n )}\n\n {code && (\n <RuntimeCodeSection\n code={code}\n language={displayLanguage}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n shikiConfig={shikiConfig}\n />\n )}\n\n {children && !code && (\n <ChildrenCodeSection\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n >\n {children}\n </ChildrenCodeSection>\n )}\n </Flex>\n </Box>\n </CodeBlockContext.Provider>\n );\n}\n\nexport function useCodeBlockContext() {\n return useContext(CodeBlockContext);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["CodeBlock_exports", "__export", "CodeBlock", "useCodeBlockContext", "__toCommonJS", "import_react", "import_kookie_ui", "import_core_free_icons", "import_shiki", "import_types", "import_useCodeCard", "import_LanguageBadge", "CodeBlockContext", "DEFAULT_COLLAPSED_HEIGHT", "DEFAULT_LIGHT_THEME", "DEFAULT_DARK_THEME", "PreviewSection", "children", "background", "backgroundProps", "dotSize", "color", "backgroundColor", "height", "width", "radius", "backgroundStyle", "React", "CodeSkeleton", "index", "CodeCard", "code", "language", "showCopy", "showLanguage", "showLineNumbers", "collapsible", "collapsedHeight", "file", "isLoading", "isExpanded", "shouldShowToggle", "copied", "contentRef", "contentMaxHeight", "handleToggle", "handleCopy", "showToggle", "chevronRotation", "contentClassName", "RuntimeCodeSection", "shikiConfig", "highlighted", "setHighlighted", "shikiOptions", "lightTheme", "darkTheme", "cancelled", "html", "error", "ChildrenCodeSection", "preview", "displayLanguage"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import e,{useState as
|
|
1
|
+
import e,{useState as E,useEffect as F,useMemo as w,memo as x,createContext as I,useContext as A}from"react";import{Box as m,Card as k,Flex as f,Button as _,Text as z,Theme as D,ScrollArea as $,IconButton as M}from"@kushagradhawan/kookie-ui";import{HugeiconsIcon as S}from"@hugeicons/react";import{Copy01Icon as W,Tick01Icon as O,ArrowDown01Icon as U}from"@hugeicons/core-free-icons";import{codeToHtml as j}from"shiki";import{extractTextFromChildren as G,extractLanguageFromChildren as L}from"./types";import{useCodeCard as K}from"./useCodeCard";import{LanguageBadge as V}from"./LanguageBadge";const P=I(!1),q=360,J="one-light",Q="one-dark-pro";function X({children:c,background:o="none",backgroundProps:t={}}){const{dotSize:a=24,color:s="var(--gray-10)",backgroundColor:i="var(--gray-2)",height:r,width:d="100%",radius:l="3"}=t,n=w(()=>{if(o!=="none")return o==="dots"?{backgroundImage:`radial-gradient(circle, ${s} 1px, transparent 1px)`,borderRadius:`var(--radius-${l})`,backgroundSize:`${a}px ${a}px`,backgroundPosition:"center",backgroundColor:i,width:d,...r&&{height:r}}:{backgroundImage:`url(${o})`,backgroundSize:"cover",backgroundPosition:"center",backgroundRepeat:"no-repeat",borderRadius:`var(--radius-${l})`,width:d,...r&&{height:r}}},[o,s,i,a,r,d,l]);return e.createElement(k,{size:"1",variant:"soft"},e.createElement(f,{justify:"center",align:"center",py:"4",style:n},e.createElement(D,{fontFamily:"sans"},c)))}function Y(){return e.createElement(m,{className:"code-skeleton"},["85%","70%","90%","60%","75%","80%"].map((o,t)=>e.createElement(m,{key:t,className:"code-skeleton-line",style:{width:o}})))}const B=x(function({code:o,language:t,showCopy:a,showLanguage:s,showLineNumbers:i,collapsible:r,collapsedHeight:d,file:l,isLoading:n=!1,children:g}){const{isExpanded:u,shouldShowToggle:p,copied:C,contentRef:h,contentMaxHeight:b,handleToggle:v,handleCopy:T}=K({code:o,collapsedHeight:d}),y=r&&p,N=u?"rotate(180deg)":"rotate(0deg)",H=i?"code-content":"code-content hide-line-numbers";return e.createElement(m,{position:"relative"},e.createElement(k,{size:"1",variant:"soft"},e.createElement(f,{direction:"column"},e.createElement(f,{justify:"between",align:"start",gap:"2"},e.createElement(f,{align:"center",gap:"2"},s&&e.createElement(V,{language:t}),l&&e.createElement(z,{size:"1",color:"gray",highContrast:!0},l)),e.createElement(f,{align:"center",className:"code-action-buttons"},y&&e.createElement(M,{size:"2",variant:"ghost",color:"gray",onClick:v,tooltip:u?"Collapse":"Expand","aria-label":u?"Collapse code":"Expand code"},e.createElement(S,{icon:U,style:{transform:N},className:"code-chevron",strokeWidth:1.75})),a&&e.createElement(_,{size:"2",variant:"ghost",color:"gray",onClick:T,tooltip:C?"Copied!":"Copy","aria-label":C?"Copied!":"Copy code"},e.createElement(S,{icon:C?O:W,strokeWidth:1.75})," Copy"))),e.createElement(m,{ref:h,style:{maxHeight:r?`${b}px`:void 0},className:H},e.createElement($,{type:"auto",scrollbars:"horizontal"},n?e.createElement(Y,null):g)),y&&!u&&e.createElement(m,{className:"code-scroll-shadow visible"}))))}),Z=x(function({code:o,language:t,showCopy:a,showLanguage:s,showLineNumbers:i,collapsible:r,collapsedHeight:d,file:l,shikiConfig:n}){const[g,u]=E(null),p=w(()=>{const h=n?.themes?.light||J,b=n?.themes?.dark||Q;return{lang:t,themes:{light:h,dark:b},defaultColor:!1,langAlias:n?.langAlias,transformers:n?.transformers,meta:n?.meta?{__raw:n.meta}:void 0}},[t,n?.themes?.light,n?.themes?.dark,n?.langAlias,n?.transformers,n?.meta]);return F(()=>{let h=!1;return j(o,p).then(b=>{h||u(b)}).catch(b=>{}),()=>{h=!0}},[o,p]),e.createElement(B,{code:o,language:t,showCopy:a,showLanguage:s,showLineNumbers:i,collapsible:r,collapsedHeight:d,file:l,isLoading:g===null},g?e.createElement(m,{dangerouslySetInnerHTML:{__html:g}}):null)}),R=x(function({children:o,showCopy:t,showLanguage:a,showLineNumbers:s,collapsible:i,collapsedHeight:r,file:d}){const l=G(o),n=L(o);return e.createElement(B,{code:l,language:n,showCopy:t,showLanguage:a,showLineNumbers:s,collapsible:i,collapsedHeight:r,file:d},o)});function de({children:c,code:o,language:t,preview:a,showCopy:s=!0,showLanguage:i=!0,showLineNumbers:r=!0,shikiConfig:d,background:l,backgroundProps:n,collapsible:g=!0,collapsedHeight:u=q,file:p}){const C=t||L(c)||"text";return e.createElement(P.Provider,{value:!0},e.createElement(m,{className:"docs-code-block",mt:"6",mb:"8"},e.createElement(f,{direction:"column",gap:"2"},a&&e.createElement(X,{background:l,backgroundProps:n},a),o&&e.createElement(Z,{code:o,language:C,showCopy:s,showLanguage:i,showLineNumbers:r,collapsible:g,collapsedHeight:u,file:p,shikiConfig:d}),c&&!o&&e.createElement(R,{showCopy:s,showLanguage:i,showLineNumbers:r,collapsible:g,collapsedHeight:u,file:p},c))))}function ce(){return A(P)}export{de as CodeBlock,ce as useCodeBlockContext};
|
|
2
2
|
//# sourceMappingURL=CodeBlock.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/code/CodeBlock.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { useState, useEffect, useMemo, memo, createContext, useContext, type ReactNode } from \"react\";\nimport { Box, Card, Code, Flex, Button, Text, Theme, ScrollArea, IconButton } from \"@kushagradhawan/kookie-ui\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { Copy01Icon, Tick01Icon, ArrowDown01Icon } from \"@hugeicons/core-free-icons\";\nimport { codeToHtml, type BundledLanguage, type BundledTheme } from \"shiki\";\nimport type { CodeBlockProps, ShikiConfig, PreviewBackgroundProps } from \"./types\";\nimport { extractTextFromChildren, extractLanguageFromChildren } from \"./types\";\nimport { useCodeCard } from \"./useCodeCard\";\nimport { LanguageBadge } from \"./LanguageBadge\";\n\nconst CodeBlockContext = createContext<boolean>(false);\n\nconst DEFAULT_COLLAPSED_HEIGHT = 360;\nconst DEFAULT_LIGHT_THEME = \"one-light\";\nconst DEFAULT_DARK_THEME = \"one-dark-pro\";\n\ninterface PreviewSectionProps {\n children: ReactNode;\n background?: \"none\" | \"dots\" | string;\n backgroundProps?: PreviewBackgroundProps;\n}\n\nfunction PreviewSection({ children, background = \"none\", backgroundProps = {} }: PreviewSectionProps) {\n const { dotSize = 24, color = \"var(--gray-10)\", backgroundColor = \"var(--gray-2)\", height, width = \"100%\", radius = \"3\" } = backgroundProps;\n\n const backgroundStyle = useMemo((): React.CSSProperties | undefined => {\n if (background === \"none\") return undefined;\n\n if (background === \"dots\") {\n return {\n backgroundImage: `radial-gradient(circle, ${color} 1px, transparent 1px)`,\n borderRadius: `var(--radius-${radius})`,\n backgroundSize: `${dotSize}px ${dotSize}px`,\n backgroundPosition: \"center\",\n backgroundColor,\n width,\n ...(height && { height }),\n };\n }\n\n // Image background\n return {\n backgroundImage: `url(${background})`,\n backgroundSize: \"cover\",\n backgroundPosition: \"center\",\n backgroundRepeat: \"no-repeat\",\n borderRadius: `var(--radius-${radius})`,\n width,\n ...(height && { height }),\n };\n }, [background, color, backgroundColor, dotSize, height, width, radius]);\n\n return (\n <Card size=\"1\" variant=\"soft\">\n <Flex justify=\"center\" align=\"center\" py=\"4\" style={backgroundStyle}>\n <Theme fontFamily=\"sans\">{children}</Theme>\n </Flex>\n </Card>\n );\n}\n\ninterface CodeCardProps {\n code: string;\n language: string;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n isLoading?: boolean;\n children: ReactNode;\n}\n\nfunction CodeSkeleton() {\n // Generate varied line widths for visual interest\n const lineWidths = [\"85%\", \"70%\", \"90%\", \"60%\", \"75%\", \"80%\"];\n\n return (\n <Box className=\"code-skeleton\">\n {lineWidths.map((width, index) => (\n <Box key={index} className=\"code-skeleton-line\" style={{ width }} />\n ))}\n </Box>\n );\n}\n\nconst CodeCard = memo(function CodeCard({\n code,\n language,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n isLoading = false,\n children,\n}: CodeCardProps) {\n const { isExpanded, shouldShowToggle, copied, contentRef, contentMaxHeight, handleToggle, handleCopy } = useCodeCard({\n code,\n collapsedHeight,\n });\n\n const showToggle = collapsible && shouldShowToggle;\n const chevronRotation = isExpanded ? \"rotate(180deg)\" : \"rotate(0deg)\";\n const contentClassName = showLineNumbers ? \"code-content\" : \"code-content hide-line-numbers\";\n\n return (\n <Box position=\"relative\">\n <Card size=\"1\" variant=\"soft\">\n <Flex direction=\"column\">\n <Flex justify=\"between\" align=\"start\" gap=\"2\">\n <Flex align=\"center\" gap=\"2\">\n {showLanguage && <LanguageBadge language={language} />}\n {file && (\n <Text size=\"1\" color=\"gray\" highContrast>\n {file}\n </Text>\n )}\n </Flex>\n\n <Flex align=\"center\" className=\"code-action-buttons\">\n {showToggle && (\n <IconButton\n size=\"2\"\n variant=\"ghost\"\n color=\"gray\"\n onClick={handleToggle}\n tooltip={isExpanded ? \"Collapse\" : \"Expand\"}\n aria-label={isExpanded ? \"Collapse code\" : \"Expand code\"}\n >\n <HugeiconsIcon icon={ArrowDown01Icon} style={{ transform: chevronRotation }} className=\"code-chevron\" strokeWidth={1.75} />\n </IconButton>\n )}\n {showCopy && (\n <Button\n size=\"2\"\n variant=\"ghost\"\n color=\"gray\"\n onClick={handleCopy}\n tooltip={copied ? \"Copied!\" : \"Copy\"}\n aria-label={copied ? \"Copied!\" : \"Copy code\"}\n >\n <HugeiconsIcon icon={copied ? Tick01Icon : Copy01Icon} strokeWidth={1.75} /> Copy\n </Button>\n )}\n </Flex>\n </Flex>\n\n <Box ref={contentRef} style={{ maxHeight: collapsible ? `${contentMaxHeight}px` : undefined }} className={contentClassName}>\n <ScrollArea type=\"auto\" scrollbars=\"horizontal\">\n {isLoading ? <CodeSkeleton /> : children}\n </ScrollArea>\n </Box>\n\n {showToggle && !isExpanded && <Box className=\"code-scroll-shadow visible\" />}\n </Flex>\n </Card>\n </Box>\n );\n});\n\ninterface RuntimeCodeSectionProps {\n code: string;\n language: string;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n shikiConfig?: ShikiConfig;\n}\n\nconst RuntimeCodeSection = memo(function RuntimeCodeSection({\n code,\n language,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n shikiConfig,\n}: RuntimeCodeSectionProps) {\n const [highlighted, setHighlighted] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(true);\n\n // Memoize Shiki config to prevent unnecessary re-highlights\n const shikiOptions = useMemo(() => {\n const lightTheme = shikiConfig?.themes?.light || DEFAULT_LIGHT_THEME;\n const darkTheme = shikiConfig?.themes?.dark || DEFAULT_DARK_THEME;\n\n return {\n lang: language as BundledLanguage,\n themes: {\n light: lightTheme as BundledTheme,\n dark: darkTheme as BundledTheme,\n },\n defaultColor: false as const,\n langAlias: shikiConfig?.langAlias,\n transformers: shikiConfig?.transformers,\n meta: shikiConfig?.meta ? { __raw: shikiConfig.meta } : undefined,\n };\n }, [language, shikiConfig?.themes?.light, shikiConfig?.themes?.dark, shikiConfig?.langAlias, shikiConfig?.transformers, shikiConfig?.meta]);\n\n useEffect(() => {\n let cancelled = false;\n setIsLoading(true);\n\n codeToHtml(code, shikiOptions)\n .then((html) => {\n if (!cancelled) {\n setHighlighted(html);\n setIsLoading(false);\n }\n })\n .catch((error) => {\n if (!cancelled) {\n setHighlighted(null);\n setIsLoading(false);\n if (process.env.NODE_ENV === \"development\") {\n console.error(\"[CodeBlock] Shiki highlighting failed:\", error);\n }\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [code, shikiOptions]);\n\n return (\n <CodeCard\n code={code}\n language={language}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n isLoading={isLoading}\n >\n {highlighted ? <Box dangerouslySetInnerHTML={{ __html: highlighted }} /> : null}\n </CodeCard>\n );\n});\n\ninterface ChildrenCodeSectionProps {\n children: ReactNode;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n}\n\nconst ChildrenCodeSection = memo(function ChildrenCodeSection({\n children,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n}: ChildrenCodeSectionProps) {\n const code = extractTextFromChildren(children);\n const language = extractLanguageFromChildren(children);\n\n return (\n <CodeCard\n code={code}\n language={language}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n >\n {children}\n </CodeCard>\n );\n});\n\nexport function CodeBlock({\n children,\n code,\n language,\n preview,\n showCopy = true,\n showLanguage = true,\n showLineNumbers = true,\n shikiConfig,\n background,\n backgroundProps,\n collapsible = true,\n collapsedHeight = DEFAULT_COLLAPSED_HEIGHT,\n file,\n}: CodeBlockProps) {\n const displayLanguage = language || extractLanguageFromChildren(children) || \"text\";\n\n return (\n <CodeBlockContext.Provider value={true}>\n <Box className=\"docs-code-block\" mt=\"6\" mb=\"8\">\n <Flex direction=\"column\" gap=\"2\">\n {preview && (\n <PreviewSection background={background} backgroundProps={backgroundProps}>\n {preview}\n </PreviewSection>\n )}\n\n {code && (\n <RuntimeCodeSection\n code={code}\n language={displayLanguage}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n shikiConfig={shikiConfig}\n />\n )}\n\n {children && !code && (\n <ChildrenCodeSection\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n >\n {children}\n </ChildrenCodeSection>\n )}\n </Flex>\n </Box>\n </CodeBlockContext.Provider>\n );\n}\n\nexport function useCodeBlockContext() {\n return useContext(CodeBlockContext);\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
6
|
-
"names": ["React", "useState", "useEffect", "useMemo", "memo", "createContext", "useContext", "Box", "Card", "Flex", "Button", "Text", "Theme", "ScrollArea", "IconButton", "HugeiconsIcon", "Copy01Icon", "Tick01Icon", "ArrowDown01Icon", "codeToHtml", "extractTextFromChildren", "extractLanguageFromChildren", "useCodeCard", "LanguageBadge", "CodeBlockContext", "DEFAULT_COLLAPSED_HEIGHT", "DEFAULT_LIGHT_THEME", "DEFAULT_DARK_THEME", "PreviewSection", "children", "background", "backgroundProps", "dotSize", "color", "backgroundColor", "height", "width", "radius", "backgroundStyle", "CodeSkeleton", "index", "CodeCard", "code", "language", "showCopy", "showLanguage", "showLineNumbers", "collapsible", "collapsedHeight", "file", "isLoading", "isExpanded", "shouldShowToggle", "copied", "contentRef", "contentMaxHeight", "handleToggle", "handleCopy", "showToggle", "chevronRotation", "contentClassName", "RuntimeCodeSection", "shikiConfig", "highlighted", "setHighlighted", "
|
|
4
|
+
"sourcesContent": ["import React, { useState, useEffect, useMemo, memo, createContext, useContext, type ReactNode } from \"react\";\nimport { Box, Card, Code, Flex, Button, Text, Theme, ScrollArea, IconButton } from \"@kushagradhawan/kookie-ui\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { Copy01Icon, Tick01Icon, ArrowDown01Icon } from \"@hugeicons/core-free-icons\";\nimport { codeToHtml, type BundledLanguage, type BundledTheme } from \"shiki\";\nimport type { CodeBlockProps, ShikiConfig, PreviewBackgroundProps } from \"./types\";\nimport { extractTextFromChildren, extractLanguageFromChildren } from \"./types\";\nimport { useCodeCard } from \"./useCodeCard\";\nimport { LanguageBadge } from \"./LanguageBadge\";\n\nconst CodeBlockContext = createContext<boolean>(false);\n\nconst DEFAULT_COLLAPSED_HEIGHT = 360;\nconst DEFAULT_LIGHT_THEME = \"one-light\";\nconst DEFAULT_DARK_THEME = \"one-dark-pro\";\n\ninterface PreviewSectionProps {\n children: ReactNode;\n background?: \"none\" | \"dots\" | string;\n backgroundProps?: PreviewBackgroundProps;\n}\n\nfunction PreviewSection({ children, background = \"none\", backgroundProps = {} }: PreviewSectionProps) {\n const { dotSize = 24, color = \"var(--gray-10)\", backgroundColor = \"var(--gray-2)\", height, width = \"100%\", radius = \"3\" } = backgroundProps;\n\n const backgroundStyle = useMemo((): React.CSSProperties | undefined => {\n if (background === \"none\") return undefined;\n\n if (background === \"dots\") {\n return {\n backgroundImage: `radial-gradient(circle, ${color} 1px, transparent 1px)`,\n borderRadius: `var(--radius-${radius})`,\n backgroundSize: `${dotSize}px ${dotSize}px`,\n backgroundPosition: \"center\",\n backgroundColor,\n width,\n ...(height && { height }),\n };\n }\n\n // Image background\n return {\n backgroundImage: `url(${background})`,\n backgroundSize: \"cover\",\n backgroundPosition: \"center\",\n backgroundRepeat: \"no-repeat\",\n borderRadius: `var(--radius-${radius})`,\n width,\n ...(height && { height }),\n };\n }, [background, color, backgroundColor, dotSize, height, width, radius]);\n\n return (\n <Card size=\"1\" variant=\"soft\">\n <Flex justify=\"center\" align=\"center\" py=\"4\" style={backgroundStyle}>\n <Theme fontFamily=\"sans\">{children}</Theme>\n </Flex>\n </Card>\n );\n}\n\ninterface CodeCardProps {\n code: string;\n language: string;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n isLoading?: boolean;\n children: ReactNode;\n}\n\nfunction CodeSkeleton() {\n // Generate varied line widths for visual interest\n const lineWidths = [\"85%\", \"70%\", \"90%\", \"60%\", \"75%\", \"80%\"];\n\n return (\n <Box className=\"code-skeleton\">\n {lineWidths.map((width, index) => (\n <Box key={index} className=\"code-skeleton-line\" style={{ width }} />\n ))}\n </Box>\n );\n}\n\nconst CodeCard = memo(function CodeCard({\n code,\n language,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n isLoading = false,\n children,\n}: CodeCardProps) {\n const { isExpanded, shouldShowToggle, copied, contentRef, contentMaxHeight, handleToggle, handleCopy } = useCodeCard({\n code,\n collapsedHeight,\n });\n\n const showToggle = collapsible && shouldShowToggle;\n const chevronRotation = isExpanded ? \"rotate(180deg)\" : \"rotate(0deg)\";\n const contentClassName = showLineNumbers ? \"code-content\" : \"code-content hide-line-numbers\";\n\n return (\n <Box position=\"relative\">\n <Card size=\"1\" variant=\"soft\">\n <Flex direction=\"column\">\n <Flex justify=\"between\" align=\"start\" gap=\"2\">\n <Flex align=\"center\" gap=\"2\">\n {showLanguage && <LanguageBadge language={language} />}\n {file && (\n <Text size=\"1\" color=\"gray\" highContrast>\n {file}\n </Text>\n )}\n </Flex>\n\n <Flex align=\"center\" className=\"code-action-buttons\">\n {showToggle && (\n <IconButton\n size=\"2\"\n variant=\"ghost\"\n color=\"gray\"\n onClick={handleToggle}\n tooltip={isExpanded ? \"Collapse\" : \"Expand\"}\n aria-label={isExpanded ? \"Collapse code\" : \"Expand code\"}\n >\n <HugeiconsIcon icon={ArrowDown01Icon} style={{ transform: chevronRotation }} className=\"code-chevron\" strokeWidth={1.75} />\n </IconButton>\n )}\n {showCopy && (\n <Button\n size=\"2\"\n variant=\"ghost\"\n color=\"gray\"\n onClick={handleCopy}\n tooltip={copied ? \"Copied!\" : \"Copy\"}\n aria-label={copied ? \"Copied!\" : \"Copy code\"}\n >\n <HugeiconsIcon icon={copied ? Tick01Icon : Copy01Icon} strokeWidth={1.75} /> Copy\n </Button>\n )}\n </Flex>\n </Flex>\n\n <Box ref={contentRef} style={{ maxHeight: collapsible ? `${contentMaxHeight}px` : undefined }} className={contentClassName}>\n <ScrollArea type=\"auto\" scrollbars=\"horizontal\">\n {isLoading ? <CodeSkeleton /> : children}\n </ScrollArea>\n </Box>\n\n {showToggle && !isExpanded && <Box className=\"code-scroll-shadow visible\" />}\n </Flex>\n </Card>\n </Box>\n );\n});\n\ninterface RuntimeCodeSectionProps {\n code: string;\n language: string;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n shikiConfig?: ShikiConfig;\n}\n\nconst RuntimeCodeSection = memo(function RuntimeCodeSection({\n code,\n language,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n shikiConfig,\n}: RuntimeCodeSectionProps) {\n const [highlighted, setHighlighted] = useState<string | null>(null);\n\n // Memoize Shiki config to prevent unnecessary re-highlights\n const shikiOptions = useMemo(() => {\n const lightTheme = shikiConfig?.themes?.light || DEFAULT_LIGHT_THEME;\n const darkTheme = shikiConfig?.themes?.dark || DEFAULT_DARK_THEME;\n\n return {\n lang: language as BundledLanguage,\n themes: {\n light: lightTheme as BundledTheme,\n dark: darkTheme as BundledTheme,\n },\n defaultColor: false as const,\n langAlias: shikiConfig?.langAlias,\n transformers: shikiConfig?.transformers,\n meta: shikiConfig?.meta ? { __raw: shikiConfig.meta } : undefined,\n };\n }, [language, shikiConfig?.themes?.light, shikiConfig?.themes?.dark, shikiConfig?.langAlias, shikiConfig?.transformers, shikiConfig?.meta]);\n\n useEffect(() => {\n let cancelled = false;\n\n codeToHtml(code, shikiOptions)\n .then((html) => {\n if (!cancelled) {\n setHighlighted(html);\n }\n })\n .catch((error) => {\n if (!cancelled) {\n // Keep previous highlighted content on error (stale while revalidate)\n if (process.env.NODE_ENV === \"development\") {\n console.error(\"[CodeBlock] Shiki highlighting failed:\", error);\n }\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, [code, shikiOptions]);\n\n // Only show loading skeleton on initial render (no highlighted content yet)\n // During updates, keep showing previous highlighted content (stale while revalidate)\n const isInitialLoading = highlighted === null;\n\n return (\n <CodeCard\n code={code}\n language={language}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n isLoading={isInitialLoading}\n >\n {highlighted ? <Box dangerouslySetInnerHTML={{ __html: highlighted }} /> : null}\n </CodeCard>\n );\n});\n\ninterface ChildrenCodeSectionProps {\n children: ReactNode;\n showCopy: boolean;\n showLanguage: boolean;\n showLineNumbers: boolean;\n collapsible: boolean;\n collapsedHeight: number;\n file?: string;\n}\n\nconst ChildrenCodeSection = memo(function ChildrenCodeSection({\n children,\n showCopy,\n showLanguage,\n showLineNumbers,\n collapsible,\n collapsedHeight,\n file,\n}: ChildrenCodeSectionProps) {\n const code = extractTextFromChildren(children);\n const language = extractLanguageFromChildren(children);\n\n return (\n <CodeCard\n code={code}\n language={language}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n >\n {children}\n </CodeCard>\n );\n});\n\nexport function CodeBlock({\n children,\n code,\n language,\n preview,\n showCopy = true,\n showLanguage = true,\n showLineNumbers = true,\n shikiConfig,\n background,\n backgroundProps,\n collapsible = true,\n collapsedHeight = DEFAULT_COLLAPSED_HEIGHT,\n file,\n}: CodeBlockProps) {\n const displayLanguage = language || extractLanguageFromChildren(children) || \"text\";\n\n return (\n <CodeBlockContext.Provider value={true}>\n <Box className=\"docs-code-block\" mt=\"6\" mb=\"8\">\n <Flex direction=\"column\" gap=\"2\">\n {preview && (\n <PreviewSection background={background} backgroundProps={backgroundProps}>\n {preview}\n </PreviewSection>\n )}\n\n {code && (\n <RuntimeCodeSection\n code={code}\n language={displayLanguage}\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n shikiConfig={shikiConfig}\n />\n )}\n\n {children && !code && (\n <ChildrenCodeSection\n showCopy={showCopy}\n showLanguage={showLanguage}\n showLineNumbers={showLineNumbers}\n collapsible={collapsible}\n collapsedHeight={collapsedHeight}\n file={file}\n >\n {children}\n </ChildrenCodeSection>\n )}\n </Flex>\n </Box>\n </CodeBlockContext.Provider>\n );\n}\n\nexport function useCodeBlockContext() {\n return useContext(CodeBlockContext);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["React", "useState", "useEffect", "useMemo", "memo", "createContext", "useContext", "Box", "Card", "Flex", "Button", "Text", "Theme", "ScrollArea", "IconButton", "HugeiconsIcon", "Copy01Icon", "Tick01Icon", "ArrowDown01Icon", "codeToHtml", "extractTextFromChildren", "extractLanguageFromChildren", "useCodeCard", "LanguageBadge", "CodeBlockContext", "DEFAULT_COLLAPSED_HEIGHT", "DEFAULT_LIGHT_THEME", "DEFAULT_DARK_THEME", "PreviewSection", "children", "background", "backgroundProps", "dotSize", "color", "backgroundColor", "height", "width", "radius", "backgroundStyle", "CodeSkeleton", "index", "CodeCard", "code", "language", "showCopy", "showLanguage", "showLineNumbers", "collapsible", "collapsedHeight", "file", "isLoading", "isExpanded", "shouldShowToggle", "copied", "contentRef", "contentMaxHeight", "handleToggle", "handleCopy", "showToggle", "chevronRotation", "contentClassName", "RuntimeCodeSection", "shikiConfig", "highlighted", "setHighlighted", "shikiOptions", "lightTheme", "darkTheme", "cancelled", "html", "error", "ChildrenCodeSection", "CodeBlock", "preview", "displayLanguage", "useCodeBlockContext"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -185,7 +185,6 @@ const RuntimeCodeSection = memo(function RuntimeCodeSection({
|
|
|
185
185
|
shikiConfig,
|
|
186
186
|
}: RuntimeCodeSectionProps) {
|
|
187
187
|
const [highlighted, setHighlighted] = useState<string | null>(null);
|
|
188
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
189
188
|
|
|
190
189
|
// Memoize Shiki config to prevent unnecessary re-highlights
|
|
191
190
|
const shikiOptions = useMemo(() => {
|
|
@@ -207,19 +206,16 @@ const RuntimeCodeSection = memo(function RuntimeCodeSection({
|
|
|
207
206
|
|
|
208
207
|
useEffect(() => {
|
|
209
208
|
let cancelled = false;
|
|
210
|
-
setIsLoading(true);
|
|
211
209
|
|
|
212
210
|
codeToHtml(code, shikiOptions)
|
|
213
211
|
.then((html) => {
|
|
214
212
|
if (!cancelled) {
|
|
215
213
|
setHighlighted(html);
|
|
216
|
-
setIsLoading(false);
|
|
217
214
|
}
|
|
218
215
|
})
|
|
219
216
|
.catch((error) => {
|
|
220
217
|
if (!cancelled) {
|
|
221
|
-
|
|
222
|
-
setIsLoading(false);
|
|
218
|
+
// Keep previous highlighted content on error (stale while revalidate)
|
|
223
219
|
if (process.env.NODE_ENV === "development") {
|
|
224
220
|
console.error("[CodeBlock] Shiki highlighting failed:", error);
|
|
225
221
|
}
|
|
@@ -231,6 +227,10 @@ const RuntimeCodeSection = memo(function RuntimeCodeSection({
|
|
|
231
227
|
};
|
|
232
228
|
}, [code, shikiOptions]);
|
|
233
229
|
|
|
230
|
+
// Only show loading skeleton on initial render (no highlighted content yet)
|
|
231
|
+
// During updates, keep showing previous highlighted content (stale while revalidate)
|
|
232
|
+
const isInitialLoading = highlighted === null;
|
|
233
|
+
|
|
234
234
|
return (
|
|
235
235
|
<CodeCard
|
|
236
236
|
code={code}
|
|
@@ -241,7 +241,7 @@ const RuntimeCodeSection = memo(function RuntimeCodeSection({
|
|
|
241
241
|
collapsible={collapsible}
|
|
242
242
|
collapsedHeight={collapsedHeight}
|
|
243
243
|
file={file}
|
|
244
|
-
isLoading={
|
|
244
|
+
isLoading={isInitialLoading}
|
|
245
245
|
>
|
|
246
246
|
{highlighted ? <Box dangerouslySetInnerHTML={{ __html: highlighted }} /> : null}
|
|
247
247
|
</CodeCard>
|