@kushagradhawan/kookie-blocks 0.1.15 → 0.1.17
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/dist/cjs/components/code/code-block.js +1 -1
- package/dist/cjs/components/code/code-block.js.map +2 -2
- package/dist/cjs/components/markdown/create-markdown-components.d.ts.map +1 -1
- package/dist/cjs/components/markdown/create-markdown-components.js +2 -2
- package/dist/cjs/components/markdown/create-markdown-components.js.map +3 -3
- package/dist/cjs/components/markdown/streaming-markdown.d.ts.map +1 -1
- package/dist/cjs/components/markdown/streaming-markdown.js +1 -1
- package/dist/cjs/components/markdown/streaming-markdown.js.map +3 -3
- package/dist/cjs/components/markdown/types.d.ts +7 -0
- package/dist/cjs/components/markdown/types.d.ts.map +1 -1
- package/dist/cjs/components/markdown/types.js +1 -1
- package/dist/cjs/components/markdown/types.js.map +1 -1
- package/dist/esm/components/code/code-block.js +1 -1
- package/dist/esm/components/code/code-block.js.map +2 -2
- package/dist/esm/components/markdown/create-markdown-components.d.ts.map +1 -1
- package/dist/esm/components/markdown/create-markdown-components.js +2 -2
- package/dist/esm/components/markdown/create-markdown-components.js.map +3 -3
- package/dist/esm/components/markdown/streaming-markdown.d.ts.map +1 -1
- package/dist/esm/components/markdown/streaming-markdown.js +1 -1
- package/dist/esm/components/markdown/streaming-markdown.js.map +3 -3
- package/dist/esm/components/markdown/types.d.ts +7 -0
- package/dist/esm/components/markdown/types.d.ts.map +1 -1
- package/package.json +4 -1
- package/src/components/code/code-block.tsx +1 -1
- package/src/components/markdown/create-markdown-components.tsx +38 -24
- package/src/components/markdown/streaming-markdown.tsx +5 -1
- package/src/components/markdown/types.ts +8 -0
|
@@ -1,2 +1,2 @@
|
|
|
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("./use-code-card"),T=require("./language-badge");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",
|
|
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("./use-code-card"),T=require("./language-badge");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",my:"3"},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=code-block.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/code/code-block.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 \"./use-code-card\";\nimport { LanguageBadge } from \"./language-badge\";\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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
|
|
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 \"./use-code-card\";\nimport { LanguageBadge } from \"./language-badge\";\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\" my=\"3\">\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
6
|
"names": ["code_block_exports", "__export", "CodeBlock", "useCodeBlockContext", "__toCommonJS", "import_react", "import_kookie_ui", "import_core_free_icons", "import_shiki", "import_types", "import_use_code_card", "import_language_badge", "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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-markdown-components.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/create-markdown-components.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,KAAK,EAAE,wBAAwB,EAAyB,MAAM,SAAS,CAAC;AA8B/E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,wBAA6B,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"create-markdown-components.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/create-markdown-components.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,KAAK,EAAE,wBAAwB,EAAyB,MAAM,SAAS,CAAC;AA8B/E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,wBAA6B,GAAG,UAAU,CAiK3F"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`)&&
|
|
1
|
+
"use strict";var T=Object.create;var u=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var B=Object.getOwnPropertyNames;var H=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var z=(t,n)=>{for(var m in n)u(t,m,{get:n[m],enumerable:!0})},M=(t,n,m,h)=>{if(n&&typeof n=="object"||typeof n=="function")for(let l of B(n))!x.call(t,l)&&l!==m&&u(t,l,{get:()=>n[l],enumerable:!(h=c(n,l))||h.enumerable});return t};var I=(t,n,m)=>(m=t!=null?T(H(t)):{},M(n||!t||!t.__esModule?u(m,"default",{value:t,enumerable:!0}):m,t)),S=t=>M(u({},"__esModule",{value:!0}),t);var A={};z(A,{createMarkdownComponents:()=>v});module.exports=S(A);var e=I(require("react")),r=require("@kushagradhawan/kookie-ui"),k=require("../code");function L(t){return t?t.match(/language-([\w-]+)/i)?.[1]??"text":"text"}function q(t){let n="";return t?(typeof t=="string"?n=t:Array.isArray(t)&&(n=t.map(m=>typeof m=="string"?m:"").join("")),n.replace(/^\n+|\n+$/g,"")):n}function v(t={}){const{codeBlockCollapsible:n=!1,imageComponent:m,inlineCodeHighContrast:h=!0,spacing:l="spacious"}=t,i=l==="compact",s={h1:{top:i?"1.5rem":"3rem",bottom:i?"1rem":"1.5rem"},h2:{top:i?"2rem":"3rem",bottom:i?"0.375rem":"0.5rem"},h3:{top:i?"1.5rem":"2rem",bottom:i?"0.375rem":"0.5rem"},h4:{top:i?"0.5rem":"0.625rem",bottom:i?"0.25rem":"0.5rem"},h5:{top:i?"0.375rem":"0.5rem",bottom:i?"0.25rem":"0.5rem"},h6:{top:i?"0.375rem":"0.5rem",bottom:i?"0.25rem":"0.5rem"}},p=i?"0.25rem":"0.5rem",b=i?"0.125rem":"0.25rem",f=i?"1":"2",w=i?"0.375rem":"0.5rem",y=i?"0":"0.5rem",P=i?"0.5rem":"1rem";return{h1:({children:o})=>e.default.createElement(r.Heading,{size:"9",weight:"medium",as:"h1",style:{marginTop:s.h1.top,marginBottom:s.h1.bottom}},o),h2:({children:o})=>e.default.createElement(r.Heading,{weight:"medium",size:"7",as:"h2",style:{marginTop:s.h2.top,marginBottom:s.h2.bottom}},o),h3:({children:o})=>e.default.createElement(r.Heading,{weight:"medium",size:"5",as:"h3",style:{marginTop:s.h3.top,marginBottom:s.h3.bottom}},o),h4:({children:o})=>e.default.createElement(r.Heading,{weight:"medium",size:"4",as:"h4",style:{marginTop:s.h4.top,marginBottom:s.h4.bottom}},o),h5:({children:o})=>e.default.createElement(r.Heading,{weight:"medium",size:"3",as:"h5",style:{marginTop:s.h5.top,marginBottom:s.h5.bottom}},o),h6:({children:o})=>e.default.createElement(r.Heading,{weight:"medium",size:"2",as:"h6",style:{marginTop:s.h6.top,marginBottom:s.h6.bottom}},o),p:({children:o})=>e.default.createElement(r.Text,{size:"3",as:"p",style:{lineHeight:"1.6",marginTop:y,marginBottom:y}},o),code:({className:o,children:d,inline:g})=>{const a=q(d);return g===!0||g===void 0&&!o&&!a.includes(`
|
|
2
|
+
`)&&a.length<100?e.default.createElement(r.Code,{highContrast:h,size:"3"},a):e.default.createElement(r.Box,{my:f,style:{minWidth:0}},e.default.createElement(k.CodeBlock,{code:a,language:L(o),collapsible:n}))},ul:({children:o})=>e.default.createElement("ul",{style:{marginTop:p,marginBottom:p,lineHeight:"1.6",paddingLeft:"1.5rem",listStyleType:"disc"}},o),ol:({children:o})=>e.default.createElement("ol",{style:{marginTop:p,marginBottom:p,lineHeight:"1.6",paddingLeft:"1.5rem",listStyleType:"decimal"}},o),li:({children:o})=>e.default.createElement("li",{style:{marginBottom:b,lineHeight:"1.6"}},o),blockquote:({children:o})=>e.default.createElement(r.Blockquote,{size:"1",my:P},o),a:({href:o,children:d})=>e.default.createElement("a",{href:o,style:{color:"var(--accent-9)",textDecoration:"underline"}},d),strong:({children:o})=>e.default.createElement(r.Text,{weight:"medium",style:{lineHeight:"1.6"}},o),em:({children:o})=>e.default.createElement(r.Text,{style:{lineHeight:"1.6",fontStyle:"italic"}},o),hr:()=>e.default.createElement(r.Box,{style:{marginTop:w,marginBottom:w}},e.default.createElement(r.Separator,{orientation:"horizontal",light:!0})),pre:({children:o})=>e.default.createElement(e.default.Fragment,null,o),table:({children:o})=>e.default.createElement(r.Box,{my:"2",style:{overflowX:"auto"}},e.default.createElement(r.Table.Root,{size:"2",variant:"ghost"},o)),thead:({children:o})=>e.default.createElement(r.Table.Header,null,o),tbody:({children:o})=>e.default.createElement(r.Table.Body,null,o),tr:({children:o})=>e.default.createElement(r.Table.Row,null,o),th:({children:o})=>e.default.createElement(r.Table.ColumnHeaderCell,null,o),td:({children:o})=>e.default.createElement(r.Table.Cell,null,o),sub:({children:o})=>e.default.createElement("sub",null,o),sup:({children:o})=>e.default.createElement("sup",null,o),br:()=>e.default.createElement("br",null),img:m?o=>{const{src:d,alt:g,width:a,height:C}=o;return!d||typeof d!="string"?null:m({src:d,alt:g??"Image",width:a?String(a):void 0,height:C?String(C):void 0})}:void 0,details:({children:o})=>e.default.createElement("details",{style:{padding:"0.5rem 0"}},o),summary:({children:o})=>e.default.createElement("summary",{style:{cursor:"pointer",fontWeight:500}},o)}}
|
|
3
3
|
//# sourceMappingURL=create-markdown-components.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/markdown/create-markdown-components.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { type ReactNode } from \"react\";\nimport type { Components } from \"react-markdown\";\nimport { Blockquote, Box, Code, Flex, Heading, Text, Table } from \"@kushagradhawan/kookie-ui\";\nimport { CodeBlock } from \"../code\";\nimport type { MarkdownComponentOptions, MarkdownChildrenProps } from \"./types\";\n\n/**\n * Extracts language from className (e.g., \"language-typescript\" -> \"typescript\")\n */\nfunction extractLanguage(className?: string): string {\n if (!className) {\n return \"text\";\n }\n const match = className.match(/language-([\\w-]+)/i);\n return match?.[1] ?? \"text\";\n}\n\n/**\n * Extracts code string from ReactNode children\n */\nfunction extractCode(children?: ReactNode): string {\n let code = \"\";\n if (!children) {\n return code;\n }\n if (typeof children === \"string\") {\n code = children;\n } else if (Array.isArray(children)) {\n code = children.map((child) => (typeof child === \"string\" ? child : \"\")).join(\"\");\n }\n // Trim trailing newlines but preserve internal whitespace\n return code.replace(/^\\n+|\\n+$/g, \"\");\n}\n\n/**\n * Creates markdown component mappings that work with both react-markdown and MDX.\n * Uses KookieUI components for consistent styling across all projects.\n *\n * @param options - Optional configuration for component behavior\n * @returns Component mappings for markdown/MDX renderers\n *\n * @example\n * ```tsx\n * // In react-markdown\n * <ReactMarkdown components={createMarkdownComponents()}>\n * {content}\n * </ReactMarkdown>\n *\n * // In MDX\n * export function useMDXComponents(components: MDXComponents) {\n * return {\n * ...createMarkdownComponents(),\n * ...components,\n * };\n * }\n * ```\n */\nexport function createMarkdownComponents(options: MarkdownComponentOptions = {}): Components {\n const { codeBlockCollapsible = false, imageComponent, inlineCodeHighContrast = true } = options;\n\n return {\n // Headings with consistent visual hierarchy (9-6-5-4-3-2)\n h1: ({ children }: MarkdownChildrenProps) => (\n <Heading size=\"9\" weight=\"medium\" as=\"h1\" style={{ marginTop:
|
|
5
|
-
"mappings": "0jBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,8BAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAAsC,oBAEtCC,
|
|
6
|
-
"names": ["create_markdown_components_exports", "__export", "createMarkdownComponents", "__toCommonJS", "import_react", "import_kookie_ui", "import_code", "extractLanguage", "className", "extractCode", "children", "code", "child", "options", "codeBlockCollapsible", "imageComponent", "inlineCodeHighContrast", "React", "inline", "href", "props", "src", "alt", "width", "height"]
|
|
4
|
+
"sourcesContent": ["import React, { type ReactNode } from \"react\";\nimport type { Components } from \"react-markdown\";\nimport { Blockquote, Box, Code, Flex, Heading, Text, Table, Separator } from \"@kushagradhawan/kookie-ui\";\nimport { CodeBlock } from \"../code\";\nimport type { MarkdownComponentOptions, MarkdownChildrenProps } from \"./types\";\n\n/**\n * Extracts language from className (e.g., \"language-typescript\" -> \"typescript\")\n */\nfunction extractLanguage(className?: string): string {\n if (!className) {\n return \"text\";\n }\n const match = className.match(/language-([\\w-]+)/i);\n return match?.[1] ?? \"text\";\n}\n\n/**\n * Extracts code string from ReactNode children\n */\nfunction extractCode(children?: ReactNode): string {\n let code = \"\";\n if (!children) {\n return code;\n }\n if (typeof children === \"string\") {\n code = children;\n } else if (Array.isArray(children)) {\n code = children.map((child) => (typeof child === \"string\" ? child : \"\")).join(\"\");\n }\n // Trim trailing newlines but preserve internal whitespace\n return code.replace(/^\\n+|\\n+$/g, \"\");\n}\n\n/**\n * Creates markdown component mappings that work with both react-markdown and MDX.\n * Uses KookieUI components for consistent styling across all projects.\n *\n * @param options - Optional configuration for component behavior\n * @returns Component mappings for markdown/MDX renderers\n *\n * @example\n * ```tsx\n * // In react-markdown\n * <ReactMarkdown components={createMarkdownComponents()}>\n * {content}\n * </ReactMarkdown>\n *\n * // In MDX\n * export function useMDXComponents(components: MDXComponents) {\n * return {\n * ...createMarkdownComponents(),\n * ...components,\n * };\n * }\n * ```\n */\nexport function createMarkdownComponents(options: MarkdownComponentOptions = {}): Components {\n const { codeBlockCollapsible = false, imageComponent, inlineCodeHighContrast = true, spacing = \"spacious\" } = options;\n\n // Spacing configuration\n const isCompact = spacing === \"compact\";\n const headingMargins = {\n h1: { top: isCompact ? \"1.5rem\" : \"3rem\", bottom: isCompact ? \"1rem\" : \"1.5rem\" },\n h2: { top: isCompact ? \"2rem\" : \"3rem\", bottom: isCompact ? \"0.375rem\" : \"0.5rem\" },\n h3: { top: isCompact ? \"1.5rem\" : \"2rem\", bottom: isCompact ? \"0.375rem\" : \"0.5rem\" },\n h4: { top: isCompact ? \"0.5rem\" : \"0.625rem\", bottom: isCompact ? \"0.25rem\" : \"0.5rem\" },\n h5: { top: isCompact ? \"0.375rem\" : \"0.5rem\", bottom: isCompact ? \"0.25rem\" : \"0.5rem\" },\n h6: { top: isCompact ? \"0.375rem\" : \"0.5rem\", bottom: isCompact ? \"0.25rem\" : \"0.5rem\" },\n };\n const listMargin = isCompact ? \"0.25rem\" : \"0.5rem\";\n const listItemMargin = isCompact ? \"0.125rem\" : \"0.25rem\";\n const codeBlockMargin = isCompact ? \"1\" : \"2\";\n const hrMargin = isCompact ? \"0.375rem\" : \"0.5rem\";\n const paragraphMargin = isCompact ? \"0\" : \"0.5rem\";\n const blockquoteMargin = isCompact ? \"0.5rem\" : \"1rem\";\n\n return {\n // Headings with consistent visual hierarchy (9-6-5-4-3-2)\n h1: ({ children }: MarkdownChildrenProps) => (\n <Heading size=\"9\" weight=\"medium\" as=\"h1\" style={{ marginTop: headingMargins.h1.top, marginBottom: headingMargins.h1.bottom }}>\n {children}\n </Heading>\n ),\n h2: ({ children }: MarkdownChildrenProps) => (\n <Heading weight=\"medium\" size=\"7\" as=\"h2\" style={{ marginTop: headingMargins.h2.top, marginBottom: headingMargins.h2.bottom }}>\n {children}\n </Heading>\n ),\n h3: ({ children }: MarkdownChildrenProps) => (\n <Heading weight=\"medium\" size=\"5\" as=\"h3\" style={{ marginTop: headingMargins.h3.top, marginBottom: headingMargins.h3.bottom }}>\n {children}\n </Heading>\n ),\n h4: ({ children }: MarkdownChildrenProps) => (\n <Heading weight=\"medium\" size=\"4\" as=\"h4\" style={{ marginTop: headingMargins.h4.top, marginBottom: headingMargins.h4.bottom }}>\n {children}\n </Heading>\n ),\n h5: ({ children }: MarkdownChildrenProps) => (\n <Heading weight=\"medium\" size=\"3\" as=\"h5\" style={{ marginTop: headingMargins.h5.top, marginBottom: headingMargins.h5.bottom }}>\n {children}\n </Heading>\n ),\n h6: ({ children }: MarkdownChildrenProps) => (\n <Heading weight=\"medium\" size=\"2\" as=\"h6\" style={{ marginTop: headingMargins.h6.top, marginBottom: headingMargins.h6.bottom }}>\n {children}\n </Heading>\n ),\n\n // Paragraph text\n p: ({ children }: MarkdownChildrenProps) => (\n <Text size=\"3\" as=\"p\" style={{ lineHeight: \"1.6\", marginTop: paragraphMargin, marginBottom: paragraphMargin }}>\n {children}\n </Text>\n ),\n\n // Code - inline vs block\n code: ({ className, children, inline }: { className?: string; children?: ReactNode; inline?: boolean }) => {\n const code = extractCode(children);\n\n // Block code: has className (language) OR is not marked as inline\n // Inline code: explicitly marked as inline=true, or no className and short single-line content\n const isInlineCode = inline === true || (inline === undefined && !className && !code.includes(\"\\n\") && code.length < 100);\n\n if (isInlineCode) {\n return (\n <Code highContrast={inlineCodeHighContrast} size=\"3\">\n {code}\n </Code>\n );\n }\n\n return (\n <Box my={codeBlockMargin} style={{ minWidth: 0 }}>\n <CodeBlock code={code} language={extractLanguage(className)} collapsible={codeBlockCollapsible} />\n </Box>\n );\n },\n\n // Lists\n ul: ({ children }: MarkdownChildrenProps) => (\n <ul style={{ marginTop: listMargin, marginBottom: listMargin, lineHeight: \"1.6\", paddingLeft: \"1.5rem\", listStyleType: \"disc\" }}>{children}</ul>\n ),\n ol: ({ children }: MarkdownChildrenProps) => (\n <ol style={{ marginTop: listMargin, marginBottom: listMargin, lineHeight: \"1.6\", paddingLeft: \"1.5rem\", listStyleType: \"decimal\" }}>{children}</ol>\n ),\n li: ({ children }: MarkdownChildrenProps) => <li style={{ marginBottom: listItemMargin, lineHeight: \"1.6\" }}>{children}</li>,\n\n // Blockquote\n blockquote: ({ children }: MarkdownChildrenProps) => (\n <Blockquote size=\"1\" my={blockquoteMargin}>\n {children}\n </Blockquote>\n ),\n\n // Links\n a: ({ href, children }: { href?: string; children?: ReactNode }) => (\n <a href={href} style={{ color: \"var(--accent-9)\", textDecoration: \"underline\" }}>\n {children}\n </a>\n ),\n\n // Text styling\n strong: ({ children }: MarkdownChildrenProps) => (\n <Text weight=\"medium\" style={{ lineHeight: \"1.6\" }}>\n {children}\n </Text>\n ),\n em: ({ children }: MarkdownChildrenProps) => <Text style={{ lineHeight: \"1.6\", fontStyle: \"italic\" }}>{children}</Text>,\n\n // Horizontal rule\n hr: () => (\n <Box style={{ marginTop: hrMargin, marginBottom: hrMargin }}>\n <Separator orientation=\"horizontal\" light />\n </Box>\n ),\n\n // Pre wrapper (pass through to let code handle it)\n pre: ({ children }: MarkdownChildrenProps) => <>{children}</>,\n\n // Tables using KookieUI\n table: ({ children }: MarkdownChildrenProps) => (\n <Box my=\"2\" style={{ overflowX: \"auto\" }}>\n <Table.Root size=\"2\" variant=\"ghost\">\n {children}\n </Table.Root>\n </Box>\n ),\n thead: ({ children }: MarkdownChildrenProps) => <Table.Header>{children}</Table.Header>,\n tbody: ({ children }: MarkdownChildrenProps) => <Table.Body>{children}</Table.Body>,\n tr: ({ children }: MarkdownChildrenProps) => <Table.Row>{children}</Table.Row>,\n th: ({ children }: MarkdownChildrenProps) => <Table.ColumnHeaderCell>{children}</Table.ColumnHeaderCell>,\n td: ({ children }: MarkdownChildrenProps) => <Table.Cell>{children}</Table.Cell>,\n\n // HTML elements for raw HTML support\n sub: ({ children }: MarkdownChildrenProps) => <sub>{children}</sub>,\n sup: ({ children }: MarkdownChildrenProps) => <sup>{children}</sup>,\n br: () => <br />,\n\n // Images - use custom component if provided\n img: imageComponent\n ? (props: React.ImgHTMLAttributes<HTMLImageElement>) => {\n const { src, alt, width, height } = props;\n if (!src || typeof src !== \"string\") return null;\n return imageComponent({\n src,\n alt: alt ?? \"Image\",\n width: width ? String(width) : undefined,\n height: height ? String(height) : undefined,\n });\n }\n : undefined,\n\n // Details/Summary for expandable sections\n details: ({ children }: MarkdownChildrenProps) => <details style={{ padding: \"0.5rem 0\" }}>{children}</details>,\n summary: ({ children }: MarkdownChildrenProps) => <summary style={{ cursor: \"pointer\", fontWeight: 500 }}>{children}</summary>,\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["create_markdown_components_exports", "__export", "createMarkdownComponents", "__toCommonJS", "import_react", "import_kookie_ui", "import_code", "extractLanguage", "className", "extractCode", "children", "code", "child", "options", "codeBlockCollapsible", "imageComponent", "inlineCodeHighContrast", "spacing", "isCompact", "headingMargins", "listMargin", "listItemMargin", "codeBlockMargin", "hrMargin", "paragraphMargin", "blockquoteMargin", "React", "inline", "href", "props", "src", "alt", "width", "height"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming-markdown.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/streaming-markdown.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAC7D,OAAsB,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAOhE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"streaming-markdown.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/streaming-markdown.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAC7D,OAAsB,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAOhE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAaxD;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,wBAAwB,GAAG;IAChE;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,KAAK,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE3D;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CAClC,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,OAAO,CAAC,EAAE,wBAAwB,CAAC;CACpC,CAAC;AA6CF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAY,EAAE,EAAE,sBAAsB,4BA2CtF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";"use client";var B=Object.create;var
|
|
1
|
+
"use strict";"use client";var B=Object.create;var d=Object.defineProperty;var I=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var E=Object.getPrototypeOf,x=Object.prototype.hasOwnProperty;var L=(o,n)=>{for(var t in n)d(o,t,{get:n[t],enumerable:!0})},O=(o,n,t,i)=>{if(n&&typeof n=="object"||typeof n=="function")for(let r of S(n))!x.call(o,r)&&r!==t&&d(o,r,{get:()=>n[r],enumerable:!(i=I(n,r))||i.enumerable});return o};var s=(o,n,t)=>(t=o!=null?B(E(o)):{},O(n||!o||!o.__esModule?d(t,"default",{value:o,enumerable:!0}):t,o)),A=o=>O(d({},"__esModule",{value:!0}),o);var T={};L(T,{StreamingMarkdown:()=>H});module.exports=A(T);var e=s(require("react")),P=s(require("react-markdown")),h=s(require("remark-gfm")),y=s(require("rehype-raw")),p=s(require("harden-react-markdown")),l=require("@kushagradhawan/kookie-ui"),C=require("./create-markdown-components"),c=require("./utils/markdown-streaming");const F=typeof p.default=="function"?p.default:p.default.default||p.default,R=F(P.default),_=["https://","http://","/"],D=["https://","http://","/","data:"],N=["mailto:","tel:","data:","http:","https:"],G=typeof window<"u"&&window.location?.origin?window.location.origin:"https://app.kookie.ai";function z(o){return o||G}const w=(0,e.memo)(({content:o,defaultOrigin:n,components:t})=>e.default.createElement(l.Box,{width:"100%"},e.default.createElement(R,{defaultOrigin:n,allowedLinkPrefixes:_,allowedImagePrefixes:D,allowedProtocols:N,allowDataImages:!0,components:t,remarkPlugins:[h.default],rehypePlugins:[y.default]},o)),(o,n)=>o.content===n.content&&o.defaultOrigin===n.defaultOrigin&&o.components===n.components);w.displayName="MarkdownBlock";function H({content:o,id:n,options:t={}}){const{defaultOrigin:i,enableBlockMemoization:r=!0,blockParser:k,components:f={},...g}=t,u=(0,e.useMemo)(()=>z(i),[i]),M=(0,e.useMemo)(()=>({...(0,C.createMarkdownComponents)(g),...f}),[g,f]),m=(0,e.useMemo)(()=>{if(!r||!k){const a=(0,c.completeUnterminatedMarkdown)(o);return a.trim()?[a]:[]}return(0,c.parseMarkdownIntoBlocks)(o,k)},[o,r,k]);return m.length?m.length===1?e.default.createElement(w,{content:m[0],defaultOrigin:u,components:M}):e.default.createElement(l.Flex,{direction:"column",gap:"2",width:"100%"},m.map((a,b)=>e.default.createElement(w,{key:`${n}-block-${b}`,content:a,defaultOrigin:u,components:M}))):null}
|
|
2
2
|
//# sourceMappingURL=streaming-markdown.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/markdown/streaming-markdown.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\n\nimport React, { memo, useMemo, type ReactNode } from \"react\";\nimport ReactMarkdown, { type Components } from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypeRaw from \"rehype-raw\";\nimport
|
|
5
|
-
"mappings": "ukBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,uBAAAE,IAAA,eAAAC,EAAAH,GAEA,IAAAI,EAAqD,oBACrDC,EAA+C,6BAC/CC,EAAsB,yBACtBC,EAAsB,yBACtBC,
|
|
6
|
-
"names": ["streaming_markdown_exports", "__export", "StreamingMarkdown", "__toCommonJS", "import_react", "import_react_markdown", "import_remark_gfm", "import_rehype_raw", "import_harden_react_markdown", "import_kookie_ui", "import_create_markdown_components", "import_markdown_streaming", "
|
|
4
|
+
"sourcesContent": ["\"use client\";\n\nimport React, { memo, useMemo, type ReactNode } from \"react\";\nimport ReactMarkdown, { type Components } from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypeRaw from \"rehype-raw\";\nimport hardenReactMarkdownModule from \"harden-react-markdown\";\nimport { Box, Flex } from \"@kushagradhawan/kookie-ui\";\nimport { createMarkdownComponents } from \"./create-markdown-components\";\nimport { completeUnterminatedMarkdown, parseMarkdownIntoBlocks } from \"./utils/markdown-streaming\";\nimport type { MarkdownComponentOptions } from \"./types\";\n\n// Handle different export formats\nconst hardenReactMarkdown =\n typeof hardenReactMarkdownModule === \"function\" ? hardenReactMarkdownModule : (hardenReactMarkdownModule as any).default || hardenReactMarkdownModule;\n\nconst HardenedMarkdown = hardenReactMarkdown(ReactMarkdown);\n\nconst LINK_PREFIXES = [\"https://\", \"http://\", \"/\"];\nconst IMAGE_PREFIXES = [\"https://\", \"http://\", \"/\", \"data:\"];\nconst ALLOWED_PROTOCOLS = [\"mailto:\", \"tel:\", \"data:\", \"http:\", \"https:\"];\nconst DEFAULT_APP_ORIGIN = typeof window !== \"undefined\" && window.location?.origin ? window.location.origin : \"https://app.kookie.ai\";\n\n/**\n * Options for StreamingMarkdown component\n */\nexport type StreamingMarkdownOptions = MarkdownComponentOptions & {\n /**\n * Security origin for link/image validation\n * @default window.location.origin or \"https://app.kookie.ai\"\n */\n defaultOrigin?: string;\n\n /**\n * Whether to enable block-level memoization for performance\n * Recommended for streaming scenarios where content updates frequently\n * @default true\n */\n enableBlockMemoization?: boolean;\n\n /**\n * Custom parser for splitting content into blocks\n * If not provided, content will be rendered as a single block\n * For optimal streaming performance, use marked.lexer with GFM enabled\n */\n blockParser?: (content: string) => Array<{ raw?: string }>;\n\n /**\n * Override default component mappings\n */\n components?: Partial<Components>;\n};\n\ntype StreamingMarkdownProps = {\n /**\n * Markdown content to render (supports streaming/incomplete markdown)\n */\n content: string;\n\n /**\n * Unique identifier for this markdown instance (used for keys)\n */\n id: string;\n\n /**\n * Optional configuration\n */\n options?: StreamingMarkdownOptions;\n};\n\ntype MarkdownBlockProps = {\n content: string;\n defaultOrigin: string;\n components: Components;\n};\n\n/**\n * Resolves the default origin for security validation\n */\nfunction resolveDefaultOrigin(customOrigin?: string): string {\n if (customOrigin) {\n return customOrigin;\n }\n return DEFAULT_APP_ORIGIN;\n}\n\n/**\n * Memoized markdown block component for efficient streaming rendering\n */\nconst MarkdownBlock = memo(\n ({ content, defaultOrigin, components }: MarkdownBlockProps) => {\n return (\n <Box width=\"100%\">\n <HardenedMarkdown\n defaultOrigin={defaultOrigin}\n allowedLinkPrefixes={LINK_PREFIXES}\n allowedImagePrefixes={IMAGE_PREFIXES}\n allowedProtocols={ALLOWED_PROTOCOLS}\n allowDataImages\n components={components}\n remarkPlugins={[remarkGfm]}\n rehypePlugins={[rehypeRaw]}\n >\n {content}\n </HardenedMarkdown>\n </Box>\n );\n },\n (previous, next) => previous.content === next.content && previous.defaultOrigin === next.defaultOrigin && previous.components === next.components\n);\n\nMarkdownBlock.displayName = \"MarkdownBlock\";\n\n/**\n * StreamingMarkdown - A drop-in markdown renderer designed for AI streaming.\n *\n * Features:\n * - Unterminated block parsing (handles incomplete markdown during streaming)\n * - Block-level memoization for performance\n * - Security hardening (validates links/images)\n * - GitHub Flavored Markdown support\n * - KookieUI component integration\n * - Code syntax highlighting via CodeBlock\n *\n * @example\n * ```tsx\n * import { StreamingMarkdown } from '@kushagradhawan/kookie-blocks';\n * import { marked } from 'marked';\n *\n * function ChatMessage({ message }) {\n * return (\n * <StreamingMarkdown\n * content={message.content}\n * id={message.id}\n * options={{\n * blockParser: (content) => marked.lexer(content, { gfm: true }),\n * enableBlockMemoization: true,\n * }}\n * />\n * );\n * }\n * ```\n */\nexport function StreamingMarkdown({ content, id, options = {} }: StreamingMarkdownProps) {\n const { defaultOrigin: customOrigin, enableBlockMemoization = true, blockParser, components: customComponents = {}, ...componentOptions } = options;\n\n // Resolve security origin\n const defaultOrigin = useMemo(() => resolveDefaultOrigin(customOrigin), [customOrigin]);\n\n // Create component mappings with custom overrides\n const markdownComponents = useMemo(() => {\n const baseComponents = createMarkdownComponents(componentOptions);\n return {\n ...baseComponents,\n ...customComponents,\n };\n }, [componentOptions, customComponents]);\n\n // Parse content into blocks for memoization (if enabled and parser provided)\n const blocks = useMemo(() => {\n if (!enableBlockMemoization || !blockParser) {\n // No block splitting - just complete unterminated markdown\n const completed = completeUnterminatedMarkdown(content);\n return completed.trim() ? [completed] : [];\n }\n\n return parseMarkdownIntoBlocks(content, blockParser);\n }, [content, enableBlockMemoization, blockParser]);\n\n if (!blocks.length) {\n return null;\n }\n\n // Single block - no need for wrapper\n if (blocks.length === 1) {\n return <MarkdownBlock content={blocks[0]} defaultOrigin={defaultOrigin} components={markdownComponents} />;\n }\n\n // Multiple blocks - render with flex wrapper\n return (\n <Flex direction=\"column\" gap=\"2\" width=\"100%\">\n {blocks.map((block, index) => (\n <MarkdownBlock key={`${id}-block-${index}`} content={block} defaultOrigin={defaultOrigin} components={markdownComponents} />\n ))}\n </Flex>\n );\n}\n"],
|
|
5
|
+
"mappings": "ukBAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,uBAAAE,IAAA,eAAAC,EAAAH,GAEA,IAAAI,EAAqD,oBACrDC,EAA+C,6BAC/CC,EAAsB,yBACtBC,EAAsB,yBACtBC,EAAsC,oCACtCC,EAA0B,qCAC1BC,EAAyC,wCACzCC,EAAsE,sCAItE,MAAMC,EACJ,OAAO,EAAAC,SAA8B,WAAa,EAAAA,QAA6B,EAAAA,QAAkC,SAAW,EAAAA,QAExHC,EAAmBF,EAAoB,EAAAG,OAAa,EAEpDC,EAAgB,CAAC,WAAY,UAAW,GAAG,EAC3CC,EAAiB,CAAC,WAAY,UAAW,IAAK,OAAO,EACrDC,EAAoB,CAAC,UAAW,OAAQ,QAAS,QAAS,QAAQ,EAClEC,EAAqB,OAAO,OAAW,KAAe,OAAO,UAAU,OAAS,OAAO,SAAS,OAAS,wBA0D/G,SAASC,EAAqBC,EAA+B,CAC3D,OAAIA,GAGGF,CACT,CAKA,MAAMG,KAAgB,QACpB,CAAC,CAAE,QAAAC,EAAS,cAAAC,EAAe,WAAAC,CAAW,IAElC,EAAAC,QAAA,cAAC,OAAI,MAAM,QACT,EAAAA,QAAA,cAACZ,EAAA,CACC,cAAeU,EACf,oBAAqBR,EACrB,qBAAsBC,EACtB,iBAAkBC,EAClB,gBAAe,GACf,WAAYO,EACZ,cAAe,CAAC,EAAAE,OAAS,EACzB,cAAe,CAAC,EAAAC,OAAS,GAExBL,CACH,CACF,EAGJ,CAACM,EAAUC,IAASD,EAAS,UAAYC,EAAK,SAAWD,EAAS,gBAAkBC,EAAK,eAAiBD,EAAS,aAAeC,EAAK,UACzI,EAEAR,EAAc,YAAc,gBAgCrB,SAASpB,EAAkB,CAAE,QAAAqB,EAAS,GAAAQ,EAAI,QAAAC,EAAU,CAAC,CAAE,EAA2B,CACvF,KAAM,CAAE,cAAeX,EAAc,uBAAAY,EAAyB,GAAM,YAAAC,EAAa,WAAYC,EAAmB,CAAC,EAAG,GAAGC,CAAiB,EAAIJ,EAGtIR,KAAgB,WAAQ,IAAMJ,EAAqBC,CAAY,EAAG,CAACA,CAAY,CAAC,EAGhFgB,KAAqB,WAAQ,KAE1B,CACL,MAFqB,4BAAyBD,CAAgB,EAG9D,GAAGD,CACL,GACC,CAACC,EAAkBD,CAAgB,CAAC,EAGjCG,KAAS,WAAQ,IAAM,CAC3B,GAAI,CAACL,GAA0B,CAACC,EAAa,CAE3C,MAAMK,KAAY,gCAA6BhB,CAAO,EACtD,OAAOgB,EAAU,KAAK,EAAI,CAACA,CAAS,EAAI,CAAC,CAC3C,CAEA,SAAO,2BAAwBhB,EAASW,CAAW,CACrD,EAAG,CAACX,EAASU,EAAwBC,CAAW,CAAC,EAEjD,OAAKI,EAAO,OAKRA,EAAO,SAAW,EACb,EAAAZ,QAAA,cAACJ,EAAA,CAAc,QAASgB,EAAO,CAAC,EAAG,cAAed,EAAe,WAAYa,EAAoB,EAKxG,EAAAX,QAAA,cAAC,QAAK,UAAU,SAAS,IAAI,IAAI,MAAM,QACpCY,EAAO,IAAI,CAACE,EAAOC,IAClB,EAAAf,QAAA,cAACJ,EAAA,CAAc,IAAK,GAAGS,CAAE,UAAUU,CAAK,GAAI,QAASD,EAAO,cAAehB,EAAe,WAAYa,EAAoB,CAC3H,CACH,EAdO,IAgBX",
|
|
6
|
+
"names": ["streaming_markdown_exports", "__export", "StreamingMarkdown", "__toCommonJS", "import_react", "import_react_markdown", "import_remark_gfm", "import_rehype_raw", "import_harden_react_markdown", "import_kookie_ui", "import_create_markdown_components", "import_markdown_streaming", "hardenReactMarkdown", "hardenReactMarkdownModule", "HardenedMarkdown", "ReactMarkdown", "LINK_PREFIXES", "IMAGE_PREFIXES", "ALLOWED_PROTOCOLS", "DEFAULT_APP_ORIGIN", "resolveDefaultOrigin", "customOrigin", "MarkdownBlock", "content", "defaultOrigin", "components", "React", "remarkGfm", "rehypeRaw", "previous", "next", "id", "options", "enableBlockMemoization", "blockParser", "customComponents", "componentOptions", "markdownComponents", "blocks", "completed", "block", "index"]
|
|
7
7
|
}
|
|
@@ -22,6 +22,13 @@ export type MarkdownComponentOptions = {
|
|
|
22
22
|
* @default true
|
|
23
23
|
*/
|
|
24
24
|
inlineCodeHighContrast?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Spacing density for markdown elements
|
|
27
|
+
* - "compact": Tighter spacing, ideal for chat/conversational interfaces
|
|
28
|
+
* - "spacious": More breathing room, ideal for documentation/articles
|
|
29
|
+
* @default "spacious"
|
|
30
|
+
*/
|
|
31
|
+
spacing?: "compact" | "spacious";
|
|
25
32
|
};
|
|
26
33
|
/**
|
|
27
34
|
* Common props for markdown child components
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,SAAS,CAAC;IAEvG;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,SAAS,CAAC;IAEvG;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var i=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var c=(e,o,r,n)=>{if(o&&typeof o=="object"||typeof o=="function")for(let t of a(o))!s.call(e,t)&&t!==r&&i(e,t,{get:()=>o[t],enumerable:!(n=p(o,t))||n.enumerable});return e};var d=e=>c(i({},"__esModule",{value:!0}),e);var l={};module.exports=d(l);
|
|
2
2
|
//# sourceMappingURL=types.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/markdown/types.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ReactNode } from \"react\";\n\n/**\n * Options for customizing markdown component behavior\n */\nexport type MarkdownComponentOptions = {\n /**\n * Whether code blocks should be collapsible\n * @default false\n */\n codeBlockCollapsible?: boolean;\n\n /**\n * Custom image component\n */\n imageComponent?: (props: { src?: string; alt?: string; width?: string; height?: string }) => ReactNode;\n\n /**\n * Whether to use high contrast for inline code\n * @default true\n */\n inlineCodeHighContrast?: boolean;\n};\n\n/**\n * Common props for markdown child components\n */\nexport type MarkdownChildrenProps = {\n children?: ReactNode;\n};\n\n"],
|
|
4
|
+
"sourcesContent": ["import type { ReactNode } from \"react\";\n\n/**\n * Options for customizing markdown component behavior\n */\nexport type MarkdownComponentOptions = {\n /**\n * Whether code blocks should be collapsible\n * @default false\n */\n codeBlockCollapsible?: boolean;\n\n /**\n * Custom image component\n */\n imageComponent?: (props: { src?: string; alt?: string; width?: string; height?: string }) => ReactNode;\n\n /**\n * Whether to use high contrast for inline code\n * @default true\n */\n inlineCodeHighContrast?: boolean;\n\n /**\n * Spacing density for markdown elements\n * - \"compact\": Tighter spacing, ideal for chat/conversational interfaces\n * - \"spacious\": More breathing room, ideal for documentation/articles\n * @default \"spacious\"\n */\n spacing?: \"compact\" | \"spacious\";\n};\n\n/**\n * Common props for markdown child components\n */\nexport type MarkdownChildrenProps = {\n children?: ReactNode;\n};\n\n"],
|
|
5
5
|
"mappings": "+WAAA,IAAAA,EAAA,kBAAAC,EAAAD",
|
|
6
6
|
"names": ["types_exports", "__toCommonJS"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
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"./use-code-card";import{LanguageBadge as V}from"./language-badge";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",
|
|
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"./use-code-card";import{LanguageBadge as V}from"./language-badge";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",my:"3"},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=code-block.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/code/code-block.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 \"./use-code-card\";\nimport { LanguageBadge } from \"./language-badge\";\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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
|
|
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 \"./use-code-card\";\nimport { LanguageBadge } from \"./language-badge\";\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\" my=\"3\">\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
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
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-markdown-components.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/create-markdown-components.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,KAAK,EAAE,wBAAwB,EAAyB,MAAM,SAAS,CAAC;AA8B/E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,wBAA6B,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"create-markdown-components.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/create-markdown-components.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGjD,OAAO,KAAK,EAAE,wBAAwB,EAAyB,MAAM,SAAS,CAAC;AA8B/E;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,GAAE,wBAA6B,GAAG,UAAU,CAiK3F"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
`)&&
|
|
1
|
+
import e from"react";import{Blockquote as T,Box as u,Code as c,Heading as l,Text as C,Table as d,Separator as B}from"@kushagradhawan/kookie-ui";import{CodeBlock as H}from"../code";function x(n){return n?n.match(/language-([\w-]+)/i)?.[1]??"text":"text"}function z(n){let i="";return n?(typeof n=="string"?i=n:Array.isArray(n)&&(i=n.map(a=>typeof a=="string"?a:"").join("")),i.replace(/^\n+|\n+$/g,"")):i}function v(n={}){const{codeBlockCollapsible:i=!1,imageComponent:a,inlineCodeHighContrast:M=!0,spacing:k="spacious"}=n,r=k==="compact",t={h1:{top:r?"1.5rem":"3rem",bottom:r?"1rem":"1.5rem"},h2:{top:r?"2rem":"3rem",bottom:r?"0.375rem":"0.5rem"},h3:{top:r?"1.5rem":"2rem",bottom:r?"0.375rem":"0.5rem"},h4:{top:r?"0.5rem":"0.625rem",bottom:r?"0.25rem":"0.5rem"},h5:{top:r?"0.375rem":"0.5rem",bottom:r?"0.25rem":"0.5rem"},h6:{top:r?"0.375rem":"0.5rem",bottom:r?"0.25rem":"0.5rem"}},h=r?"0.25rem":"0.5rem",b=r?"0.125rem":"0.25rem",f=r?"1":"2",w=r?"0.375rem":"0.5rem",y=r?"0":"0.5rem",P=r?"0.5rem":"1rem";return{h1:({children:o})=>e.createElement(l,{size:"9",weight:"medium",as:"h1",style:{marginTop:t.h1.top,marginBottom:t.h1.bottom}},o),h2:({children:o})=>e.createElement(l,{weight:"medium",size:"7",as:"h2",style:{marginTop:t.h2.top,marginBottom:t.h2.bottom}},o),h3:({children:o})=>e.createElement(l,{weight:"medium",size:"5",as:"h3",style:{marginTop:t.h3.top,marginBottom:t.h3.bottom}},o),h4:({children:o})=>e.createElement(l,{weight:"medium",size:"4",as:"h4",style:{marginTop:t.h4.top,marginBottom:t.h4.bottom}},o),h5:({children:o})=>e.createElement(l,{weight:"medium",size:"3",as:"h5",style:{marginTop:t.h5.top,marginBottom:t.h5.bottom}},o),h6:({children:o})=>e.createElement(l,{weight:"medium",size:"2",as:"h6",style:{marginTop:t.h6.top,marginBottom:t.h6.bottom}},o),p:({children:o})=>e.createElement(C,{size:"3",as:"p",style:{lineHeight:"1.6",marginTop:y,marginBottom:y}},o),code:({className:o,children:m,inline:p})=>{const s=z(m);return p===!0||p===void 0&&!o&&!s.includes(`
|
|
2
|
+
`)&&s.length<100?e.createElement(c,{highContrast:M,size:"3"},s):e.createElement(u,{my:f,style:{minWidth:0}},e.createElement(H,{code:s,language:x(o),collapsible:i}))},ul:({children:o})=>e.createElement("ul",{style:{marginTop:h,marginBottom:h,lineHeight:"1.6",paddingLeft:"1.5rem",listStyleType:"disc"}},o),ol:({children:o})=>e.createElement("ol",{style:{marginTop:h,marginBottom:h,lineHeight:"1.6",paddingLeft:"1.5rem",listStyleType:"decimal"}},o),li:({children:o})=>e.createElement("li",{style:{marginBottom:b,lineHeight:"1.6"}},o),blockquote:({children:o})=>e.createElement(T,{size:"1",my:P},o),a:({href:o,children:m})=>e.createElement("a",{href:o,style:{color:"var(--accent-9)",textDecoration:"underline"}},m),strong:({children:o})=>e.createElement(C,{weight:"medium",style:{lineHeight:"1.6"}},o),em:({children:o})=>e.createElement(C,{style:{lineHeight:"1.6",fontStyle:"italic"}},o),hr:()=>e.createElement(u,{style:{marginTop:w,marginBottom:w}},e.createElement(B,{orientation:"horizontal",light:!0})),pre:({children:o})=>e.createElement(e.Fragment,null,o),table:({children:o})=>e.createElement(u,{my:"2",style:{overflowX:"auto"}},e.createElement(d.Root,{size:"2",variant:"ghost"},o)),thead:({children:o})=>e.createElement(d.Header,null,o),tbody:({children:o})=>e.createElement(d.Body,null,o),tr:({children:o})=>e.createElement(d.Row,null,o),th:({children:o})=>e.createElement(d.ColumnHeaderCell,null,o),td:({children:o})=>e.createElement(d.Cell,null,o),sub:({children:o})=>e.createElement("sub",null,o),sup:({children:o})=>e.createElement("sup",null,o),br:()=>e.createElement("br",null),img:a?o=>{const{src:m,alt:p,width:s,height:g}=o;return!m||typeof m!="string"?null:a({src:m,alt:p??"Image",width:s?String(s):void 0,height:g?String(g):void 0})}:void 0,details:({children:o})=>e.createElement("details",{style:{padding:"0.5rem 0"}},o),summary:({children:o})=>e.createElement("summary",{style:{cursor:"pointer",fontWeight:500}},o)}}export{v as createMarkdownComponents};
|
|
3
3
|
//# sourceMappingURL=create-markdown-components.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/markdown/create-markdown-components.tsx"],
|
|
4
|
-
"sourcesContent": ["import React, { type ReactNode } from \"react\";\nimport type { Components } from \"react-markdown\";\nimport { Blockquote, Box, Code, Flex, Heading, Text, Table } from \"@kushagradhawan/kookie-ui\";\nimport { CodeBlock } from \"../code\";\nimport type { MarkdownComponentOptions, MarkdownChildrenProps } from \"./types\";\n\n/**\n * Extracts language from className (e.g., \"language-typescript\" -> \"typescript\")\n */\nfunction extractLanguage(className?: string): string {\n if (!className) {\n return \"text\";\n }\n const match = className.match(/language-([\\w-]+)/i);\n return match?.[1] ?? \"text\";\n}\n\n/**\n * Extracts code string from ReactNode children\n */\nfunction extractCode(children?: ReactNode): string {\n let code = \"\";\n if (!children) {\n return code;\n }\n if (typeof children === \"string\") {\n code = children;\n } else if (Array.isArray(children)) {\n code = children.map((child) => (typeof child === \"string\" ? child : \"\")).join(\"\");\n }\n // Trim trailing newlines but preserve internal whitespace\n return code.replace(/^\\n+|\\n+$/g, \"\");\n}\n\n/**\n * Creates markdown component mappings that work with both react-markdown and MDX.\n * Uses KookieUI components for consistent styling across all projects.\n *\n * @param options - Optional configuration for component behavior\n * @returns Component mappings for markdown/MDX renderers\n *\n * @example\n * ```tsx\n * // In react-markdown\n * <ReactMarkdown components={createMarkdownComponents()}>\n * {content}\n * </ReactMarkdown>\n *\n * // In MDX\n * export function useMDXComponents(components: MDXComponents) {\n * return {\n * ...createMarkdownComponents(),\n * ...components,\n * };\n * }\n * ```\n */\nexport function createMarkdownComponents(options: MarkdownComponentOptions = {}): Components {\n const { codeBlockCollapsible = false, imageComponent, inlineCodeHighContrast = true } = options;\n\n return {\n // Headings with consistent visual hierarchy (9-6-5-4-3-2)\n h1: ({ children }: MarkdownChildrenProps) => (\n <Heading size=\"9\" weight=\"medium\" as=\"h1\" style={{ marginTop:
|
|
5
|
-
"mappings": "AAAA,OAAOA,MAA+B,QAEtC,OAAS,cAAAC,EAAY,OAAAC,EAAK,QAAAC,EAAY,WAAAC,EAAS,QAAAC,EAAM,SAAAC,
|
|
6
|
-
"names": ["React", "Blockquote", "Box", "Code", "Heading", "Text", "Table", "CodeBlock", "extractLanguage", "className", "extractCode", "children", "code", "child", "createMarkdownComponents", "options", "codeBlockCollapsible", "imageComponent", "inlineCodeHighContrast", "inline", "href", "props", "src", "alt", "width", "height"]
|
|
4
|
+
"sourcesContent": ["import React, { type ReactNode } from \"react\";\nimport type { Components } from \"react-markdown\";\nimport { Blockquote, Box, Code, Flex, Heading, Text, Table, Separator } from \"@kushagradhawan/kookie-ui\";\nimport { CodeBlock } from \"../code\";\nimport type { MarkdownComponentOptions, MarkdownChildrenProps } from \"./types\";\n\n/**\n * Extracts language from className (e.g., \"language-typescript\" -> \"typescript\")\n */\nfunction extractLanguage(className?: string): string {\n if (!className) {\n return \"text\";\n }\n const match = className.match(/language-([\\w-]+)/i);\n return match?.[1] ?? \"text\";\n}\n\n/**\n * Extracts code string from ReactNode children\n */\nfunction extractCode(children?: ReactNode): string {\n let code = \"\";\n if (!children) {\n return code;\n }\n if (typeof children === \"string\") {\n code = children;\n } else if (Array.isArray(children)) {\n code = children.map((child) => (typeof child === \"string\" ? child : \"\")).join(\"\");\n }\n // Trim trailing newlines but preserve internal whitespace\n return code.replace(/^\\n+|\\n+$/g, \"\");\n}\n\n/**\n * Creates markdown component mappings that work with both react-markdown and MDX.\n * Uses KookieUI components for consistent styling across all projects.\n *\n * @param options - Optional configuration for component behavior\n * @returns Component mappings for markdown/MDX renderers\n *\n * @example\n * ```tsx\n * // In react-markdown\n * <ReactMarkdown components={createMarkdownComponents()}>\n * {content}\n * </ReactMarkdown>\n *\n * // In MDX\n * export function useMDXComponents(components: MDXComponents) {\n * return {\n * ...createMarkdownComponents(),\n * ...components,\n * };\n * }\n * ```\n */\nexport function createMarkdownComponents(options: MarkdownComponentOptions = {}): Components {\n const { codeBlockCollapsible = false, imageComponent, inlineCodeHighContrast = true, spacing = \"spacious\" } = options;\n\n // Spacing configuration\n const isCompact = spacing === \"compact\";\n const headingMargins = {\n h1: { top: isCompact ? \"1.5rem\" : \"3rem\", bottom: isCompact ? \"1rem\" : \"1.5rem\" },\n h2: { top: isCompact ? \"2rem\" : \"3rem\", bottom: isCompact ? \"0.375rem\" : \"0.5rem\" },\n h3: { top: isCompact ? \"1.5rem\" : \"2rem\", bottom: isCompact ? \"0.375rem\" : \"0.5rem\" },\n h4: { top: isCompact ? \"0.5rem\" : \"0.625rem\", bottom: isCompact ? \"0.25rem\" : \"0.5rem\" },\n h5: { top: isCompact ? \"0.375rem\" : \"0.5rem\", bottom: isCompact ? \"0.25rem\" : \"0.5rem\" },\n h6: { top: isCompact ? \"0.375rem\" : \"0.5rem\", bottom: isCompact ? \"0.25rem\" : \"0.5rem\" },\n };\n const listMargin = isCompact ? \"0.25rem\" : \"0.5rem\";\n const listItemMargin = isCompact ? \"0.125rem\" : \"0.25rem\";\n const codeBlockMargin = isCompact ? \"1\" : \"2\";\n const hrMargin = isCompact ? \"0.375rem\" : \"0.5rem\";\n const paragraphMargin = isCompact ? \"0\" : \"0.5rem\";\n const blockquoteMargin = isCompact ? \"0.5rem\" : \"1rem\";\n\n return {\n // Headings with consistent visual hierarchy (9-6-5-4-3-2)\n h1: ({ children }: MarkdownChildrenProps) => (\n <Heading size=\"9\" weight=\"medium\" as=\"h1\" style={{ marginTop: headingMargins.h1.top, marginBottom: headingMargins.h1.bottom }}>\n {children}\n </Heading>\n ),\n h2: ({ children }: MarkdownChildrenProps) => (\n <Heading weight=\"medium\" size=\"7\" as=\"h2\" style={{ marginTop: headingMargins.h2.top, marginBottom: headingMargins.h2.bottom }}>\n {children}\n </Heading>\n ),\n h3: ({ children }: MarkdownChildrenProps) => (\n <Heading weight=\"medium\" size=\"5\" as=\"h3\" style={{ marginTop: headingMargins.h3.top, marginBottom: headingMargins.h3.bottom }}>\n {children}\n </Heading>\n ),\n h4: ({ children }: MarkdownChildrenProps) => (\n <Heading weight=\"medium\" size=\"4\" as=\"h4\" style={{ marginTop: headingMargins.h4.top, marginBottom: headingMargins.h4.bottom }}>\n {children}\n </Heading>\n ),\n h5: ({ children }: MarkdownChildrenProps) => (\n <Heading weight=\"medium\" size=\"3\" as=\"h5\" style={{ marginTop: headingMargins.h5.top, marginBottom: headingMargins.h5.bottom }}>\n {children}\n </Heading>\n ),\n h6: ({ children }: MarkdownChildrenProps) => (\n <Heading weight=\"medium\" size=\"2\" as=\"h6\" style={{ marginTop: headingMargins.h6.top, marginBottom: headingMargins.h6.bottom }}>\n {children}\n </Heading>\n ),\n\n // Paragraph text\n p: ({ children }: MarkdownChildrenProps) => (\n <Text size=\"3\" as=\"p\" style={{ lineHeight: \"1.6\", marginTop: paragraphMargin, marginBottom: paragraphMargin }}>\n {children}\n </Text>\n ),\n\n // Code - inline vs block\n code: ({ className, children, inline }: { className?: string; children?: ReactNode; inline?: boolean }) => {\n const code = extractCode(children);\n\n // Block code: has className (language) OR is not marked as inline\n // Inline code: explicitly marked as inline=true, or no className and short single-line content\n const isInlineCode = inline === true || (inline === undefined && !className && !code.includes(\"\\n\") && code.length < 100);\n\n if (isInlineCode) {\n return (\n <Code highContrast={inlineCodeHighContrast} size=\"3\">\n {code}\n </Code>\n );\n }\n\n return (\n <Box my={codeBlockMargin} style={{ minWidth: 0 }}>\n <CodeBlock code={code} language={extractLanguage(className)} collapsible={codeBlockCollapsible} />\n </Box>\n );\n },\n\n // Lists\n ul: ({ children }: MarkdownChildrenProps) => (\n <ul style={{ marginTop: listMargin, marginBottom: listMargin, lineHeight: \"1.6\", paddingLeft: \"1.5rem\", listStyleType: \"disc\" }}>{children}</ul>\n ),\n ol: ({ children }: MarkdownChildrenProps) => (\n <ol style={{ marginTop: listMargin, marginBottom: listMargin, lineHeight: \"1.6\", paddingLeft: \"1.5rem\", listStyleType: \"decimal\" }}>{children}</ol>\n ),\n li: ({ children }: MarkdownChildrenProps) => <li style={{ marginBottom: listItemMargin, lineHeight: \"1.6\" }}>{children}</li>,\n\n // Blockquote\n blockquote: ({ children }: MarkdownChildrenProps) => (\n <Blockquote size=\"1\" my={blockquoteMargin}>\n {children}\n </Blockquote>\n ),\n\n // Links\n a: ({ href, children }: { href?: string; children?: ReactNode }) => (\n <a href={href} style={{ color: \"var(--accent-9)\", textDecoration: \"underline\" }}>\n {children}\n </a>\n ),\n\n // Text styling\n strong: ({ children }: MarkdownChildrenProps) => (\n <Text weight=\"medium\" style={{ lineHeight: \"1.6\" }}>\n {children}\n </Text>\n ),\n em: ({ children }: MarkdownChildrenProps) => <Text style={{ lineHeight: \"1.6\", fontStyle: \"italic\" }}>{children}</Text>,\n\n // Horizontal rule\n hr: () => (\n <Box style={{ marginTop: hrMargin, marginBottom: hrMargin }}>\n <Separator orientation=\"horizontal\" light />\n </Box>\n ),\n\n // Pre wrapper (pass through to let code handle it)\n pre: ({ children }: MarkdownChildrenProps) => <>{children}</>,\n\n // Tables using KookieUI\n table: ({ children }: MarkdownChildrenProps) => (\n <Box my=\"2\" style={{ overflowX: \"auto\" }}>\n <Table.Root size=\"2\" variant=\"ghost\">\n {children}\n </Table.Root>\n </Box>\n ),\n thead: ({ children }: MarkdownChildrenProps) => <Table.Header>{children}</Table.Header>,\n tbody: ({ children }: MarkdownChildrenProps) => <Table.Body>{children}</Table.Body>,\n tr: ({ children }: MarkdownChildrenProps) => <Table.Row>{children}</Table.Row>,\n th: ({ children }: MarkdownChildrenProps) => <Table.ColumnHeaderCell>{children}</Table.ColumnHeaderCell>,\n td: ({ children }: MarkdownChildrenProps) => <Table.Cell>{children}</Table.Cell>,\n\n // HTML elements for raw HTML support\n sub: ({ children }: MarkdownChildrenProps) => <sub>{children}</sub>,\n sup: ({ children }: MarkdownChildrenProps) => <sup>{children}</sup>,\n br: () => <br />,\n\n // Images - use custom component if provided\n img: imageComponent\n ? (props: React.ImgHTMLAttributes<HTMLImageElement>) => {\n const { src, alt, width, height } = props;\n if (!src || typeof src !== \"string\") return null;\n return imageComponent({\n src,\n alt: alt ?? \"Image\",\n width: width ? String(width) : undefined,\n height: height ? String(height) : undefined,\n });\n }\n : undefined,\n\n // Details/Summary for expandable sections\n details: ({ children }: MarkdownChildrenProps) => <details style={{ padding: \"0.5rem 0\" }}>{children}</details>,\n summary: ({ children }: MarkdownChildrenProps) => <summary style={{ cursor: \"pointer\", fontWeight: 500 }}>{children}</summary>,\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["React", "Blockquote", "Box", "Code", "Heading", "Text", "Table", "Separator", "CodeBlock", "extractLanguage", "className", "extractCode", "children", "code", "child", "createMarkdownComponents", "options", "codeBlockCollapsible", "imageComponent", "inlineCodeHighContrast", "spacing", "isCompact", "headingMargins", "listMargin", "listItemMargin", "codeBlockMargin", "hrMargin", "paragraphMargin", "blockquoteMargin", "inline", "href", "props", "src", "alt", "width", "height"]
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streaming-markdown.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/streaming-markdown.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAC7D,OAAsB,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAOhE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"streaming-markdown.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/streaming-markdown.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAwC,MAAM,OAAO,CAAC;AAC7D,OAAsB,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAOhE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAaxD;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,wBAAwB,GAAG;IAChE;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,KAAK,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAE3D;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CAClC,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,OAAO,CAAC,EAAE,wBAAwB,CAAC;CACpC,CAAC;AA6CF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAY,EAAE,EAAE,sBAAsB,4BA2CtF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import e,{memo as
|
|
1
|
+
"use client";import e,{memo as u,useMemo as p}from"react";import M from"react-markdown";import O from"remark-gfm";import P from"rehype-raw";import i from"harden-react-markdown";import{Box as h,Flex as y}from"@kushagradhawan/kookie-ui";import{createMarkdownComponents as C}from"./create-markdown-components";import{completeUnterminatedMarkdown as b,parseMarkdownIntoBlocks as B}from"./utils/markdown-streaming";const I=typeof i=="function"?i:i.default||i,S=I(M),E=["https://","http://","/"],x=["https://","http://","/","data:"],L=["mailto:","tel:","data:","http:","https:"],A=typeof window<"u"&&window.location?.origin?window.location.origin:"https://app.kookie.ai";function F(o){return o||A}const m=u(({content:o,defaultOrigin:n,components:a})=>e.createElement(h,{width:"100%"},e.createElement(S,{defaultOrigin:n,allowedLinkPrefixes:E,allowedImagePrefixes:x,allowedProtocols:L,allowDataImages:!0,components:a,remarkPlugins:[O],rehypePlugins:[P]},o)),(o,n)=>o.content===n.content&&o.defaultOrigin===n.defaultOrigin&&o.components===n.components);m.displayName="MarkdownBlock";function U({content:o,id:n,options:a={}}){const{defaultOrigin:d,enableBlockMemoization:l=!0,blockParser:s,components:c={},...k}=a,w=p(()=>F(d),[d]),f=p(()=>({...C(k),...c}),[k,c]),r=p(()=>{if(!l||!s){const t=b(o);return t.trim()?[t]:[]}return B(o,s)},[o,l,s]);return r.length?r.length===1?e.createElement(m,{content:r[0],defaultOrigin:w,components:f}):e.createElement(y,{direction:"column",gap:"2",width:"100%"},r.map((t,g)=>e.createElement(m,{key:`${n}-block-${g}`,content:t,defaultOrigin:w,components:f}))):null}export{U as StreamingMarkdown};
|
|
2
2
|
//# sourceMappingURL=streaming-markdown.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/components/markdown/streaming-markdown.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\";\n\nimport React, { memo, useMemo, type ReactNode } from \"react\";\nimport ReactMarkdown, { type Components } from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypeRaw from \"rehype-raw\";\nimport
|
|
5
|
-
"mappings": "aAEA,OAAOA,GAAS,QAAAC,EAAM,WAAAC,MAA+B,QACrD,OAAOC,MAAwC,iBAC/C,OAAOC,MAAe,aACtB,OAAOC,MAAe,aACtB,OAAOC,
|
|
6
|
-
"names": ["React", "memo", "useMemo", "ReactMarkdown", "remarkGfm", "rehypeRaw", "
|
|
4
|
+
"sourcesContent": ["\"use client\";\n\nimport React, { memo, useMemo, type ReactNode } from \"react\";\nimport ReactMarkdown, { type Components } from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\nimport rehypeRaw from \"rehype-raw\";\nimport hardenReactMarkdownModule from \"harden-react-markdown\";\nimport { Box, Flex } from \"@kushagradhawan/kookie-ui\";\nimport { createMarkdownComponents } from \"./create-markdown-components\";\nimport { completeUnterminatedMarkdown, parseMarkdownIntoBlocks } from \"./utils/markdown-streaming\";\nimport type { MarkdownComponentOptions } from \"./types\";\n\n// Handle different export formats\nconst hardenReactMarkdown =\n typeof hardenReactMarkdownModule === \"function\" ? hardenReactMarkdownModule : (hardenReactMarkdownModule as any).default || hardenReactMarkdownModule;\n\nconst HardenedMarkdown = hardenReactMarkdown(ReactMarkdown);\n\nconst LINK_PREFIXES = [\"https://\", \"http://\", \"/\"];\nconst IMAGE_PREFIXES = [\"https://\", \"http://\", \"/\", \"data:\"];\nconst ALLOWED_PROTOCOLS = [\"mailto:\", \"tel:\", \"data:\", \"http:\", \"https:\"];\nconst DEFAULT_APP_ORIGIN = typeof window !== \"undefined\" && window.location?.origin ? window.location.origin : \"https://app.kookie.ai\";\n\n/**\n * Options for StreamingMarkdown component\n */\nexport type StreamingMarkdownOptions = MarkdownComponentOptions & {\n /**\n * Security origin for link/image validation\n * @default window.location.origin or \"https://app.kookie.ai\"\n */\n defaultOrigin?: string;\n\n /**\n * Whether to enable block-level memoization for performance\n * Recommended for streaming scenarios where content updates frequently\n * @default true\n */\n enableBlockMemoization?: boolean;\n\n /**\n * Custom parser for splitting content into blocks\n * If not provided, content will be rendered as a single block\n * For optimal streaming performance, use marked.lexer with GFM enabled\n */\n blockParser?: (content: string) => Array<{ raw?: string }>;\n\n /**\n * Override default component mappings\n */\n components?: Partial<Components>;\n};\n\ntype StreamingMarkdownProps = {\n /**\n * Markdown content to render (supports streaming/incomplete markdown)\n */\n content: string;\n\n /**\n * Unique identifier for this markdown instance (used for keys)\n */\n id: string;\n\n /**\n * Optional configuration\n */\n options?: StreamingMarkdownOptions;\n};\n\ntype MarkdownBlockProps = {\n content: string;\n defaultOrigin: string;\n components: Components;\n};\n\n/**\n * Resolves the default origin for security validation\n */\nfunction resolveDefaultOrigin(customOrigin?: string): string {\n if (customOrigin) {\n return customOrigin;\n }\n return DEFAULT_APP_ORIGIN;\n}\n\n/**\n * Memoized markdown block component for efficient streaming rendering\n */\nconst MarkdownBlock = memo(\n ({ content, defaultOrigin, components }: MarkdownBlockProps) => {\n return (\n <Box width=\"100%\">\n <HardenedMarkdown\n defaultOrigin={defaultOrigin}\n allowedLinkPrefixes={LINK_PREFIXES}\n allowedImagePrefixes={IMAGE_PREFIXES}\n allowedProtocols={ALLOWED_PROTOCOLS}\n allowDataImages\n components={components}\n remarkPlugins={[remarkGfm]}\n rehypePlugins={[rehypeRaw]}\n >\n {content}\n </HardenedMarkdown>\n </Box>\n );\n },\n (previous, next) => previous.content === next.content && previous.defaultOrigin === next.defaultOrigin && previous.components === next.components\n);\n\nMarkdownBlock.displayName = \"MarkdownBlock\";\n\n/**\n * StreamingMarkdown - A drop-in markdown renderer designed for AI streaming.\n *\n * Features:\n * - Unterminated block parsing (handles incomplete markdown during streaming)\n * - Block-level memoization for performance\n * - Security hardening (validates links/images)\n * - GitHub Flavored Markdown support\n * - KookieUI component integration\n * - Code syntax highlighting via CodeBlock\n *\n * @example\n * ```tsx\n * import { StreamingMarkdown } from '@kushagradhawan/kookie-blocks';\n * import { marked } from 'marked';\n *\n * function ChatMessage({ message }) {\n * return (\n * <StreamingMarkdown\n * content={message.content}\n * id={message.id}\n * options={{\n * blockParser: (content) => marked.lexer(content, { gfm: true }),\n * enableBlockMemoization: true,\n * }}\n * />\n * );\n * }\n * ```\n */\nexport function StreamingMarkdown({ content, id, options = {} }: StreamingMarkdownProps) {\n const { defaultOrigin: customOrigin, enableBlockMemoization = true, blockParser, components: customComponents = {}, ...componentOptions } = options;\n\n // Resolve security origin\n const defaultOrigin = useMemo(() => resolveDefaultOrigin(customOrigin), [customOrigin]);\n\n // Create component mappings with custom overrides\n const markdownComponents = useMemo(() => {\n const baseComponents = createMarkdownComponents(componentOptions);\n return {\n ...baseComponents,\n ...customComponents,\n };\n }, [componentOptions, customComponents]);\n\n // Parse content into blocks for memoization (if enabled and parser provided)\n const blocks = useMemo(() => {\n if (!enableBlockMemoization || !blockParser) {\n // No block splitting - just complete unterminated markdown\n const completed = completeUnterminatedMarkdown(content);\n return completed.trim() ? [completed] : [];\n }\n\n return parseMarkdownIntoBlocks(content, blockParser);\n }, [content, enableBlockMemoization, blockParser]);\n\n if (!blocks.length) {\n return null;\n }\n\n // Single block - no need for wrapper\n if (blocks.length === 1) {\n return <MarkdownBlock content={blocks[0]} defaultOrigin={defaultOrigin} components={markdownComponents} />;\n }\n\n // Multiple blocks - render with flex wrapper\n return (\n <Flex direction=\"column\" gap=\"2\" width=\"100%\">\n {blocks.map((block, index) => (\n <MarkdownBlock key={`${id}-block-${index}`} content={block} defaultOrigin={defaultOrigin} components={markdownComponents} />\n ))}\n </Flex>\n );\n}\n"],
|
|
5
|
+
"mappings": "aAEA,OAAOA,GAAS,QAAAC,EAAM,WAAAC,MAA+B,QACrD,OAAOC,MAAwC,iBAC/C,OAAOC,MAAe,aACtB,OAAOC,MAAe,aACtB,OAAOC,MAA+B,wBACtC,OAAS,OAAAC,EAAK,QAAAC,MAAY,4BAC1B,OAAS,4BAAAC,MAAgC,+BACzC,OAAS,gCAAAC,EAA8B,2BAAAC,MAA+B,6BAItE,MAAMC,EACJ,OAAON,GAA8B,WAAaA,EAA6BA,EAAkC,SAAWA,EAExHO,EAAmBD,EAAoBT,CAAa,EAEpDW,EAAgB,CAAC,WAAY,UAAW,GAAG,EAC3CC,EAAiB,CAAC,WAAY,UAAW,IAAK,OAAO,EACrDC,EAAoB,CAAC,UAAW,OAAQ,QAAS,QAAS,QAAQ,EAClEC,EAAqB,OAAO,OAAW,KAAe,OAAO,UAAU,OAAS,OAAO,SAAS,OAAS,wBA0D/G,SAASC,EAAqBC,EAA+B,CAC3D,OAAIA,GAGGF,CACT,CAKA,MAAMG,EAAgBnB,EACpB,CAAC,CAAE,QAAAoB,EAAS,cAAAC,EAAe,WAAAC,CAAW,IAElCvB,EAAA,cAACO,EAAA,CAAI,MAAM,QACTP,EAAA,cAACa,EAAA,CACC,cAAeS,EACf,oBAAqBR,EACrB,qBAAsBC,EACtB,iBAAkBC,EAClB,gBAAe,GACf,WAAYO,EACZ,cAAe,CAACnB,CAAS,EACzB,cAAe,CAACC,CAAS,GAExBgB,CACH,CACF,EAGJ,CAACG,EAAUC,IAASD,EAAS,UAAYC,EAAK,SAAWD,EAAS,gBAAkBC,EAAK,eAAiBD,EAAS,aAAeC,EAAK,UACzI,EAEAL,EAAc,YAAc,gBAgCrB,SAASM,EAAkB,CAAE,QAAAL,EAAS,GAAAM,EAAI,QAAAC,EAAU,CAAC,CAAE,EAA2B,CACvF,KAAM,CAAE,cAAeT,EAAc,uBAAAU,EAAyB,GAAM,YAAAC,EAAa,WAAYC,EAAmB,CAAC,EAAG,GAAGC,CAAiB,EAAIJ,EAGtIN,EAAgBpB,EAAQ,IAAMgB,EAAqBC,CAAY,EAAG,CAACA,CAAY,CAAC,EAGhFc,EAAqB/B,EAAQ,KAE1B,CACL,GAFqBO,EAAyBuB,CAAgB,EAG9D,GAAGD,CACL,GACC,CAACC,EAAkBD,CAAgB,CAAC,EAGjCG,EAAShC,EAAQ,IAAM,CAC3B,GAAI,CAAC2B,GAA0B,CAACC,EAAa,CAE3C,MAAMK,EAAYzB,EAA6BW,CAAO,EACtD,OAAOc,EAAU,KAAK,EAAI,CAACA,CAAS,EAAI,CAAC,CAC3C,CAEA,OAAOxB,EAAwBU,EAASS,CAAW,CACrD,EAAG,CAACT,EAASQ,EAAwBC,CAAW,CAAC,EAEjD,OAAKI,EAAO,OAKRA,EAAO,SAAW,EACblC,EAAA,cAACoB,EAAA,CAAc,QAASc,EAAO,CAAC,EAAG,cAAeZ,EAAe,WAAYW,EAAoB,EAKxGjC,EAAA,cAACQ,EAAA,CAAK,UAAU,SAAS,IAAI,IAAI,MAAM,QACpC0B,EAAO,IAAI,CAACE,EAAOC,IAClBrC,EAAA,cAACoB,EAAA,CAAc,IAAK,GAAGO,CAAE,UAAUU,CAAK,GAAI,QAASD,EAAO,cAAed,EAAe,WAAYW,EAAoB,CAC3H,CACH,EAdO,IAgBX",
|
|
6
|
+
"names": ["React", "memo", "useMemo", "ReactMarkdown", "remarkGfm", "rehypeRaw", "hardenReactMarkdownModule", "Box", "Flex", "createMarkdownComponents", "completeUnterminatedMarkdown", "parseMarkdownIntoBlocks", "hardenReactMarkdown", "HardenedMarkdown", "LINK_PREFIXES", "IMAGE_PREFIXES", "ALLOWED_PROTOCOLS", "DEFAULT_APP_ORIGIN", "resolveDefaultOrigin", "customOrigin", "MarkdownBlock", "content", "defaultOrigin", "components", "previous", "next", "StreamingMarkdown", "id", "options", "enableBlockMemoization", "blockParser", "customComponents", "componentOptions", "markdownComponents", "blocks", "completed", "block", "index"]
|
|
7
7
|
}
|
|
@@ -22,6 +22,13 @@ export type MarkdownComponentOptions = {
|
|
|
22
22
|
* @default true
|
|
23
23
|
*/
|
|
24
24
|
inlineCodeHighContrast?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Spacing density for markdown elements
|
|
27
|
+
* - "compact": Tighter spacing, ideal for chat/conversational interfaces
|
|
28
|
+
* - "spacious": More breathing room, ideal for documentation/articles
|
|
29
|
+
* @default "spacious"
|
|
30
|
+
*/
|
|
31
|
+
spacing?: "compact" | "spacious";
|
|
25
32
|
};
|
|
26
33
|
/**
|
|
27
34
|
* Common props for markdown child components
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,SAAS,CAAC;IAEvG;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/markdown/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,SAAS,CAAC;IAEvG;;;OAGG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAEjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC;CAClC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kushagradhawan/kookie-blocks",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/KushagraDhawan1997/kookie-blocks.git"
|
|
@@ -113,12 +113,15 @@
|
|
|
113
113
|
},
|
|
114
114
|
"devDependencies": {
|
|
115
115
|
"@eslint/js": "^9.18.0",
|
|
116
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
117
|
+
"@testing-library/react": "^16.3.1",
|
|
116
118
|
"@types/react": "^19.0.2",
|
|
117
119
|
"@types/react-dom": "^19.0.2",
|
|
118
120
|
"autoprefixer": "10.4.19",
|
|
119
121
|
"esbuild": "0.20.0",
|
|
120
122
|
"eslint": "^9.18.0",
|
|
121
123
|
"globals": "^15.14.0",
|
|
124
|
+
"jsdom": "^27.3.0",
|
|
122
125
|
"postcss": "8.4.33",
|
|
123
126
|
"postcss-cli": "11.0.0",
|
|
124
127
|
"postcss-combine-duplicated-selectors": "10.0.3",
|
|
@@ -305,7 +305,7 @@ export function CodeBlock({
|
|
|
305
305
|
|
|
306
306
|
return (
|
|
307
307
|
<CodeBlockContext.Provider value={true}>
|
|
308
|
-
<Box className="docs-code-block"
|
|
308
|
+
<Box className="docs-code-block" my="3">
|
|
309
309
|
<Flex direction="column" gap="2">
|
|
310
310
|
{preview && (
|
|
311
311
|
<PreviewSection background={background} backgroundProps={backgroundProps}>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { type ReactNode } from "react";
|
|
2
2
|
import type { Components } from "react-markdown";
|
|
3
|
-
import { Blockquote, Box, Code, Flex, Heading, Text, Table } from "@kushagradhawan/kookie-ui";
|
|
3
|
+
import { Blockquote, Box, Code, Flex, Heading, Text, Table, Separator } from "@kushagradhawan/kookie-ui";
|
|
4
4
|
import { CodeBlock } from "../code";
|
|
5
5
|
import type { MarkdownComponentOptions, MarkdownChildrenProps } from "./types";
|
|
6
6
|
|
|
@@ -56,44 +56,61 @@ function extractCode(children?: ReactNode): string {
|
|
|
56
56
|
* ```
|
|
57
57
|
*/
|
|
58
58
|
export function createMarkdownComponents(options: MarkdownComponentOptions = {}): Components {
|
|
59
|
-
const { codeBlockCollapsible = false, imageComponent, inlineCodeHighContrast = true } = options;
|
|
59
|
+
const { codeBlockCollapsible = false, imageComponent, inlineCodeHighContrast = true, spacing = "spacious" } = options;
|
|
60
|
+
|
|
61
|
+
// Spacing configuration
|
|
62
|
+
const isCompact = spacing === "compact";
|
|
63
|
+
const headingMargins = {
|
|
64
|
+
h1: { top: isCompact ? "1.5rem" : "3rem", bottom: isCompact ? "1rem" : "1.5rem" },
|
|
65
|
+
h2: { top: isCompact ? "2rem" : "3rem", bottom: isCompact ? "0.375rem" : "0.5rem" },
|
|
66
|
+
h3: { top: isCompact ? "1.5rem" : "2rem", bottom: isCompact ? "0.375rem" : "0.5rem" },
|
|
67
|
+
h4: { top: isCompact ? "0.5rem" : "0.625rem", bottom: isCompact ? "0.25rem" : "0.5rem" },
|
|
68
|
+
h5: { top: isCompact ? "0.375rem" : "0.5rem", bottom: isCompact ? "0.25rem" : "0.5rem" },
|
|
69
|
+
h6: { top: isCompact ? "0.375rem" : "0.5rem", bottom: isCompact ? "0.25rem" : "0.5rem" },
|
|
70
|
+
};
|
|
71
|
+
const listMargin = isCompact ? "0.25rem" : "0.5rem";
|
|
72
|
+
const listItemMargin = isCompact ? "0.125rem" : "0.25rem";
|
|
73
|
+
const codeBlockMargin = isCompact ? "1" : "2";
|
|
74
|
+
const hrMargin = isCompact ? "0.375rem" : "0.5rem";
|
|
75
|
+
const paragraphMargin = isCompact ? "0" : "0.5rem";
|
|
76
|
+
const blockquoteMargin = isCompact ? "0.5rem" : "1rem";
|
|
60
77
|
|
|
61
78
|
return {
|
|
62
79
|
// Headings with consistent visual hierarchy (9-6-5-4-3-2)
|
|
63
80
|
h1: ({ children }: MarkdownChildrenProps) => (
|
|
64
|
-
<Heading size="9" weight="medium" as="h1" style={{ marginTop:
|
|
81
|
+
<Heading size="9" weight="medium" as="h1" style={{ marginTop: headingMargins.h1.top, marginBottom: headingMargins.h1.bottom }}>
|
|
65
82
|
{children}
|
|
66
83
|
</Heading>
|
|
67
84
|
),
|
|
68
85
|
h2: ({ children }: MarkdownChildrenProps) => (
|
|
69
|
-
<Heading weight="medium" size="
|
|
86
|
+
<Heading weight="medium" size="7" as="h2" style={{ marginTop: headingMargins.h2.top, marginBottom: headingMargins.h2.bottom }}>
|
|
70
87
|
{children}
|
|
71
88
|
</Heading>
|
|
72
89
|
),
|
|
73
90
|
h3: ({ children }: MarkdownChildrenProps) => (
|
|
74
|
-
<Heading weight="medium" size="5" as="h3" style={{ marginTop:
|
|
91
|
+
<Heading weight="medium" size="5" as="h3" style={{ marginTop: headingMargins.h3.top, marginBottom: headingMargins.h3.bottom }}>
|
|
75
92
|
{children}
|
|
76
93
|
</Heading>
|
|
77
94
|
),
|
|
78
95
|
h4: ({ children }: MarkdownChildrenProps) => (
|
|
79
|
-
<Heading weight="medium" size="4" as="h4" style={{ marginTop:
|
|
96
|
+
<Heading weight="medium" size="4" as="h4" style={{ marginTop: headingMargins.h4.top, marginBottom: headingMargins.h4.bottom }}>
|
|
80
97
|
{children}
|
|
81
98
|
</Heading>
|
|
82
99
|
),
|
|
83
100
|
h5: ({ children }: MarkdownChildrenProps) => (
|
|
84
|
-
<Heading weight="medium" size="3" as="h5" style={{ marginTop:
|
|
101
|
+
<Heading weight="medium" size="3" as="h5" style={{ marginTop: headingMargins.h5.top, marginBottom: headingMargins.h5.bottom }}>
|
|
85
102
|
{children}
|
|
86
103
|
</Heading>
|
|
87
104
|
),
|
|
88
105
|
h6: ({ children }: MarkdownChildrenProps) => (
|
|
89
|
-
<Heading weight="medium" size="2" as="h6" style={{ marginTop:
|
|
106
|
+
<Heading weight="medium" size="2" as="h6" style={{ marginTop: headingMargins.h6.top, marginBottom: headingMargins.h6.bottom }}>
|
|
90
107
|
{children}
|
|
91
108
|
</Heading>
|
|
92
109
|
),
|
|
93
110
|
|
|
94
111
|
// Paragraph text
|
|
95
112
|
p: ({ children }: MarkdownChildrenProps) => (
|
|
96
|
-
<Text size="3" as="p" style={{ lineHeight: "1.6" }}>
|
|
113
|
+
<Text size="3" as="p" style={{ lineHeight: "1.6", marginTop: paragraphMargin, marginBottom: paragraphMargin }}>
|
|
97
114
|
{children}
|
|
98
115
|
</Text>
|
|
99
116
|
),
|
|
@@ -115,7 +132,7 @@ export function createMarkdownComponents(options: MarkdownComponentOptions = {})
|
|
|
115
132
|
}
|
|
116
133
|
|
|
117
134
|
return (
|
|
118
|
-
<Box my=
|
|
135
|
+
<Box my={codeBlockMargin} style={{ minWidth: 0 }}>
|
|
119
136
|
<CodeBlock code={code} language={extractLanguage(className)} collapsible={codeBlockCollapsible} />
|
|
120
137
|
</Box>
|
|
121
138
|
);
|
|
@@ -123,15 +140,19 @@ export function createMarkdownComponents(options: MarkdownComponentOptions = {})
|
|
|
123
140
|
|
|
124
141
|
// Lists
|
|
125
142
|
ul: ({ children }: MarkdownChildrenProps) => (
|
|
126
|
-
<ul style={{ marginTop:
|
|
143
|
+
<ul style={{ marginTop: listMargin, marginBottom: listMargin, lineHeight: "1.6", paddingLeft: "1.5rem", listStyleType: "disc" }}>{children}</ul>
|
|
127
144
|
),
|
|
128
145
|
ol: ({ children }: MarkdownChildrenProps) => (
|
|
129
|
-
<ol style={{ marginTop:
|
|
146
|
+
<ol style={{ marginTop: listMargin, marginBottom: listMargin, lineHeight: "1.6", paddingLeft: "1.5rem", listStyleType: "decimal" }}>{children}</ol>
|
|
130
147
|
),
|
|
131
|
-
li: ({ children }: MarkdownChildrenProps) => <li style={{ marginBottom:
|
|
148
|
+
li: ({ children }: MarkdownChildrenProps) => <li style={{ marginBottom: listItemMargin, lineHeight: "1.6" }}>{children}</li>,
|
|
132
149
|
|
|
133
150
|
// Blockquote
|
|
134
|
-
blockquote: ({ children }: MarkdownChildrenProps) =>
|
|
151
|
+
blockquote: ({ children }: MarkdownChildrenProps) => (
|
|
152
|
+
<Blockquote size="1" my={blockquoteMargin}>
|
|
153
|
+
{children}
|
|
154
|
+
</Blockquote>
|
|
155
|
+
),
|
|
135
156
|
|
|
136
157
|
// Links
|
|
137
158
|
a: ({ href, children }: { href?: string; children?: ReactNode }) => (
|
|
@@ -150,16 +171,9 @@ export function createMarkdownComponents(options: MarkdownComponentOptions = {})
|
|
|
150
171
|
|
|
151
172
|
// Horizontal rule
|
|
152
173
|
hr: () => (
|
|
153
|
-
<
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
marginTop: "0.5rem",
|
|
157
|
-
marginBottom: "0.5rem",
|
|
158
|
-
height: "1px",
|
|
159
|
-
width: "100%",
|
|
160
|
-
opacity: 0.5,
|
|
161
|
-
}}
|
|
162
|
-
/>
|
|
174
|
+
<Box style={{ marginTop: hrMargin, marginBottom: hrMargin }}>
|
|
175
|
+
<Separator orientation="horizontal" light />
|
|
176
|
+
</Box>
|
|
163
177
|
),
|
|
164
178
|
|
|
165
179
|
// Pre wrapper (pass through to let code handle it)
|
|
@@ -4,12 +4,16 @@ import React, { memo, useMemo, type ReactNode } from "react";
|
|
|
4
4
|
import ReactMarkdown, { type Components } from "react-markdown";
|
|
5
5
|
import remarkGfm from "remark-gfm";
|
|
6
6
|
import rehypeRaw from "rehype-raw";
|
|
7
|
-
import
|
|
7
|
+
import hardenReactMarkdownModule from "harden-react-markdown";
|
|
8
8
|
import { Box, Flex } from "@kushagradhawan/kookie-ui";
|
|
9
9
|
import { createMarkdownComponents } from "./create-markdown-components";
|
|
10
10
|
import { completeUnterminatedMarkdown, parseMarkdownIntoBlocks } from "./utils/markdown-streaming";
|
|
11
11
|
import type { MarkdownComponentOptions } from "./types";
|
|
12
12
|
|
|
13
|
+
// Handle different export formats
|
|
14
|
+
const hardenReactMarkdown =
|
|
15
|
+
typeof hardenReactMarkdownModule === "function" ? hardenReactMarkdownModule : (hardenReactMarkdownModule as any).default || hardenReactMarkdownModule;
|
|
16
|
+
|
|
13
17
|
const HardenedMarkdown = hardenReactMarkdown(ReactMarkdown);
|
|
14
18
|
|
|
15
19
|
const LINK_PREFIXES = ["https://", "http://", "/"];
|
|
@@ -20,6 +20,14 @@ export type MarkdownComponentOptions = {
|
|
|
20
20
|
* @default true
|
|
21
21
|
*/
|
|
22
22
|
inlineCodeHighContrast?: boolean;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Spacing density for markdown elements
|
|
26
|
+
* - "compact": Tighter spacing, ideal for chat/conversational interfaces
|
|
27
|
+
* - "spacious": More breathing room, ideal for documentation/articles
|
|
28
|
+
* @default "spacious"
|
|
29
|
+
*/
|
|
30
|
+
spacing?: "compact" | "spacious";
|
|
23
31
|
};
|
|
24
32
|
|
|
25
33
|
/**
|