@ably/ui 17.8.0 → 17.9.1-dev.f8cf1684
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/core/Code.js +1 -1
- package/core/Code.js.map +1 -1
- package/core/CodeSnippet/ApiKeySelector.js +1 -1
- package/core/CodeSnippet/ApiKeySelector.js.map +1 -1
- package/core/CodeSnippet/CopyButton.js +1 -1
- package/core/CodeSnippet/CopyButton.js.map +1 -1
- package/core/CodeSnippet/LanguageSelector.js +1 -1
- package/core/CodeSnippet/LanguageSelector.js.map +1 -1
- package/core/CodeSnippet/PlainCodeView.js +1 -1
- package/core/CodeSnippet/PlainCodeView.js.map +1 -1
- package/core/CodeSnippet/TooltipButton.js +1 -1
- package/core/CodeSnippet/TooltipButton.js.map +1 -1
- package/core/CodeSnippet.js +1 -1
- package/core/CodeSnippet.js.map +1 -1
- package/core/CookieMessage.js +1 -1
- package/core/CookieMessage.js.map +1 -1
- package/core/Expander.js +1 -1
- package/core/Expander.js.map +1 -1
- package/core/Flash.js +1 -1
- package/core/Flash.js.map +1 -1
- package/core/Header/HeaderLinks.js +1 -1
- package/core/Header/HeaderLinks.js.map +1 -1
- package/core/Header.js +1 -1
- package/core/Header.js.map +1 -1
- package/core/Meganav.js +1 -1
- package/core/Meganav.js.map +1 -1
- package/core/Pricing/PricingCards.js +1 -1
- package/core/Pricing/PricingCards.js.map +1 -1
- package/core/Slider.js +1 -1
- package/core/Slider.js.map +1 -1
- package/core/TabMenu.js +1 -1
- package/core/TabMenu.js.map +1 -1
- package/core/Tooltip.js +1 -1
- package/core/Tooltip.js.map +1 -1
- package/index.d.ts +15 -40
- package/package.json +7 -2
- package/core/utils/useCopyToClipboard.js +0 -2
- package/core/utils/useCopyToClipboard.js.map +0 -1
package/core/Code.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React from"react";import{highlightSnippet,registerDefaultLanguages}from"./utils/syntax-highlighter";import languagesRegistry from"./utils/syntax-highlighter-registry";import cn from"./utils/cn";registerDefaultLanguages(languagesRegistry);const Code=({language,snippet,textSize="ui-text-code",padding="p-8",additionalCSS="",showLines,lineCSS})=>{const trimmedSnippet=snippet.trimEnd();const HTMLraw=highlightSnippet(language,trimmedSnippet)??"";const className=`language-${language} ${textSize}`;const lines=trimmedSnippet.split(/\r\n|\r|\n/);const lineCount=lines.length;return React.createElement("div",{className:cn("hljs overflow-y-auto flex",padding,additionalCSS),"data-id":"code"},showLines?React.createElement("div",{className:"text-
|
|
1
|
+
import React from"react";import{highlightSnippet,registerDefaultLanguages}from"./utils/syntax-highlighter";import languagesRegistry from"./utils/syntax-highlighter-registry";import cn from"./utils/cn";registerDefaultLanguages(languagesRegistry);const Code=({language,snippet,textSize="ui-text-code",padding="p-8",additionalCSS="",showLines,lineCSS})=>{const trimmedSnippet=snippet.trimEnd();const HTMLraw=highlightSnippet(language,trimmedSnippet)??"";const className=`language-${language} ${textSize}`;const lines=trimmedSnippet.split(/\r\n|\r|\n/);const lineCount=lines.length;return React.createElement("div",{className:cn("hljs overflow-y-auto flex",padding,additionalCSS),"data-id":"code"},showLines?React.createElement("div",{className:"text-p4 leading-normal pt-px"},[...Array(lineCount)].map((_,i)=>React.createElement("p",{className:cn("mr-4 font-mono text-right text-neutral-800",lineCSS),key:i},i+1))):null,React.createElement("pre",{lang:language,className:"overflow-x-auto h-full flex-1 text-p4 leading-normal"},React.createElement("code",{className:className,dangerouslySetInnerHTML:{__html:HTMLraw}})))};export default Code;
|
|
2
2
|
//# sourceMappingURL=Code.js.map
|
package/core/Code.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/Code.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n highlightSnippet,\n registerDefaultLanguages,\n} from \"./utils/syntax-highlighter\";\nimport languagesRegistry from \"./utils/syntax-highlighter-registry\";\nimport cn from \"./utils/cn\";\n\nregisterDefaultLanguages(languagesRegistry);\n\ntype CodeProps = {\n language: string;\n snippet: string;\n textSize?: string;\n padding?: string;\n additionalCSS?: string;\n showLines?: boolean;\n lineCSS?: string;\n};\n\nconst Code = ({\n language,\n snippet,\n textSize = \"ui-text-code\",\n padding = \"p-8\",\n additionalCSS = \"\",\n showLines,\n lineCSS,\n}: CodeProps) => {\n // Trim the snippet and remove trailing empty lines\n const trimmedSnippet = snippet.trimEnd();\n const HTMLraw = highlightSnippet(language, trimmedSnippet) ?? \"\";\n const className = `language-${language} ${textSize}`;\n\n // Calculate line count after removing trailing empty lines\n const lines = trimmedSnippet.split(/\\r\\n|\\r|\\n/);\n const lineCount = lines.length;\n\n return (\n <div\n className={cn(\"hljs overflow-y-auto flex\", padding, additionalCSS)}\n data-id=\"code\"\n >\n {showLines ? (\n <div className=\"text-
|
|
1
|
+
{"version":3,"sources":["../../src/core/Code.tsx"],"sourcesContent":["import React from \"react\";\nimport {\n highlightSnippet,\n registerDefaultLanguages,\n} from \"./utils/syntax-highlighter\";\nimport languagesRegistry from \"./utils/syntax-highlighter-registry\";\nimport cn from \"./utils/cn\";\n\nregisterDefaultLanguages(languagesRegistry);\n\ntype CodeProps = {\n language: string;\n snippet: string;\n textSize?: string;\n padding?: string;\n additionalCSS?: string;\n showLines?: boolean;\n lineCSS?: string;\n};\n\nconst Code = ({\n language,\n snippet,\n textSize = \"ui-text-code\",\n padding = \"p-8\",\n additionalCSS = \"\",\n showLines,\n lineCSS,\n}: CodeProps) => {\n // Trim the snippet and remove trailing empty lines\n const trimmedSnippet = snippet.trimEnd();\n const HTMLraw = highlightSnippet(language, trimmedSnippet) ?? \"\";\n const className = `language-${language} ${textSize}`;\n\n // Calculate line count after removing trailing empty lines\n const lines = trimmedSnippet.split(/\\r\\n|\\r|\\n/);\n const lineCount = lines.length;\n\n return (\n <div\n className={cn(\"hljs overflow-y-auto flex\", padding, additionalCSS)}\n data-id=\"code\"\n >\n {showLines ? (\n <div className=\"text-p4 leading-normal pt-px\">\n {[...Array(lineCount)].map((_, i) => (\n <p\n className={cn(\n \"mr-4 font-mono text-right text-neutral-800\",\n lineCSS,\n )}\n key={i}\n >\n {i + 1}\n </p>\n ))}\n </div>\n ) : null}\n <pre\n lang={language}\n className=\"overflow-x-auto h-full flex-1 text-p4 leading-normal\"\n >\n <code\n className={className}\n dangerouslySetInnerHTML={{ __html: HTMLraw }}\n />\n </pre>\n </div>\n );\n};\n\nexport default Code;\n"],"names":["React","highlightSnippet","registerDefaultLanguages","languagesRegistry","cn","Code","language","snippet","textSize","padding","additionalCSS","showLines","lineCSS","trimmedSnippet","trimEnd","HTMLraw","className","lines","split","lineCount","length","div","data-id","Array","map","_","i","p","key","pre","lang","code","dangerouslySetInnerHTML","__html"],"mappings":"AAAA,OAAOA,UAAW,OAAQ,AAC1B,QACEC,gBAAgB,CAChBC,wBAAwB,KACnB,4BAA6B,AACpC,QAAOC,sBAAuB,qCAAsC,AACpE,QAAOC,OAAQ,YAAa,CAE5BF,yBAAyBC,mBAYzB,MAAME,KAAO,CAAC,CACZC,QAAQ,CACRC,OAAO,CACPC,SAAW,cAAc,CACzBC,QAAU,KAAK,CACfC,cAAgB,EAAE,CAClBC,SAAS,CACTC,OAAO,CACG,IAEV,MAAMC,eAAiBN,QAAQO,OAAO,GACtC,MAAMC,QAAUd,iBAAiBK,SAAUO,iBAAmB,GAC9D,MAAMG,UAAY,CAAC,SAAS,EAAEV,SAAS,CAAC,EAAEE,SAAS,CAAC,CAGpD,MAAMS,MAAQJ,eAAeK,KAAK,CAAC,cACnC,MAAMC,UAAYF,MAAMG,MAAM,CAE9B,OACE,oBAACC,OACCL,UAAWZ,GAAG,4BAA6BK,QAASC,eACpDY,UAAQ,QAEPX,UACC,oBAACU,OAAIL,UAAU,gCACZ,IAAIO,MAAMJ,WAAW,CAACK,GAAG,CAAC,CAACC,EAAGC,IAC7B,oBAACC,KACCX,UAAWZ,GACT,6CACAQ,SAEFgB,IAAKF,GAEJA,EAAI,KAIT,KACJ,oBAACG,OACCC,KAAMxB,SACNU,UAAU,wDAEV,oBAACe,QACCf,UAAWA,UACXgB,wBAAyB,CAAEC,OAAQlB,OAAQ,KAKrD,CAEA,gBAAeV,IAAK"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{useMemo}from"react";import*as Select from"@radix-ui/react-select";import Badge from"../Badge";import Icon from"../Icon";import Tooltip from"../Tooltip";const ApiKeySelector=({apiKeys,selectedApiKey,onApiKeyChange})=>{const isDemoMode=useMemo(()=>apiKeys?.length===1&&apiKeys[0].app==="demo",[apiKeys]);const renderDemoMode=useMemo(()=>React.createElement("div",{className:"flex items-center gap-2"},React.createElement(Badge,{className:"ml-1 bg-neutral-200 dark:bg-neutral-1100"},"DEMO ONLY"),React.createElement(Tooltip,{className:"ml-0",triggerElement:React.createElement(Icon,{name:"icon-gui-information-circle-outline",size:"
|
|
1
|
+
import React,{useMemo}from"react";import*as Select from"@radix-ui/react-select";import Badge from"../Badge";import Icon from"../Icon";import Tooltip from"../Tooltip";const ApiKeySelector=({apiKeys,selectedApiKey,onApiKeyChange})=>{const isDemoMode=useMemo(()=>apiKeys?.length===1&&apiKeys[0].app==="demo",[apiKeys]);const renderDemoMode=useMemo(()=>React.createElement("div",{className:"flex items-center gap-2"},React.createElement(Badge,{className:"ml-1 bg-neutral-200 dark:bg-neutral-1100"},"DEMO ONLY"),React.createElement(Tooltip,{className:"ml-0",triggerProps:{className:"h-5"},contentProps:{className:"bg-neutral-1100 dark:bg-neutral-200 text-neutral-300 dark:text-neutral-1000"},triggerElement:React.createElement("div",{className:"group/code-snippet-tooltip-icon-hover flex items-center justify-center"},React.createElement(Icon,{name:"icon-gui-information-circle-outline",size:"20px",color:"text-neutral-700 dark:text-neutral-600",additionalCSS:"group-hover/code-snippet-tooltip-icon-hover:hidden"}),React.createElement(Icon,{name:"icon-gui-information-circle-solid",size:"20px",color:"text-neutral-1300 dark:text-neutral-000",additionalCSS:"group-hover/code-snippet-tooltip-icon-hover:flex hidden"}))},"This code example uses a temporary key that is rate limited and expires in 4 hrs. Sign in to Ably to use your API keys instead.")),[]);const renderApiKeyDropdown=useMemo(()=>{if(isDemoMode){return renderDemoMode}if(!apiKeys?.length){return null}return React.createElement(Select.Root,{value:selectedApiKey,onValueChange:onApiKeyChange},React.createElement(Select.Trigger,{className:"font-sans inline-flex items-center justify-between rounded px-3 py-2 ml-1 text-14 text-neutral-1300 dark:text-neutral-000 bg-neutral-200 dark:bg-neutral-1100 hover:bg-neutral-300 dark:hover:bg-neutral-1000 gap-2 focus-base border border-neutral-300 dark:border-neutral-1000 transition-colors","aria-label":"API Key"},React.createElement(Select.Value,null),React.createElement(Select.Icon,{className:"size-4"},React.createElement(Icon,{name:"icon-gui-chevron-down-micro",size:"16px"}))),React.createElement(Select.Portal,null,React.createElement(Select.Content,{className:"overflow-hidden rounded-lg bg-neutral-000 dark:bg-neutral-1300 border border-neutral-300 dark:border-neutral-1000 shadow-md z-50"},React.createElement(Select.ScrollUpButton,{className:"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base"},React.createElement(Icon,{name:"icon-gui-chevron-down-outline",size:"16px",additionalCSS:"rotate-180"})),React.createElement(Select.Viewport,{className:"rounded-lg font-sans"},apiKeys.map(apiKeyItem=>React.createElement(Select.Group,{key:apiKeyItem.app},apiKeys.length>1&&React.createElement(Select.Label,{className:"text-neutral-700 rounded-none dark:text-neutral-600 p-1 bg-neutral-200 dark:bg-neutral-1100"},apiKeyItem.app),apiKeyItem.keys.map(({name,key})=>React.createElement(Select.Item,{key:`${apiKeyItem.app}-${name}-${key}`,value:key,className:"relative flex items-center justify-between m-2 p-2 rounded-lg text-14 text-neutral-1300 dark:text-neutral-000 select-none hover:bg-neutral-100 dark:hover:bg-neutral-1200 data-[highlighted]:outline-none data-[highlighted]:bg-neutral-100 dark:data-[highlighted]:bg-neutral-1200 focus-base min-w-64"},React.createElement(Select.ItemText,null,key.length>10?`${key.substring(0,10)}...`:key,React.createElement("span",{className:"font-light"},name&&` - ${name}`)),React.createElement(Select.ItemIndicator,{className:"size-4"},React.createElement(Icon,{name:"icon-gui-check-micro",size:"16px"}))))))),React.createElement(Select.ScrollDownButton,{className:"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base"},React.createElement(Icon,{name:"icon-gui-chevron-down-outline",size:"16px"})))))},[apiKeys,isDemoMode,selectedApiKey,onApiKeyChange,renderDemoMode]);return React.createElement("div",{className:"flex items-center border-t border-neutral-300 dark:border-neutral-1000 px-3 py-3"},React.createElement("span",{className:"ui-text-label4 text-neutral-700 dark:text-neutral-600 mr-1"},"API key:"),renderApiKeyDropdown)};export default ApiKeySelector;
|
|
2
2
|
//# sourceMappingURL=ApiKeySelector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/CodeSnippet/ApiKeySelector.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport * as Select from \"@radix-ui/react-select\";\nimport Badge from \"../Badge\";\nimport Icon from \"../Icon\";\nimport Tooltip from \"../Tooltip\";\nimport type { ApiKeysItem } from \"../CodeSnippet\";\n\ntype ApiKeySelectorProps = {\n apiKeys?: ApiKeysItem[];\n selectedApiKey: string;\n onApiKeyChange: (apiKey: string) => void;\n};\n\nconst ApiKeySelector = ({\n apiKeys,\n selectedApiKey,\n onApiKeyChange,\n}: ApiKeySelectorProps) => {\n const isDemoMode = useMemo(\n () => apiKeys?.length === 1 && apiKeys[0].app === \"demo\",\n [apiKeys],\n );\n\n
|
|
1
|
+
{"version":3,"sources":["../../../src/core/CodeSnippet/ApiKeySelector.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport * as Select from \"@radix-ui/react-select\";\nimport Badge from \"../Badge\";\nimport Icon from \"../Icon\";\nimport Tooltip from \"../Tooltip\";\nimport type { ApiKeysItem } from \"../CodeSnippet\";\n\ntype ApiKeySelectorProps = {\n apiKeys?: ApiKeysItem[];\n selectedApiKey: string;\n onApiKeyChange: (apiKey: string) => void;\n};\n\nconst ApiKeySelector = ({\n apiKeys,\n selectedApiKey,\n onApiKeyChange,\n}: ApiKeySelectorProps) => {\n const isDemoMode = useMemo(\n () => apiKeys?.length === 1 && apiKeys[0].app === \"demo\",\n [apiKeys],\n );\n\n const renderDemoMode = useMemo(\n () => (\n <div className=\"flex items-center gap-2\">\n <Badge className=\"ml-1 bg-neutral-200 dark:bg-neutral-1100\">\n DEMO ONLY\n </Badge>\n <Tooltip\n className=\"ml-0\"\n triggerProps={{\n className: \"h-5\",\n }}\n contentProps={{\n className:\n \"bg-neutral-1100 dark:bg-neutral-200 text-neutral-300 dark:text-neutral-1000\",\n }}\n triggerElement={\n <div className=\"group/code-snippet-tooltip-icon-hover flex items-center justify-center\">\n <Icon\n name=\"icon-gui-information-circle-outline\"\n size=\"20px\"\n color=\"text-neutral-700 dark:text-neutral-600\"\n additionalCSS=\"group-hover/code-snippet-tooltip-icon-hover:hidden\"\n />\n <Icon\n name=\"icon-gui-information-circle-solid\"\n size=\"20px\"\n color=\"text-neutral-1300 dark:text-neutral-000\"\n additionalCSS=\"group-hover/code-snippet-tooltip-icon-hover:flex hidden\"\n />\n </div>\n }\n >\n This code example uses a temporary key that is rate limited and\n expires in 4 hrs. Sign in to Ably to use your API keys instead.\n </Tooltip>\n </div>\n ),\n [],\n );\n\n const renderApiKeyDropdown = useMemo(() => {\n if (isDemoMode) {\n return renderDemoMode;\n }\n\n if (!apiKeys?.length) {\n return null;\n }\n\n return (\n <Select.Root value={selectedApiKey} onValueChange={onApiKeyChange}>\n <Select.Trigger\n className=\"font-sans inline-flex items-center justify-between rounded px-3 py-2 ml-1 text-14 text-neutral-1300 dark:text-neutral-000 bg-neutral-200 dark:bg-neutral-1100 hover:bg-neutral-300 dark:hover:bg-neutral-1000 gap-2 focus-base border border-neutral-300 dark:border-neutral-1000 transition-colors\"\n aria-label=\"API Key\"\n >\n <Select.Value />\n <Select.Icon className=\"size-4\">\n <Icon name=\"icon-gui-chevron-down-micro\" size=\"16px\" />\n </Select.Icon>\n </Select.Trigger>\n\n <Select.Portal>\n <Select.Content className=\"overflow-hidden rounded-lg bg-neutral-000 dark:bg-neutral-1300 border border-neutral-300 dark:border-neutral-1000 shadow-md z-50\">\n <Select.ScrollUpButton className=\"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base\">\n <Icon\n name=\"icon-gui-chevron-down-outline\"\n size=\"16px\"\n additionalCSS=\"rotate-180\"\n />\n </Select.ScrollUpButton>\n\n <Select.Viewport className=\"rounded-lg font-sans\">\n {apiKeys.map((apiKeyItem) => (\n <Select.Group key={apiKeyItem.app}>\n {apiKeys.length > 1 && (\n <Select.Label className=\"text-neutral-700 rounded-none dark:text-neutral-600 p-1 bg-neutral-200 dark:bg-neutral-1100\">\n {apiKeyItem.app}\n </Select.Label>\n )}\n {apiKeyItem.keys.map(({ name, key }) => (\n <Select.Item\n key={`${apiKeyItem.app}-${name}-${key}`}\n value={key}\n className=\"relative flex items-center justify-between m-2 p-2 rounded-lg text-14 text-neutral-1300 dark:text-neutral-000 select-none hover:bg-neutral-100 dark:hover:bg-neutral-1200 data-[highlighted]:outline-none data-[highlighted]:bg-neutral-100 dark:data-[highlighted]:bg-neutral-1200 focus-base min-w-64\"\n >\n <Select.ItemText>\n {key.length > 10 ? `${key.substring(0, 10)}...` : key}\n <span className=\"font-light\">\n {name && ` - ${name}`}\n </span>\n </Select.ItemText>\n <Select.ItemIndicator className=\"size-4\">\n <Icon name=\"icon-gui-check-micro\" size=\"16px\" />\n </Select.ItemIndicator>\n </Select.Item>\n ))}\n </Select.Group>\n ))}\n </Select.Viewport>\n\n <Select.ScrollDownButton className=\"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base\">\n <Icon name=\"icon-gui-chevron-down-outline\" size=\"16px\" />\n </Select.ScrollDownButton>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n );\n }, [apiKeys, isDemoMode, selectedApiKey, onApiKeyChange, renderDemoMode]);\n\n return (\n <div className=\"flex items-center border-t border-neutral-300 dark:border-neutral-1000 px-3 py-3\">\n <span className=\"ui-text-label4 text-neutral-700 dark:text-neutral-600 mr-1\">\n API key:\n </span>\n {renderApiKeyDropdown}\n </div>\n );\n};\n\nexport default ApiKeySelector;\n"],"names":["React","useMemo","Select","Badge","Icon","Tooltip","ApiKeySelector","apiKeys","selectedApiKey","onApiKeyChange","isDemoMode","length","app","renderDemoMode","div","className","triggerProps","contentProps","triggerElement","name","size","color","additionalCSS","renderApiKeyDropdown","Root","value","onValueChange","Trigger","aria-label","Value","Portal","Content","ScrollUpButton","Viewport","map","apiKeyItem","Group","key","Label","keys","Item","ItemText","substring","span","ItemIndicator","ScrollDownButton"],"mappings":"AAAA,OAAOA,OAASC,OAAO,KAAQ,OAAQ,AACvC,WAAYC,WAAY,wBAAyB,AACjD,QAAOC,UAAW,UAAW,AAC7B,QAAOC,SAAU,SAAU,AAC3B,QAAOC,YAAa,YAAa,CASjC,MAAMC,eAAiB,CAAC,CACtBC,OAAO,CACPC,cAAc,CACdC,cAAc,CACM,IACpB,MAAMC,WAAaT,QACjB,IAAMM,SAASI,SAAW,GAAKJ,OAAO,CAAC,EAAE,CAACK,GAAG,GAAK,OAClD,CAACL,QAAQ,EAGX,MAAMM,eAAiBZ,QACrB,IACE,oBAACa,OAAIC,UAAU,2BACb,oBAACZ,OAAMY,UAAU,4CAA2C,aAG5D,oBAACV,SACCU,UAAU,OACVC,aAAc,CACZD,UAAW,KACb,EACAE,aAAc,CACZF,UACE,6EACJ,EACAG,eACE,oBAACJ,OAAIC,UAAU,0EACb,oBAACX,MACCe,KAAK,sCACLC,KAAK,OACLC,MAAM,yCACNC,cAAc,uDAEhB,oBAAClB,MACCe,KAAK,oCACLC,KAAK,OACLC,MAAM,0CACNC,cAAc,8DAIrB,oIAML,EAAE,EAGJ,MAAMC,qBAAuBtB,QAAQ,KACnC,GAAIS,WAAY,CACd,OAAOG,cACT,CAEA,GAAI,CAACN,SAASI,OAAQ,CACpB,OAAO,IACT,CAEA,OACE,oBAACT,OAAOsB,IAAI,EAACC,MAAOjB,eAAgBkB,cAAejB,gBACjD,oBAACP,OAAOyB,OAAO,EACbZ,UAAU,sSACVa,aAAW,WAEX,oBAAC1B,OAAO2B,KAAK,OACb,oBAAC3B,OAAOE,IAAI,EAACW,UAAU,UACrB,oBAACX,MAAKe,KAAK,8BAA8BC,KAAK,WAIlD,oBAAClB,OAAO4B,MAAM,MACZ,oBAAC5B,OAAO6B,OAAO,EAAChB,UAAU,oIACxB,oBAACb,OAAO8B,cAAc,EAACjB,UAAU,8IAC/B,oBAACX,MACCe,KAAK,gCACLC,KAAK,OACLE,cAAc,gBAIlB,oBAACpB,OAAO+B,QAAQ,EAAClB,UAAU,wBACxBR,QAAQ2B,GAAG,CAAC,AAACC,YACZ,oBAACjC,OAAOkC,KAAK,EAACC,IAAKF,WAAWvB,GAAG,EAC9BL,QAAQI,MAAM,CAAG,GAChB,oBAACT,OAAOoC,KAAK,EAACvB,UAAU,+FACrBoB,WAAWvB,GAAG,EAGlBuB,WAAWI,IAAI,CAACL,GAAG,CAAC,CAAC,CAAEf,IAAI,CAAEkB,GAAG,CAAE,GACjC,oBAACnC,OAAOsC,IAAI,EACVH,IAAK,CAAC,EAAEF,WAAWvB,GAAG,CAAC,CAAC,EAAEO,KAAK,CAAC,EAAEkB,IAAI,CAAC,CACvCZ,MAAOY,IACPtB,UAAU,2SAEV,oBAACb,OAAOuC,QAAQ,MACbJ,IAAI1B,MAAM,CAAG,GAAK,CAAC,EAAE0B,IAAIK,SAAS,CAAC,EAAG,IAAI,GAAG,CAAC,CAAGL,IAClD,oBAACM,QAAK5B,UAAU,cACbI,MAAQ,CAAC,GAAG,EAAEA,KAAK,CAAC,GAGzB,oBAACjB,OAAO0C,aAAa,EAAC7B,UAAU,UAC9B,oBAACX,MAAKe,KAAK,uBAAuBC,KAAK,eAQnD,oBAAClB,OAAO2C,gBAAgB,EAAC9B,UAAU,8IACjC,oBAACX,MAAKe,KAAK,gCAAgCC,KAAK,YAM5D,EAAG,CAACb,QAASG,WAAYF,eAAgBC,eAAgBI,eAAe,EAExE,OACE,oBAACC,OAAIC,UAAU,oFACb,oBAAC4B,QAAK5B,UAAU,8DAA6D,YAG5EQ,qBAGP,CAEA,gBAAejB,cAAe"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{
|
|
1
|
+
import React,{useState}from"react";import Icon from"../Icon";import TooltipButton from"./TooltipButton";const CopyButton=({onCopy,tooltip="Copy"})=>{const[isCopied,setIsCopied]=useState(false);const[isHovering,setIsHovering]=useState(false);return React.createElement("div",{className:"absolute top-2 right-2 z-10 rounded-lg focus-base",role:"button",tabIndex:0,onMouseEnter:()=>setIsHovering(true),onMouseLeave:()=>{setIsHovering(false);setTimeout(()=>{setIsCopied(false)},250)}},React.createElement(TooltipButton,{tooltip:isCopied?"Copied!":tooltip,onClick:()=>{onCopy();setIsCopied(true)},tooltipRootProps:{open:isHovering},variant:"icon-button"},React.createElement(Icon,{name:"icon-gui-document-duplicate-outline",size:"20px",color:"text-neutral-1300 dark:text-neutral-000"})))};export default CopyButton;
|
|
2
2
|
//# sourceMappingURL=CopyButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/CodeSnippet/CopyButton.tsx"],"sourcesContent":["import React, {
|
|
1
|
+
{"version":3,"sources":["../../../src/core/CodeSnippet/CopyButton.tsx"],"sourcesContent":["import React, { useState } from \"react\";\nimport Icon from \"../Icon\";\nimport TooltipButton from \"./TooltipButton\";\n\ntype CopyButtonProps = {\n onCopy: () => void;\n tooltip?: string;\n};\n\nconst CopyButton = ({ onCopy, tooltip = \"Copy\" }: CopyButtonProps) => {\n const [isCopied, setIsCopied] = useState(false);\n const [isHovering, setIsHovering] = useState(false);\n\n return (\n <div\n className=\"absolute top-2 right-2 z-10 rounded-lg focus-base\"\n role=\"button\"\n tabIndex={0}\n onMouseEnter={() => setIsHovering(true)}\n onMouseLeave={() => {\n setIsHovering(false);\n\n setTimeout(() => {\n setIsCopied(false);\n }, 250);\n }}\n >\n <TooltipButton\n tooltip={isCopied ? \"Copied!\" : tooltip}\n onClick={() => {\n onCopy();\n setIsCopied(true);\n }}\n tooltipRootProps={{\n open: isHovering,\n }}\n variant=\"icon-button\"\n >\n <Icon\n name=\"icon-gui-document-duplicate-outline\"\n size=\"20px\"\n color=\"text-neutral-1300 dark:text-neutral-000\"\n />\n </TooltipButton>\n </div>\n );\n};\n\nexport default CopyButton;\n"],"names":["React","useState","Icon","TooltipButton","CopyButton","onCopy","tooltip","isCopied","setIsCopied","isHovering","setIsHovering","div","className","role","tabIndex","onMouseEnter","onMouseLeave","setTimeout","onClick","tooltipRootProps","open","variant","name","size","color"],"mappings":"AAAA,OAAOA,OAASC,QAAQ,KAAQ,OAAQ,AACxC,QAAOC,SAAU,SAAU,AAC3B,QAAOC,kBAAmB,iBAAkB,CAO5C,MAAMC,WAAa,CAAC,CAAEC,MAAM,CAAEC,QAAU,MAAM,CAAmB,IAC/D,KAAM,CAACC,SAAUC,YAAY,CAAGP,SAAS,OACzC,KAAM,CAACQ,WAAYC,cAAc,CAAGT,SAAS,OAE7C,OACE,oBAACU,OACCC,UAAU,oDACVC,KAAK,SACLC,SAAU,EACVC,aAAc,IAAML,cAAc,MAClCM,aAAc,KACZN,cAAc,OAEdO,WAAW,KACTT,YAAY,MACd,EAAG,IACL,GAEA,oBAACL,eACCG,QAASC,SAAW,UAAYD,QAChCY,QAAS,KACPb,SACAG,YAAY,KACd,EACAW,iBAAkB,CAChBC,KAAMX,UACR,EACAY,QAAQ,eAER,oBAACnB,MACCoB,KAAK,sCACLC,KAAK,OACLC,MAAM,6CAKhB,CAEA,gBAAepB,UAAW"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{
|
|
1
|
+
import React,{useMemo}from"react";import*as Select from"@radix-ui/react-select";import Icon from"../Icon";import TooltipButton from"./TooltipButton";import{getLanguageInfo}from"./languages";const LanguageSelector=({languages,activeLanguage,onLanguageChange})=>{const desktopLanguageElements=useMemo(()=>languages.map(lang=>{const active=activeLanguage===lang;const displayName=getLanguageInfo(lang).label;return React.createElement(TooltipButton,{key:lang,tooltip:displayName,active:active,onClick:()=>onLanguageChange(lang),icon:getLanguageInfo(lang).icon,variant:"segmented",size:"xs"},displayName)}),[languages,activeLanguage,onLanguageChange]);const mobileLanguageElements=useMemo(()=>languages.map(lang=>React.createElement(Select.Item,{key:lang,value:lang,className:"relative flex items-center rounded px-2 py-1.5 text-14 text-neutral-1300 dark:text-neutral-000 select-none hover:bg-neutral-100 dark:hover:bg-neutral-1200 data-[highlighted]:outline-none data-[highlighted]:bg-neutral-100 dark:data-[highlighted]:bg-neutral-1200 focus-base"},React.createElement(Select.ItemText,{asChild:true},React.createElement("div",{className:"flex items-center gap-2"},React.createElement(Icon,{name:getLanguageInfo(lang).icon,size:"20px"}),React.createElement("span",null,getLanguageInfo(lang).label))),React.createElement(Select.ItemIndicator,{className:"absolute right-2"},React.createElement(Icon,{name:"icon-gui-check-outline",size:"16px"})))),[languages]);const mobileSelectValue=useMemo(()=>activeLanguage?React.createElement("div",{className:"flex items-center gap-2"},React.createElement(Icon,{name:getLanguageInfo(activeLanguage).icon,size:"20px"}),React.createElement("span",null,getLanguageInfo(activeLanguage).label)):null,[activeLanguage]);return React.createElement("div",{className:"p-2 border-b border-neutral-300 dark:border-neutral-1000 overflow-x-auto"},React.createElement("div",{className:"hidden sm:flex gap-2"},desktopLanguageElements),React.createElement("div",{className:"sm:hidden w-full"},React.createElement(Select.Root,{value:activeLanguage||undefined,onValueChange:onLanguageChange},React.createElement(Select.Trigger,{className:"w-full inline-flex items-center justify-between rounded-lg px-3 py-2 text-14 text-neutral-1300 dark:text-neutral-000 bg-neutral-200 dark:bg-neutral-1100 hover:bg-neutral-300 dark:hover:bg-neutral-1000 gap-1 border border-neutral-300 dark:border-neutral-900 focus-base","aria-label":"Select language"},React.createElement(Select.Value,{asChild:true},mobileSelectValue),React.createElement(Select.Icon,null,React.createElement(Icon,{name:"icon-gui-chevron-down-outline",size:"16px"}))),React.createElement(Select.Portal,null,React.createElement(Select.Content,{className:"overflow-hidden rounded-md bg-neutral-000 dark:bg-neutral-1300 border border-neutral-300 dark:border-neutral-1000 shadow-md z-50 w-[var(--radix-select-trigger-width)]",position:"popper"},React.createElement(Select.ScrollUpButton,{className:"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base"},React.createElement(Icon,{name:"icon-gui-chevron-down-outline",size:"16px",additionalCSS:"rotate-180"})),React.createElement(Select.Viewport,{className:"p-1"},mobileLanguageElements),React.createElement(Select.ScrollDownButton,{className:"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base"},React.createElement(Icon,{name:"icon-gui-chevron-down-outline",size:"16px"})))))))};export default LanguageSelector;
|
|
2
2
|
//# sourceMappingURL=LanguageSelector.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/CodeSnippet/LanguageSelector.tsx"],"sourcesContent":["import React, {
|
|
1
|
+
{"version":3,"sources":["../../../src/core/CodeSnippet/LanguageSelector.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport * as Select from \"@radix-ui/react-select\";\nimport Icon from \"../Icon\";\nimport TooltipButton from \"./TooltipButton\";\nimport { getLanguageInfo } from \"./languages\";\n\ntype LanguageSelectorProps = {\n languages: string[];\n activeLanguage: string;\n onLanguageChange: (language: string) => void;\n};\n\nconst LanguageSelector = ({\n languages,\n activeLanguage,\n onLanguageChange,\n}: LanguageSelectorProps) => {\n const desktopLanguageElements = useMemo(\n () =>\n languages.map((lang) => {\n const active = activeLanguage === lang;\n const displayName = getLanguageInfo(lang).label;\n\n return (\n <TooltipButton\n key={lang}\n tooltip={displayName}\n active={active}\n onClick={() => onLanguageChange(lang)}\n icon={getLanguageInfo(lang).icon}\n variant=\"segmented\"\n size=\"xs\"\n >\n {displayName}\n </TooltipButton>\n );\n }),\n [languages, activeLanguage, onLanguageChange],\n );\n\n const mobileLanguageElements = useMemo(\n () =>\n languages.map((lang) => (\n <Select.Item\n key={lang}\n value={lang}\n className=\"relative flex items-center rounded px-2 py-1.5 text-14 text-neutral-1300 dark:text-neutral-000 select-none hover:bg-neutral-100 dark:hover:bg-neutral-1200 data-[highlighted]:outline-none data-[highlighted]:bg-neutral-100 dark:data-[highlighted]:bg-neutral-1200 focus-base\"\n >\n <Select.ItemText asChild>\n <div className=\"flex items-center gap-2\">\n <Icon name={getLanguageInfo(lang).icon} size=\"20px\" />\n <span>{getLanguageInfo(lang).label}</span>\n </div>\n </Select.ItemText>\n <Select.ItemIndicator className=\"absolute right-2\">\n <Icon name=\"icon-gui-check-outline\" size=\"16px\" />\n </Select.ItemIndicator>\n </Select.Item>\n )),\n [languages],\n );\n\n const mobileSelectValue = useMemo(\n () =>\n activeLanguage ? (\n <div className=\"flex items-center gap-2\">\n <Icon name={getLanguageInfo(activeLanguage).icon} size=\"20px\" />\n <span>{getLanguageInfo(activeLanguage).label}</span>\n </div>\n ) : null,\n [activeLanguage],\n );\n\n return (\n <div className=\"p-2 border-b border-neutral-300 dark:border-neutral-1000 overflow-x-auto\">\n <div className=\"hidden sm:flex gap-2\">{desktopLanguageElements}</div>\n\n <div className=\"sm:hidden w-full\">\n <Select.Root\n value={activeLanguage || undefined}\n onValueChange={onLanguageChange}\n >\n <Select.Trigger\n className=\"w-full inline-flex items-center justify-between rounded-lg px-3 py-2 text-14 text-neutral-1300 dark:text-neutral-000 bg-neutral-200 dark:bg-neutral-1100 hover:bg-neutral-300 dark:hover:bg-neutral-1000 gap-1 border border-neutral-300 dark:border-neutral-900 focus-base\"\n aria-label=\"Select language\"\n >\n <Select.Value asChild>{mobileSelectValue}</Select.Value>\n <Select.Icon>\n <Icon name=\"icon-gui-chevron-down-outline\" size=\"16px\" />\n </Select.Icon>\n </Select.Trigger>\n\n <Select.Portal>\n <Select.Content\n className=\"overflow-hidden rounded-md bg-neutral-000 dark:bg-neutral-1300 border border-neutral-300 dark:border-neutral-1000 shadow-md z-50 w-[var(--radix-select-trigger-width)]\"\n position=\"popper\"\n >\n <Select.ScrollUpButton className=\"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base\">\n <Icon\n name=\"icon-gui-chevron-down-outline\"\n size=\"16px\"\n additionalCSS=\"rotate-180\"\n />\n </Select.ScrollUpButton>\n\n <Select.Viewport className=\"p-1\">\n {mobileLanguageElements}\n </Select.Viewport>\n\n <Select.ScrollDownButton className=\"flex items-center justify-center h-6 bg-neutral-000 dark:bg-neutral-1300 text-neutral-1300 dark:text-neutral-000 cursor-default focus-base\">\n <Icon name=\"icon-gui-chevron-down-outline\" size=\"16px\" />\n </Select.ScrollDownButton>\n </Select.Content>\n </Select.Portal>\n </Select.Root>\n </div>\n </div>\n );\n};\n\nexport default LanguageSelector;\n"],"names":["React","useMemo","Select","Icon","TooltipButton","getLanguageInfo","LanguageSelector","languages","activeLanguage","onLanguageChange","desktopLanguageElements","map","lang","active","displayName","label","key","tooltip","onClick","icon","variant","size","mobileLanguageElements","Item","value","className","ItemText","asChild","div","name","span","ItemIndicator","mobileSelectValue","Root","undefined","onValueChange","Trigger","aria-label","Value","Portal","Content","position","ScrollUpButton","additionalCSS","Viewport","ScrollDownButton"],"mappings":"AAAA,OAAOA,OAASC,OAAO,KAAQ,OAAQ,AACvC,WAAYC,WAAY,wBAAyB,AACjD,QAAOC,SAAU,SAAU,AAC3B,QAAOC,kBAAmB,iBAAkB,AAC5C,QAASC,eAAe,KAAQ,aAAc,CAQ9C,MAAMC,iBAAmB,CAAC,CACxBC,SAAS,CACTC,cAAc,CACdC,gBAAgB,CACM,IACtB,MAAMC,wBAA0BT,QAC9B,IACEM,UAAUI,GAAG,CAAC,AAACC,OACb,MAAMC,OAASL,iBAAmBI,KAClC,MAAME,YAAcT,gBAAgBO,MAAMG,KAAK,CAE/C,OACE,oBAACX,eACCY,IAAKJ,KACLK,QAASH,YACTD,OAAQA,OACRK,QAAS,IAAMT,iBAAiBG,MAChCO,KAAMd,gBAAgBO,MAAMO,IAAI,CAChCC,QAAQ,YACRC,KAAK,MAEJP,YAGP,GACF,CAACP,UAAWC,eAAgBC,iBAAiB,EAG/C,MAAMa,uBAAyBrB,QAC7B,IACEM,UAAUI,GAAG,CAAC,AAACC,MACb,oBAACV,OAAOqB,IAAI,EACVP,IAAKJ,KACLY,MAAOZ,KACPa,UAAU,mRAEV,oBAACvB,OAAOwB,QAAQ,EAACC,QAAAA,MACf,oBAACC,OAAIH,UAAU,2BACb,oBAACtB,MAAK0B,KAAMxB,gBAAgBO,MAAMO,IAAI,CAAEE,KAAK,SAC7C,oBAACS,YAAMzB,gBAAgBO,MAAMG,KAAK,IAGtC,oBAACb,OAAO6B,aAAa,EAACN,UAAU,oBAC9B,oBAACtB,MAAK0B,KAAK,yBAAyBR,KAAK,YAIjD,CAACd,UAAU,EAGb,MAAMyB,kBAAoB/B,QACxB,IACEO,eACE,oBAACoB,OAAIH,UAAU,2BACb,oBAACtB,MAAK0B,KAAMxB,gBAAgBG,gBAAgBW,IAAI,CAAEE,KAAK,SACvD,oBAACS,YAAMzB,gBAAgBG,gBAAgBO,KAAK,GAE5C,KACN,CAACP,eAAe,EAGlB,OACE,oBAACoB,OAAIH,UAAU,4EACb,oBAACG,OAAIH,UAAU,wBAAwBf,yBAEvC,oBAACkB,OAAIH,UAAU,oBACb,oBAACvB,OAAO+B,IAAI,EACVT,MAAOhB,gBAAkB0B,UACzBC,cAAe1B,kBAEf,oBAACP,OAAOkC,OAAO,EACbX,UAAU,8QACVY,aAAW,mBAEX,oBAACnC,OAAOoC,KAAK,EAACX,QAAAA,MAASK,mBACvB,oBAAC9B,OAAOC,IAAI,MACV,oBAACA,MAAK0B,KAAK,gCAAgCR,KAAK,WAIpD,oBAACnB,OAAOqC,MAAM,MACZ,oBAACrC,OAAOsC,OAAO,EACbf,UAAU,yKACVgB,SAAS,UAET,oBAACvC,OAAOwC,cAAc,EAACjB,UAAU,8IAC/B,oBAACtB,MACC0B,KAAK,gCACLR,KAAK,OACLsB,cAAc,gBAIlB,oBAACzC,OAAO0C,QAAQ,EAACnB,UAAU,OACxBH,wBAGH,oBAACpB,OAAO2C,gBAAgB,EAACpB,UAAU,8IACjC,oBAACtB,MAAK0B,KAAK,gCAAgCR,KAAK,cAQhE,CAEA,gBAAef,gBAAiB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{useRef,useState
|
|
1
|
+
import React,{useRef,useState}from"react";import Icon from"../Icon";import Code from"../Code";import cn from"../utils/cn";import CopyButton from"./CopyButton";const PlainCodeView=({content,className,language,icon})=>{const codeRef=useRef(null);const[isHovering,setIsHovering]=useState(false);return React.createElement("div",{className:cn("rounded-lg overflow-hidden bg-neutral-000 dark:bg-neutral-1300 border border-neutral-300 dark:border-neutral-1000 relative flex items-center",language==="shell"?"min-h-[3.375rem]":"min-h-12",className),onMouseEnter:()=>setIsHovering(true),onMouseLeave:()=>setIsHovering(false),onFocus:()=>setIsHovering(true),onBlur:()=>setIsHovering(false),tabIndex:0,role:"button","aria-label":"Focusable code view area",ref:codeRef},icon&&React.createElement("div",{className:"absolute top-2 left-2 z-10"},React.createElement("div",{className:"w-9 h-9 rounded-lg flex items-center justify-center bg-neutral-200 dark:bg-neutral-1100"},React.createElement(Icon,{name:icon,size:"20px",color:"text-neutral-1300 dark:text-neutral-000"}))),React.createElement(Code,{language:language,snippet:content,additionalCSS:cn("w-full bg-neutral-000 text-neutral-1300 dark:bg-neutral-1300 dark:text-neutral-200 px-4 py-2",icon&&"pl-14"),showLines:false}),isHovering&&React.createElement(CopyButton,{onCopy:()=>navigator.clipboard.writeText(content)}))};export default PlainCodeView;
|
|
2
2
|
//# sourceMappingURL=PlainCodeView.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/CodeSnippet/PlainCodeView.tsx"],"sourcesContent":["import React, { useRef, useState
|
|
1
|
+
{"version":3,"sources":["../../../src/core/CodeSnippet/PlainCodeView.tsx"],"sourcesContent":["import React, { useRef, useState } from \"react\";\nimport Icon from \"../Icon\";\nimport Code from \"../Code\";\nimport cn from \"../utils/cn\";\nimport CopyButton from \"./CopyButton\";\nimport { IconName } from \"../Icon/types\";\n\ntype PlainCodeViewProps = {\n content: string;\n language: string;\n icon: IconName | null;\n className?: string;\n};\n\nconst PlainCodeView: React.FC<PlainCodeViewProps> = ({\n content,\n className,\n language,\n icon,\n}) => {\n const codeRef = useRef<HTMLDivElement>(null);\n const [isHovering, setIsHovering] = useState(false);\n\n return (\n <div\n className={cn(\n \"rounded-lg overflow-hidden bg-neutral-000 dark:bg-neutral-1300 border border-neutral-300 dark:border-neutral-1000 relative flex items-center\",\n language === \"shell\" ? \"min-h-[3.375rem]\" : \"min-h-12\",\n className,\n )}\n onMouseEnter={() => setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n onFocus={() => setIsHovering(true)}\n onBlur={() => setIsHovering(false)}\n tabIndex={0}\n role=\"button\"\n aria-label=\"Focusable code view area\"\n ref={codeRef}\n >\n {icon && (\n <div className=\"absolute top-2 left-2 z-10\">\n <div className=\"w-9 h-9 rounded-lg flex items-center justify-center bg-neutral-200 dark:bg-neutral-1100\">\n <Icon\n name={icon}\n size=\"20px\"\n color=\"text-neutral-1300 dark:text-neutral-000\"\n />\n </div>\n </div>\n )}\n\n <Code\n language={language}\n snippet={content}\n additionalCSS={cn(\n \"w-full bg-neutral-000 text-neutral-1300 dark:bg-neutral-1300 dark:text-neutral-200 px-4 py-2\",\n icon && \"pl-14\",\n )}\n showLines={false}\n />\n\n {isHovering && (\n <CopyButton onCopy={() => navigator.clipboard.writeText(content)} />\n )}\n </div>\n );\n};\n\nexport default PlainCodeView;\n"],"names":["React","useRef","useState","Icon","Code","cn","CopyButton","PlainCodeView","content","className","language","icon","codeRef","isHovering","setIsHovering","div","onMouseEnter","onMouseLeave","onFocus","onBlur","tabIndex","role","aria-label","ref","name","size","color","snippet","additionalCSS","showLines","onCopy","navigator","clipboard","writeText"],"mappings":"AAAA,OAAOA,OAASC,MAAM,CAAEC,QAAQ,KAAQ,OAAQ,AAChD,QAAOC,SAAU,SAAU,AAC3B,QAAOC,SAAU,SAAU,AAC3B,QAAOC,OAAQ,aAAc,AAC7B,QAAOC,eAAgB,cAAe,CAUtC,MAAMC,cAA8C,CAAC,CACnDC,OAAO,CACPC,SAAS,CACTC,QAAQ,CACRC,IAAI,CACL,IACC,MAAMC,QAAUX,OAAuB,MACvC,KAAM,CAACY,WAAYC,cAAc,CAAGZ,SAAS,OAE7C,OACE,oBAACa,OACCN,UAAWJ,GACT,+IACAK,WAAa,QAAU,mBAAqB,WAC5CD,WAEFO,aAAc,IAAMF,cAAc,MAClCG,aAAc,IAAMH,cAAc,OAClCI,QAAS,IAAMJ,cAAc,MAC7BK,OAAQ,IAAML,cAAc,OAC5BM,SAAU,EACVC,KAAK,SACLC,aAAW,2BACXC,IAAKX,SAEJD,MACC,oBAACI,OAAIN,UAAU,8BACb,oBAACM,OAAIN,UAAU,2FACb,oBAACN,MACCqB,KAAMb,KACNc,KAAK,OACLC,MAAM,8CAMd,oBAACtB,MACCM,SAAUA,SACViB,QAASnB,QACToB,cAAevB,GACb,+FACAM,MAAQ,SAEVkB,UAAW,QAGZhB,YACC,oBAACP,YAAWwB,OAAQ,IAAMC,UAAUC,SAAS,CAACC,SAAS,CAACzB,WAIhE,CAEA,gBAAeD,aAAc"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{
|
|
1
|
+
import React,{useMemo}from"react";import Tooltip from"../Tooltip";import SegmentedControl from"../SegmentedControl";import cn from"../utils/cn";const TooltipButton=({tooltip,active=false,onClick,icon,className,children,variant="segmented",size="sm",alwaysShowLabel=false,tooltipRootProps})=>{const showTooltip=variant==="segmented"&&!active||variant==="icon-button";const showChildren=active||alwaysShowLabel;const buttonElement=useMemo(()=>{if(variant==="segmented"){return React.createElement(SegmentedControl,{size:size,active:active,onClick:onClick,leftIcon:icon,className:cn("focus-base transition-colors",active?"bg-neutral-000 dark:bg-neutral-1100":"bg-neutral-100 dark:bg-neutral-1200 hover:bg-neutral-200 dark:hover:bg-neutral-1100 active:bg-neutral-400 dark:active:bg-neutral-900",className)},showChildren?children:null)}return React.createElement("div",{role:"button",className:cn("w-8 h-8 rounded-lg flex items-center justify-center bg-neutral-200 dark:bg-neutral-1100 hover:bg-neutral-300 dark:hover:bg-neutral-1000 transition-colors focus-base",className),onClick:onClick,onKeyDown:e=>{if(e.key==="Enter"||e.key===" "){e.preventDefault();onClick?.()}},tabIndex:0},children)},[variant,size,active,onClick,icon,className,showChildren,children]);if(showTooltip){return React.createElement(Tooltip,{triggerElement:buttonElement,rootProps:tooltipRootProps,className:"ml-0",contentProps:{className:"px-2 py-1 bg-neutral-1100 dark:bg-neutral-200 text-neutral-300 dark:text-neutral-1000"},triggerProps:{className:"ml-0 h-auto"}},tooltip)}return buttonElement};export default TooltipButton;
|
|
2
2
|
//# sourceMappingURL=TooltipButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/core/CodeSnippet/TooltipButton.tsx"],"sourcesContent":["import React, {
|
|
1
|
+
{"version":3,"sources":["../../../src/core/CodeSnippet/TooltipButton.tsx"],"sourcesContent":["import React, { useMemo } from \"react\";\nimport Tooltip from \"../Tooltip\";\nimport SegmentedControl, { SegmentedControlSize } from \"../SegmentedControl\";\nimport cn from \"../utils/cn\";\nimport { IconName } from \"../Icon/types\";\nimport type { TooltipProps } from \"@radix-ui/react-tooltip\";\n\ntype TooltipButtonProps = {\n tooltip: string | React.ReactNode;\n active?: boolean;\n onClick: () => void;\n icon?: IconName;\n className?: string;\n children?: React.ReactNode;\n variant?: \"segmented\" | \"icon-button\";\n size?: SegmentedControlSize;\n alwaysShowLabel?: boolean;\n tooltipRootProps?: TooltipProps;\n};\n\nconst TooltipButton = ({\n tooltip,\n active = false,\n onClick,\n icon,\n className,\n children,\n variant = \"segmented\",\n size = \"sm\",\n alwaysShowLabel = false,\n tooltipRootProps,\n}: TooltipButtonProps) => {\n const showTooltip =\n (variant === \"segmented\" && !active) || variant === \"icon-button\";\n\n const showChildren = active || alwaysShowLabel;\n\n // Create the button element based on variant\n const buttonElement = useMemo(() => {\n if (variant === \"segmented\") {\n return (\n <SegmentedControl\n size={size}\n active={active}\n onClick={onClick}\n leftIcon={icon}\n className={cn(\n \"focus-base transition-colors\",\n active\n ? \"bg-neutral-000 dark:bg-neutral-1100\"\n : \"bg-neutral-100 dark:bg-neutral-1200 hover:bg-neutral-200 dark:hover:bg-neutral-1100 active:bg-neutral-400 dark:active:bg-neutral-900\",\n className,\n )}\n >\n {showChildren ? children : null}\n </SegmentedControl>\n );\n }\n\n return (\n <div\n role=\"button\"\n className={cn(\n \"w-8 h-8 rounded-lg flex items-center justify-center bg-neutral-200 dark:bg-neutral-1100 hover:bg-neutral-300 dark:hover:bg-neutral-1000 transition-colors focus-base\",\n className,\n )}\n onClick={onClick}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onClick?.();\n }\n }}\n tabIndex={0}\n >\n {children}\n </div>\n );\n }, [variant, size, active, onClick, icon, className, showChildren, children]);\n\n if (showTooltip) {\n return (\n <Tooltip\n triggerElement={buttonElement}\n rootProps={tooltipRootProps}\n className=\"ml-0\"\n contentProps={{\n className:\n \"px-2 py-1 bg-neutral-1100 dark:bg-neutral-200 text-neutral-300 dark:text-neutral-1000\",\n }}\n triggerProps={{ className: \"ml-0 h-auto\" }}\n >\n {tooltip}\n </Tooltip>\n );\n }\n\n return buttonElement;\n};\n\nexport default TooltipButton;\n"],"names":["React","useMemo","Tooltip","SegmentedControl","cn","TooltipButton","tooltip","active","onClick","icon","className","children","variant","size","alwaysShowLabel","tooltipRootProps","showTooltip","showChildren","buttonElement","leftIcon","div","role","onKeyDown","e","key","preventDefault","tabIndex","triggerElement","rootProps","contentProps","triggerProps"],"mappings":"AAAA,OAAOA,OAASC,OAAO,KAAQ,OAAQ,AACvC,QAAOC,YAAa,YAAa,AACjC,QAAOC,qBAAgD,qBAAsB,AAC7E,QAAOC,OAAQ,aAAc,CAiB7B,MAAMC,cAAgB,CAAC,CACrBC,OAAO,CACPC,OAAS,KAAK,CACdC,OAAO,CACPC,IAAI,CACJC,SAAS,CACTC,QAAQ,CACRC,QAAU,WAAW,CACrBC,KAAO,IAAI,CACXC,gBAAkB,KAAK,CACvBC,gBAAgB,CACG,IACnB,MAAMC,YACJ,AAACJ,UAAY,aAAe,CAACL,QAAWK,UAAY,cAEtD,MAAMK,aAAeV,QAAUO,gBAG/B,MAAMI,cAAgBjB,QAAQ,KAC5B,GAAIW,UAAY,YAAa,CAC3B,OACE,oBAACT,kBACCU,KAAMA,KACNN,OAAQA,OACRC,QAASA,QACTW,SAAUV,KACVC,UAAWN,GACT,+BACAG,OACI,sCACA,uIACJG,YAGDO,aAAeN,SAAW,KAGjC,CAEA,OACE,oBAACS,OACCC,KAAK,SACLX,UAAWN,GACT,uKACAM,WAEFF,QAASA,QACTc,UAAW,AAACC,IACV,GAAIA,EAAEC,GAAG,GAAK,SAAWD,EAAEC,GAAG,GAAK,IAAK,CACtCD,EAAEE,cAAc,GAChBjB,WACF,CACF,EACAkB,SAAU,GAETf,SAGP,EAAG,CAACC,QAASC,KAAMN,OAAQC,QAASC,KAAMC,UAAWO,aAAcN,SAAS,EAE5E,GAAIK,YAAa,CACf,OACE,oBAACd,SACCyB,eAAgBT,cAChBU,UAAWb,iBACXL,UAAU,OACVmB,aAAc,CACZnB,UACE,uFACJ,EACAoB,aAAc,CAAEpB,UAAW,aAAc,GAExCJ,QAGP,CAEA,OAAOY,aACT,CAEA,gBAAeb,aAAc"}
|
package/core/CodeSnippet.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{useState,useEffect,Children,isValidElement,useRef,useCallback,useMemo}from"react";import Code from"./Code";import cn from"./utils/cn";import Icon from"./Icon";import{getLanguageInfo,stripSdkType}from"./CodeSnippet/languages";import LanguageSelector from"./CodeSnippet/LanguageSelector";import ApiKeySelector from"./CodeSnippet/ApiKeySelector";import useCopyToClipboard from"./utils/useCopyToClipboard";import PlainCodeView from"./CodeSnippet/PlainCodeView";import CopyButton from"./CodeSnippet/CopyButton";import TooltipButton from"./CodeSnippet/TooltipButton";const substituteApiKey=(content,apiKey,mask=true)=>{return content.replace(/\{\{API_KEY\}\}/g,mask?`${apiKey.split(":")[0]}:*****`:apiKey)};const CodeSnippet=({fixed=false,headerRow=false,title="Code",children,className,lang,onChange,apiKeys,sdk,showCodeLines=true,languageOrdering})=>{const codeRef=useRef(null);const{isCopied,copy}=useCopyToClipboard();const[selectedApiKey,setSelectedApiKey]=useState(()=>apiKeys?.[0]?.keys?.[0]?.key??"");useEffect(()=>{if(!selectedApiKey&&apiKeys&&apiKeys.length>0){setSelectedApiKey(apiKeys[0].keys?.[0]?.key)}},[apiKeys,selectedApiKey]);useEffect(()=>{const element=codeRef.current;if(!element)return;const unmaskRenderedApiKey=(content,apiKey)=>{return content.replace(/(['"]?)([^:'"]+):\*{5}\1/g,`$1${apiKey}$1`)};const handleCopy=event=>{const selection=window.getSelection();if(!selection||selection.rangeCount===0)return;const selectedText=selection.toString();if(!selectedText)return;const range=selection.getRangeAt(0);if(!element.contains(range.commonAncestorContainer))return;const modifiedText=unmaskRenderedApiKey(selectedText,selectedApiKey);event.clipboardData?.setData("text/plain",modifiedText);event.preventDefault()};document.addEventListener("copy",handleCopy);return()=>{document.removeEventListener("copy",handleCopy)}},[selectedApiKey]);const extractLanguageFromCode=useCallback(codeElement=>{if(!codeElement||!codeElement.props.className)return null;const classNames=codeElement.props.className.split(" ");const langClass=classNames.find(cls=>cls.startsWith("language-"));if(!langClass)return null;return langClass.substring(9)},[]);const{codeData,languages,sdkTypes,isSinglePlainCommand}=useMemo(()=>{const childrenArray=Children.toArray(children);const languages=[];const sdkTypes=new Set;const codeData=[];const isSinglePlainCommand=childrenArray.length===1&&["language-shell","language-text"].some(lang=>isValidElement(childrenArray[0])&&isValidElement(childrenArray[0].props.children)&&childrenArray[0].props.children.props.className?.includes(lang));childrenArray.forEach(child=>{if(!isValidElement(child))return;const preElement=child;const codeElement=isValidElement(preElement.props.children)?preElement.props.children:null;if(!codeElement)return;const codeLanguage=extractLanguageFromCode(codeElement);if(!codeLanguage)return;if(codeLanguage.startsWith("realtime_")){sdkTypes.add("realtime")}else if(codeLanguage.startsWith("rest_")){sdkTypes.add("rest")}if(!languages.includes(codeLanguage)){languages.push(codeLanguage)}const codeContent=codeElement.props.children;codeData.push({language:codeLanguage,content:codeContent})});return{codeData,languages,sdkTypes,isSinglePlainCommand}},[children,extractLanguageFromCode]);const resolvedSdk=useMemo(()=>{if(sdkTypes.size===1&&sdk&&!sdkTypes.has(sdk)){return Array.from(sdkTypes)[0]}return sdk??null},[sdk,sdkTypes]);const showSDKSelector=sdkTypes.size>0;const filteredLanguages=useMemo(()=>{const filtered=!resolvedSdk||!showSDKSelector?[...languages]:languages.filter(lang=>lang.startsWith(`${resolvedSdk}_`));if(languageOrdering&&languageOrdering.length>0){filtered.sort((a,b)=>{const aBase=stripSdkType(a);const bBase=stripSdkType(b);const aIndex=languageOrdering.indexOf(aBase);const bIndex=languageOrdering.indexOf(bBase);if(aIndex!==-1&&bIndex!==-1)return aIndex-bIndex;if(aIndex!==-1)return-1;if(bIndex!==-1)return 1;return 0})}return filtered},[resolvedSdk,showSDKSelector,languages,languageOrdering]);const activeLanguage=useMemo(()=>{if(resolvedSdk&&sdkTypes.has(resolvedSdk)){return`${resolvedSdk}_${lang}`}if(lang)return lang;if(filteredLanguages.length>0)return filteredLanguages[0];return languages[0]},[resolvedSdk,sdkTypes,lang,filteredLanguages,languages]);const requiresApiKeySubstitution=useMemo(()=>{const containsPlaceholder=codeData.some(code=>code?.content.includes("{{API_KEY}}"));return containsPlaceholder&&!!apiKeys&&apiKeys.length>0&&!!selectedApiKey},[codeData,apiKeys,selectedApiKey]);const[isHovering,setIsHovering]=useState(false);const hasOnlyJsonSnippet=useMemo(()=>languages.length===1&&languages[0]==="json",[languages]);const processedChildren=useMemo(()=>{if(!activeLanguage)return[];const targetLanguage=hasOnlyJsonSnippet?"json":activeLanguage;return codeData.filter(code=>{return code?.language===targetLanguage}).map(code=>{if(!code)return null;const cleanLang=hasOnlyJsonSnippet?"json":code.language;const langInfo=getLanguageInfo(cleanLang??"");if(typeof code.content==="string"||typeof code.content==="number"||typeof code.content==="boolean"){let processedContent=String(code.content);if(requiresApiKeySubstitution){processedContent=substituteApiKey(processedContent,selectedApiKey)}if(!langInfo.syntaxHighlighterKey||!cleanLang)return null;return React.createElement(Code,{key:code.language,language:langInfo.syntaxHighlighterKey||cleanLang,snippet:processedContent,additionalCSS:"bg-neutral-100 text-neutral-1300 dark:bg-neutral-1200 dark:text-neutral-200 px-6 py-4",showLines:showCodeLines})}return null})},[activeLanguage,hasOnlyJsonSnippet,codeData,requiresApiKeySubstitution,showCodeLines,selectedApiKey]);const hasSnippetForActiveLanguage=useMemo(()=>{if(!activeLanguage)return false;if(hasOnlyJsonSnippet)return true;return codeData.some(code=>{return code?.language===activeLanguage})},[activeLanguage,hasOnlyJsonSnippet,codeData]);const handleSDKTypeChange=useCallback(type=>{const nextLang=stripSdkType(languages.find(l=>l===`${type}_${stripSdkType(activeLanguage)}`)??languages.find(l=>l.startsWith(`${type}_`))??activeLanguage);if(onChange&&nextLang){onChange(stripSdkType(activeLanguage),type)}},[activeLanguage,languages,onChange]);const handleLanguageChange=useCallback(language=>{if(onChange){onChange(stripSdkType(language),resolvedSdk)}},[onChange,resolvedSdk]);const NoSnippetMessage=useMemo(()=>{if(!activeLanguage)return()=>null;const activeLanguageInfo=getLanguageInfo(activeLanguage);return()=>React.createElement("div",{className:"px-16 py-6 ui-text-body2 text-neutral-800 dark:text-neutral-400 text-center flex flex-col gap-3 items-center"},React.createElement(Icon,{name:"icon-gui-exclamation-triangle-outline",color:"text-yellow-600 dark:text-yellow-400",size:"24px"}),React.createElement("p",{className:"ui-text-p3 text-neutral-700 dark:text-neutral-600"},"You're currently viewing the ",activeLanguageInfo.label," docs. There either isn't a ",activeLanguageInfo.label," code sample for this example, or this feature isn't supported in"," ",activeLanguageInfo.label,". Switch language to view this example in a different language, or check which SDKs support this feature."))},[activeLanguage]);const showLanguageSelector=!fixed&&filteredLanguages.length>0;const showFullSelector=filteredLanguages.length>1;const renderContent=useMemo(()=>{if(!activeLanguage)return null;if(hasSnippetForActiveLanguage){return processedChildren}return React.createElement(NoSnippetMessage,null)},[activeLanguage,hasSnippetForActiveLanguage,processedChildren,NoSnippetMessage]);if(isSinglePlainCommand){const plainChild=codeData[0];if(plainChild){const codeContent=plainChild.content;const language=plainChild.language;if(!language||!codeContent)return null;let processedContent=String(codeContent);if(requiresApiKeySubstitution){processedContent=substituteApiKey(processedContent,selectedApiKey)}return React.createElement(PlainCodeView,{content:processedContent,className:className,language:language,icon:language==="shell"?"icon-gui-command-line-outline":null})}}return React.createElement("div",{className:cn("rounded-lg overflow-hidden bg-neutral-100 dark:bg-neutral-1200 border border-neutral-300 dark:border-neutral-1000 min-h-[3.375rem]",className)},headerRow&&React.createElement("div",{className:"h-[2.375rem] bg-neutral-200 dark:bg-neutral-1100 border-b border-neutral-300 dark:border-neutral-1000 flex items-center py-1 px-3 rounded-t-lg"},React.createElement("div",{className:"flex space-x-1.5"},React.createElement("div",{className:"w-3 h-3 rounded-full bg-orange-500"}),React.createElement("div",{className:"w-3 h-3 rounded-full bg-yellow-500"}),React.createElement("div",{className:"w-3 h-3 rounded-full bg-green-500"})),React.createElement("div",{className:"flex-1 text-center ui-text-p3 font-bold text-neutral-1300 dark:text-neutral-000"},title),React.createElement("div",{className:"w-12"})),showSDKSelector&&React.createElement("div",{className:cn("p-2 border-b border-neutral-200 dark:border-neutral-1100 h-14",headerRow?"":"rounded-t-lg")},React.createElement("div",{className:"flex gap-3 justify-start"},sdkTypes.has("realtime")&&React.createElement(TooltipButton,{tooltip:"Realtime SDK",active:resolvedSdk==="realtime",onClick:()=>handleSDKTypeChange("realtime"),variant:"segmented",size:"sm",alwaysShowLabel:true},"Realtime"),sdkTypes.has("rest")&&React.createElement(TooltipButton,{tooltip:"REST SDK",active:resolvedSdk==="rest",onClick:()=>handleSDKTypeChange("rest"),variant:"segmented",size:"sm",alwaysShowLabel:true},"REST"))),showLanguageSelector&&(showFullSelector?React.createElement(LanguageSelector,{languages:filteredLanguages,activeLanguage:activeLanguage,onLanguageChange:handleLanguageChange}):React.createElement("div",{className:cn("border-b border-neutral-200 dark:border-neutral-1100 h-[2.125rem] inline-flex items-center px-3 w-full",{"rounded-t-lg":!headerRow})},filteredLanguages.length>0&&React.createElement("div",{className:cn("inline-flex items-center",{"cursor-pointer":filteredLanguages.length>0}),...filteredLanguages.length>0&&{onClick:()=>handleLanguageChange(filteredLanguages[0])}},React.createElement(Icon,{name:getLanguageInfo(filteredLanguages[0]).icon,size:"16px",additionalCSS:"mr-2"}),React.createElement("span",{className:"ui-text-label4 font-semibold text-neutral-800 dark:text-neutral-500 select-none"},getLanguageInfo(filteredLanguages[0]).label)))),React.createElement("div",{ref:codeRef,className:"relative",onMouseEnter:()=>setIsHovering(true),onMouseLeave:()=>setIsHovering(false),onFocus:()=>setIsHovering(true),onBlur:()=>setIsHovering(false),tabIndex:0,role:"button","aria-label":"Focusable code snippet area"},renderContent,isHovering&&activeLanguage&&React.createElement(CopyButton,{onCopy:()=>{const text=codeData.find(code=>code.language===activeLanguage)?.content;if(text)copy(substituteApiKey(text,selectedApiKey,false))},isCopied:isCopied})),requiresApiKeySubstitution&&React.createElement(ApiKeySelector,{apiKeys:apiKeys,selectedApiKey:selectedApiKey,onApiKeyChange:setSelectedApiKey}))};export default CodeSnippet;
|
|
1
|
+
import React,{useState,useEffect,Children,isValidElement,useRef,useCallback,useMemo}from"react";import Code from"./Code";import cn from"./utils/cn";import Icon from"./Icon";import{getLanguageInfo,stripSdkType}from"./CodeSnippet/languages";import LanguageSelector from"./CodeSnippet/LanguageSelector";import ApiKeySelector from"./CodeSnippet/ApiKeySelector";import PlainCodeView from"./CodeSnippet/PlainCodeView";import CopyButton from"./CodeSnippet/CopyButton";import SegmentedControl from"./SegmentedControl";const substituteApiKey=(content,apiKey,mask=true)=>{return content.replace(/\{\{API_KEY\}\}/g,mask?`${apiKey.split(":")[0]}:*****`:apiKey)};const CodeSnippet=({fixed=false,headerRow=false,title="Code",children,className,lang,onChange,apiKeys,sdk,showCodeLines=true,languageOrdering})=>{const codeRef=useRef(null);const[selectedApiKey,setSelectedApiKey]=useState(()=>apiKeys?.[0]?.keys?.[0]?.key??"");useEffect(()=>{if(!selectedApiKey&&apiKeys&&apiKeys.length>0){setSelectedApiKey(apiKeys[0].keys?.[0]?.key)}},[apiKeys]);useEffect(()=>{const element=codeRef.current;if(!element)return;const unmaskRenderedApiKey=(content,apiKey)=>{return content.replace(/(['"]?)([^:'"]+):\*{5}\1/g,`$1${apiKey}$1`)};const handleCopy=event=>{const selection=window.getSelection();if(!selection||selection.rangeCount===0)return;const selectedText=selection.toString();if(!selectedText)return;const range=selection.getRangeAt(0);if(!element.contains(range.commonAncestorContainer))return;const modifiedText=unmaskRenderedApiKey(selectedText,selectedApiKey);event.clipboardData?.setData("text/plain",modifiedText);event.preventDefault()};document.addEventListener("copy",handleCopy);return()=>{document.removeEventListener("copy",handleCopy)}},[selectedApiKey]);const extractLanguageFromCode=useCallback(codeElement=>{if(!codeElement||!codeElement.props.className)return null;const classNames=codeElement.props.className.split(" ");const langClass=classNames.find(cls=>cls.startsWith("language-"));if(!langClass)return null;return langClass.substring(9)},[]);const{codeData,languages,sdkTypes,isSinglePlainCommand}=useMemo(()=>{const childrenArray=Children.toArray(children);const languages=[];const sdkTypes=new Set;const codeData=[];const isSinglePlainCommand=childrenArray.length===1&&["language-shell","language-text"].some(lang=>isValidElement(childrenArray[0])&&isValidElement(childrenArray[0].props.children)&&childrenArray[0].props.children.props.className?.includes(lang));childrenArray.forEach(child=>{if(!isValidElement(child))return;const preElement=child;const codeElement=isValidElement(preElement.props.children)?preElement.props.children:null;if(!codeElement)return;const codeLanguage=extractLanguageFromCode(codeElement);if(!codeLanguage)return;if(codeLanguage.startsWith("realtime_")){sdkTypes.add("realtime")}else if(codeLanguage.startsWith("rest_")){sdkTypes.add("rest")}if(!languages.includes(codeLanguage)){languages.push(codeLanguage)}const codeContent=codeElement.props.children;codeData.push({language:codeLanguage,content:codeContent})});return{codeData,languages,sdkTypes,isSinglePlainCommand}},[children,extractLanguageFromCode]);const resolvedSdk=useMemo(()=>{if(sdkTypes.size===1&&sdk&&!sdkTypes.has(sdk)){return Array.from(sdkTypes)[0]}return sdk??null},[sdk,sdkTypes]);const showSDKSelector=sdkTypes.size>0;const filteredLanguages=useMemo(()=>{const filtered=!resolvedSdk||!showSDKSelector?[...languages]:languages.filter(lang=>lang.startsWith(`${resolvedSdk}_`));if(languageOrdering&&languageOrdering.length>0){filtered.sort((a,b)=>{const aBase=stripSdkType(a);const bBase=stripSdkType(b);const aIndex=languageOrdering.indexOf(aBase);const bIndex=languageOrdering.indexOf(bBase);if(aIndex!==-1&&bIndex!==-1)return aIndex-bIndex;if(aIndex!==-1)return-1;if(bIndex!==-1)return 1;return 0})}return filtered},[resolvedSdk,showSDKSelector,languages,languageOrdering]);const activeLanguage=useMemo(()=>{if(resolvedSdk&&sdkTypes.has(resolvedSdk)){return`${resolvedSdk}_${lang}`}if(lang)return lang;if(filteredLanguages.length>0)return filteredLanguages[0];return languages[0]},[resolvedSdk,sdkTypes,lang,filteredLanguages,languages]);const requiresApiKeySubstitution=useMemo(()=>{const containsPlaceholder=codeData.some(code=>code?.content.includes("{{API_KEY}}"));return containsPlaceholder&&!!apiKeys&&apiKeys.length>0&&!!selectedApiKey},[codeData,apiKeys,selectedApiKey]);const[isHovering,setIsHovering]=useState(false);const hasOnlyJsonSnippet=useMemo(()=>languages.length===1&&languages[0]==="json",[languages]);const processedChildren=useMemo(()=>{if(!activeLanguage)return[];const targetLanguage=hasOnlyJsonSnippet?"json":activeLanguage;return codeData.filter(code=>{return code?.language===targetLanguage}).map(code=>{if(!code)return null;const cleanLang=hasOnlyJsonSnippet?"json":code.language;const langInfo=getLanguageInfo(cleanLang??"");if(typeof code.content==="string"||typeof code.content==="number"||typeof code.content==="boolean"){let processedContent=String(code.content);if(requiresApiKeySubstitution){processedContent=substituteApiKey(processedContent,selectedApiKey)}if(!langInfo.syntaxHighlighterKey||!cleanLang)return null;return React.createElement(Code,{key:code.language,language:langInfo.syntaxHighlighterKey||cleanLang,snippet:processedContent,additionalCSS:"!bg-neutral-000 text-neutral-1300 dark:!bg-neutral-1300 dark:text-neutral-200 px-6 py-4",showLines:showCodeLines})}return null})},[activeLanguage,hasOnlyJsonSnippet,codeData,requiresApiKeySubstitution,showCodeLines,selectedApiKey]);const hasSnippetForActiveLanguage=useMemo(()=>{if(!activeLanguage)return false;if(hasOnlyJsonSnippet)return true;return codeData.some(code=>{return code?.language===activeLanguage})},[activeLanguage,hasOnlyJsonSnippet,codeData]);const handleSDKTypeChange=useCallback(type=>{const nextLang=stripSdkType(languages.find(l=>l===`${type}_${stripSdkType(activeLanguage)}`)??languages.find(l=>l.startsWith(`${type}_`))??activeLanguage);if(onChange&&nextLang){onChange(stripSdkType(activeLanguage),type)}},[activeLanguage,languages,onChange]);const handleLanguageChange=useCallback(language=>{if(onChange){onChange(stripSdkType(language),resolvedSdk)}},[onChange,resolvedSdk]);const noSnippetMessage=useMemo(()=>{if(!activeLanguage)return null;const activeLanguageInfo=getLanguageInfo(activeLanguage);return React.createElement("div",{className:"px-16 py-6 ui-text-body2 text-neutral-800 dark:text-neutral-400 text-center flex flex-col gap-3 items-center"},React.createElement(Icon,{name:"icon-gui-exclamation-triangle-outline",color:"text-yellow-600 dark:text-yellow-400",size:"24px"}),React.createElement("p",{className:"ui-text-p3 text-neutral-700 dark:text-neutral-600"},"You're currently viewing the ",activeLanguageInfo.label," docs. There either isn't a ",activeLanguageInfo.label," code sample for this example, or this feature isn't supported in"," ",activeLanguageInfo.label,". Switch language to view this example in a different language, or check which SDKs support this feature."))},[activeLanguage]);const showLanguageSelector=!fixed&&filteredLanguages.length>0;const showFullSelector=filteredLanguages.length>1;const renderContent=useMemo(()=>{if(!activeLanguage)return null;if(hasSnippetForActiveLanguage){return processedChildren}return noSnippetMessage},[activeLanguage,hasSnippetForActiveLanguage,processedChildren,noSnippetMessage]);if(isSinglePlainCommand){const plainChild=codeData[0];if(plainChild){const codeContent=plainChild.content;const language=plainChild.language;if(!language||!codeContent)return null;let processedContent=String(codeContent);if(requiresApiKeySubstitution){processedContent=substituteApiKey(processedContent,selectedApiKey)}return React.createElement(PlainCodeView,{content:processedContent,className:className,language:language,icon:language==="shell"?"icon-gui-command-line-outline":null})}}return React.createElement("div",{className:cn("rounded-lg overflow-hidden bg-neutral-100 dark:bg-neutral-1200 border border-neutral-300 dark:border-neutral-1000 min-h-[3.375rem]",className)},headerRow&&React.createElement("div",{className:"h-[2.375rem] bg-neutral-200 dark:bg-neutral-1100 border-b border-neutral-300 dark:border-neutral-1000 flex items-center py-1 px-3 rounded-t-lg"},React.createElement("div",{className:"flex space-x-1.5"},React.createElement("div",{className:"w-3 h-3 rounded-full bg-orange-500"}),React.createElement("div",{className:"w-3 h-3 rounded-full bg-yellow-500"}),React.createElement("div",{className:"w-3 h-3 rounded-full bg-green-500"})),React.createElement("div",{className:"flex-1 text-center ui-text-p3 font-bold text-neutral-1300 dark:text-neutral-000"},title),React.createElement("div",{className:"w-12"})),showSDKSelector&&React.createElement("div",{className:cn("p-2 border-b border-neutral-300 dark:border-neutral-1000",sdkTypes.size===1&&"p-1",headerRow?"":"rounded-t-lg")},React.createElement("div",{className:"flex gap-1 justify-start"},["realtime","rest"].map(type=>sdkTypes.has(type)&&React.createElement(SegmentedControl,{key:type,onClick:()=>handleSDKTypeChange(type),size:"xs",active:resolvedSdk===type,className:cn("text-[11px] font-semibold px-2 py-1 h-auto",sdkTypes.size===1&&"pointer-events-none bg-neutral-100 dark:bg-neutral-1200 !text-neutral-800 !dark:text-neutral-500",sdkTypes.size>1&&"bg-neutral-100 dark:bg-neutral-1200",sdkTypes.size>1&&resolvedSdk===type&&"bg-neutral-000 dark:bg-neutral-1100")},type==="realtime"?"Realtime":"REST")))),showLanguageSelector&&(showFullSelector?React.createElement(LanguageSelector,{languages:filteredLanguages,activeLanguage:activeLanguage,onLanguageChange:handleLanguageChange}):React.createElement("div",{className:cn("border-b border-neutral-300 dark:border-neutral-1000 h-[2.125rem] inline-flex items-center px-3 w-full",{"rounded-t-lg":!headerRow})},filteredLanguages.length>0&&React.createElement("div",{className:cn("inline-flex items-center",{"cursor-pointer":filteredLanguages.length>0}),...filteredLanguages.length>0&&{onClick:()=>handleLanguageChange(filteredLanguages[0])}},React.createElement(Icon,{name:getLanguageInfo(filteredLanguages[0]).icon,size:"16px",additionalCSS:"mr-2"}),React.createElement("span",{className:"ui-text-label4 font-semibold text-neutral-800 dark:text-neutral-500 select-none"},getLanguageInfo(filteredLanguages[0]).label)))),React.createElement("div",{ref:codeRef,className:"relative",onMouseEnter:()=>setIsHovering(true),onMouseLeave:()=>setIsHovering(false),onFocus:()=>setIsHovering(true),onBlur:()=>setIsHovering(false)},renderContent,isHovering&&activeLanguage&&hasSnippetForActiveLanguage&&React.createElement(CopyButton,{onCopy:()=>{const text=codeData.find(code=>code.language===activeLanguage)?.content;if(text)navigator.clipboard.writeText(substituteApiKey(text,selectedApiKey,false))}})),requiresApiKeySubstitution&&React.createElement(ApiKeySelector,{apiKeys:apiKeys,selectedApiKey:selectedApiKey,onApiKeyChange:setSelectedApiKey}))};export default CodeSnippet;
|
|
2
2
|
//# sourceMappingURL=CodeSnippet.js.map
|
package/core/CodeSnippet.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/CodeSnippet.tsx"],"sourcesContent":["import React, {\n useState,\n useEffect,\n Children,\n isValidElement,\n useRef,\n useCallback,\n useMemo,\n} from \"react\";\nimport Code from \"./Code\";\nimport cn from \"./utils/cn\";\nimport Icon from \"./Icon\";\nimport { getLanguageInfo, stripSdkType } from \"./CodeSnippet/languages\";\nimport LanguageSelector from \"./CodeSnippet/LanguageSelector\";\nimport ApiKeySelector from \"./CodeSnippet/ApiKeySelector\";\nimport useCopyToClipboard from \"./utils/useCopyToClipboard\";\nimport PlainCodeView from \"./CodeSnippet/PlainCodeView\";\nimport CopyButton from \"./CodeSnippet/CopyButton\";\nimport TooltipButton from \"./CodeSnippet/TooltipButton\";\n\n// Define SDK type\nexport type SDKType = \"realtime\" | \"rest\" | null;\n\n// Define API key types\nexport type ApiKeysItem = {\n app: string;\n keys: { name: string; key: string }[];\n};\n\nexport type CodeSnippetProps = {\n /**\n * If true, hides the language selector row completely\n */\n fixed?: boolean;\n /**\n * If true, renders a macOS-style window header with buttons and title\n */\n headerRow?: boolean;\n /**\n * Title to display in the header row (when headerRow is true)\n */\n title?: string;\n /**\n * Children elements with lang attribute\n */\n children: React.ReactNode;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Default language to display. If not found in available languages, first available is used.\n * If found in languages but no matching snippet exists, a message is displayed.\n */\n lang: string | null;\n /**\n * Callback fired when the active language changes\n */\n onChange?: (language: string, sdk?: SDKType) => void;\n /**\n * List of API keys to display in a dropdown\n */\n apiKeys?: ApiKeysItem[];\n /**\n * Default SDK type to use for the code snippet\n */\n sdk?: SDKType;\n /**\n * Whether to show line numbers in code snippets\n */\n showCodeLines?: boolean;\n /**\n * Defines the order in which languages should be displayed.\n * Languages not in this array will be shown after those that are included.\n */\n languageOrdering?: string[];\n};\n\n// Substitution function for API key placeholders\nconst substituteApiKey = (\n content: string,\n apiKey: string,\n mask = true,\n): string => {\n return content.replace(\n /\\{\\{API_KEY\\}\\}/g,\n mask ? `${apiKey.split(\":\")[0]}:*****` : apiKey,\n );\n};\n\n/**\n * CodeSnippet component that displays code with language switching capability\n */\nconst CodeSnippet: React.FC<CodeSnippetProps> = ({\n fixed = false,\n headerRow = false,\n title = \"Code\",\n children,\n className,\n lang,\n onChange,\n apiKeys,\n sdk,\n showCodeLines = true,\n languageOrdering,\n}) => {\n const codeRef = useRef<HTMLDivElement>(null);\n const { isCopied, copy } = useCopyToClipboard();\n\n const [selectedApiKey, setSelectedApiKey] = useState<string>(\n () => apiKeys?.[0]?.keys?.[0]?.key ?? \"\",\n );\n\n useEffect(() => {\n if (!selectedApiKey && apiKeys && apiKeys.length > 0) {\n setSelectedApiKey(apiKeys[0].keys?.[0]?.key);\n }\n }, [apiKeys, selectedApiKey]);\n\n useEffect(() => {\n const element = codeRef.current;\n if (!element) return;\n\n // Detects the key masking via substituteApiKey (i.e. \"abcde:*****\") and replaces it with the actual API key\n const unmaskRenderedApiKey = (content: string, apiKey: string): string => {\n return content.replace(/(['\"]?)([^:'\"]+):\\*{5}\\1/g, `$1${apiKey}$1`);\n };\n\n const handleCopy = (event: ClipboardEvent) => {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n const selectedText = selection.toString();\n if (!selectedText) return;\n\n // Check if the selection is within our element\n const range = selection.getRangeAt(0);\n if (!element.contains(range.commonAncestorContainer)) return;\n\n const modifiedText = unmaskRenderedApiKey(selectedText, selectedApiKey);\n\n event.clipboardData?.setData(\"text/plain\", modifiedText);\n event.preventDefault();\n };\n\n document.addEventListener(\"copy\", handleCopy);\n\n return () => {\n document.removeEventListener(\"copy\", handleCopy);\n };\n }, [selectedApiKey]);\n\n const extractLanguageFromCode = useCallback(\n (codeElement: React.ReactElement | null): string | null => {\n if (!codeElement || !codeElement.props.className) return null;\n\n const classNames = codeElement.props.className.split(\" \");\n const langClass = classNames.find((cls: string) =>\n cls.startsWith(\"language-\"),\n );\n if (!langClass) return null;\n\n return langClass.substring(9); // Remove \"language-\" prefix\n },\n [],\n );\n\n const { codeData, languages, sdkTypes, isSinglePlainCommand } =\n useMemo(() => {\n const childrenArray = Children.toArray(children);\n const languages: string[] = [];\n const sdkTypes = new Set<SDKType>();\n const codeData: { language: string; content: string }[] = [];\n\n const isSinglePlainCommand =\n childrenArray.length === 1 &&\n [\"language-shell\", \"language-text\"].some(\n (lang) =>\n isValidElement(childrenArray[0]) &&\n isValidElement(childrenArray[0].props.children) &&\n childrenArray[0].props.children.props.className?.includes(lang),\n );\n\n childrenArray.forEach((child) => {\n if (!isValidElement(child)) return;\n\n const preElement = child;\n const codeElement = isValidElement(preElement.props.children)\n ? preElement.props.children\n : null;\n\n if (!codeElement) return;\n\n const codeLanguage = extractLanguageFromCode(codeElement);\n\n if (!codeLanguage) return;\n\n if (codeLanguage.startsWith(\"realtime_\")) {\n sdkTypes.add(\"realtime\");\n } else if (codeLanguage.startsWith(\"rest_\")) {\n sdkTypes.add(\"rest\");\n }\n\n if (!languages.includes(codeLanguage)) {\n languages.push(codeLanguage);\n }\n\n const codeContent = codeElement.props.children;\n codeData.push({ language: codeLanguage, content: codeContent });\n });\n\n return {\n codeData,\n languages,\n sdkTypes,\n isSinglePlainCommand,\n };\n }, [children, extractLanguageFromCode]);\n\n const resolvedSdk: SDKType = useMemo(() => {\n if (sdkTypes.size === 1 && sdk && !sdkTypes.has(sdk)) {\n return Array.from(sdkTypes)[0];\n }\n return sdk ?? null;\n }, [sdk, sdkTypes]);\n\n const showSDKSelector = sdkTypes.size > 0;\n\n const filteredLanguages = useMemo(() => {\n const filtered =\n !resolvedSdk || !showSDKSelector\n ? [...languages]\n : languages.filter((lang) => lang.startsWith(`${resolvedSdk}_`));\n\n // Apply custom ordering if provided\n if (languageOrdering && languageOrdering.length > 0) {\n filtered.sort((a, b) => {\n const aBase = stripSdkType(a);\n const bBase = stripSdkType(b);\n\n const aIndex = languageOrdering.indexOf(aBase);\n const bIndex = languageOrdering.indexOf(bBase);\n\n if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;\n if (aIndex !== -1) return -1;\n if (bIndex !== -1) return 1;\n return 0;\n });\n }\n\n return filtered;\n }, [resolvedSdk, showSDKSelector, languages, languageOrdering]);\n\n const activeLanguage = useMemo(() => {\n if (resolvedSdk && sdkTypes.has(resolvedSdk)) {\n return `${resolvedSdk}_${lang}`;\n }\n\n if (lang) return lang;\n\n if (filteredLanguages.length > 0) return filteredLanguages[0];\n\n return languages[0];\n }, [resolvedSdk, sdkTypes, lang, filteredLanguages, languages]);\n\n const requiresApiKeySubstitution = useMemo(() => {\n const containsPlaceholder = codeData.some((code) =>\n code?.content.includes(\"{{API_KEY}}\"),\n );\n\n return (\n containsPlaceholder && !!apiKeys && apiKeys.length > 0 && !!selectedApiKey\n );\n }, [codeData, apiKeys, selectedApiKey]);\n\n const [isHovering, setIsHovering] = useState(false);\n\n const hasOnlyJsonSnippet = useMemo(\n () => languages.length === 1 && languages[0] === \"json\",\n [languages],\n );\n\n const processedChildren = useMemo(() => {\n if (!activeLanguage) return [];\n\n const targetLanguage = hasOnlyJsonSnippet ? \"json\" : activeLanguage;\n\n return codeData\n .filter((code) => {\n return code?.language === targetLanguage;\n })\n .map((code) => {\n if (!code) return null;\n\n const cleanLang = hasOnlyJsonSnippet ? \"json\" : code.language;\n const langInfo = getLanguageInfo(cleanLang ?? \"\");\n\n if (\n typeof code.content === \"string\" ||\n typeof code.content === \"number\" ||\n typeof code.content === \"boolean\"\n ) {\n // Apply API key substitution if apiKeys are provided\n let processedContent = String(code.content);\n if (requiresApiKeySubstitution) {\n processedContent = substituteApiKey(\n processedContent,\n selectedApiKey,\n );\n }\n\n if (!langInfo.syntaxHighlighterKey || !cleanLang) return null;\n\n return (\n <Code\n key={code.language}\n language={langInfo.syntaxHighlighterKey || cleanLang}\n snippet={processedContent}\n additionalCSS=\"bg-neutral-100 text-neutral-1300 dark:bg-neutral-1200 dark:text-neutral-200 px-6 py-4\"\n showLines={showCodeLines}\n />\n );\n }\n\n return null;\n });\n }, [\n activeLanguage,\n hasOnlyJsonSnippet,\n codeData,\n requiresApiKeySubstitution,\n showCodeLines,\n selectedApiKey,\n ]);\n\n const hasSnippetForActiveLanguage = useMemo(() => {\n if (!activeLanguage) return false;\n if (hasOnlyJsonSnippet) return true;\n\n return codeData.some((code) => {\n return code?.language === activeLanguage;\n });\n }, [activeLanguage, hasOnlyJsonSnippet, codeData]);\n\n const handleSDKTypeChange = useCallback(\n (type: SDKType) => {\n const nextLang = stripSdkType(\n languages.find(\n (l) => l === `${type}_${stripSdkType(activeLanguage)}`,\n ) ??\n languages.find((l) => l.startsWith(`${type}_`)) ??\n activeLanguage,\n );\n\n if (onChange && nextLang) {\n onChange(stripSdkType(activeLanguage), type);\n }\n },\n [activeLanguage, languages, onChange],\n );\n\n const handleLanguageChange = useCallback(\n (language: string) => {\n if (onChange) {\n onChange(stripSdkType(language), resolvedSdk);\n }\n },\n [onChange, resolvedSdk],\n );\n\n const NoSnippetMessage = useMemo(() => {\n if (!activeLanguage) return () => null;\n\n const activeLanguageInfo = getLanguageInfo(activeLanguage);\n\n return () => (\n <div className=\"px-16 py-6 ui-text-body2 text-neutral-800 dark:text-neutral-400 text-center flex flex-col gap-3 items-center\">\n <Icon\n name=\"icon-gui-exclamation-triangle-outline\"\n color=\"text-yellow-600 dark:text-yellow-400\"\n size=\"24px\"\n />\n <p className=\"ui-text-p3 text-neutral-700 dark:text-neutral-600\">\n You're currently viewing the {activeLanguageInfo.label} docs.\n There either isn't a {activeLanguageInfo.label} code sample for\n this example, or this feature isn't supported in{\" \"}\n {activeLanguageInfo.label}. Switch language to view this example in a\n different language, or check which SDKs support this feature.\n </p>\n </div>\n );\n }, [activeLanguage]);\n\n const showLanguageSelector = !fixed && filteredLanguages.length > 0;\n const showFullSelector = filteredLanguages.length > 1;\n\n const renderContent = useMemo(() => {\n if (!activeLanguage) return null;\n\n if (hasSnippetForActiveLanguage) {\n return processedChildren;\n }\n\n return <NoSnippetMessage />;\n }, [\n activeLanguage,\n hasSnippetForActiveLanguage,\n processedChildren,\n NoSnippetMessage,\n ]);\n\n // Render special case for plain commands (shell or text)\n if (isSinglePlainCommand) {\n const plainChild = codeData[0];\n if (plainChild) {\n const codeContent = plainChild.content;\n const language = plainChild.language;\n\n if (!language || !codeContent) return null;\n\n // Apply API key substitution if apiKeys are provided\n let processedContent = String(codeContent);\n if (requiresApiKeySubstitution) {\n processedContent = substituteApiKey(processedContent, selectedApiKey);\n }\n\n return (\n <PlainCodeView\n content={processedContent}\n className={className}\n language={language}\n icon={language === \"shell\" ? \"icon-gui-command-line-outline\" : null}\n />\n );\n }\n }\n\n return (\n <div\n className={cn(\n \"rounded-lg overflow-hidden bg-neutral-100 dark:bg-neutral-1200 border border-neutral-300 dark:border-neutral-1000 min-h-[3.375rem]\",\n className,\n )}\n >\n {headerRow && (\n <div className=\"h-[2.375rem] bg-neutral-200 dark:bg-neutral-1100 border-b border-neutral-300 dark:border-neutral-1000 flex items-center py-1 px-3 rounded-t-lg\">\n <div className=\"flex space-x-1.5\">\n <div className=\"w-3 h-3 rounded-full bg-orange-500\"></div>\n <div className=\"w-3 h-3 rounded-full bg-yellow-500\"></div>\n <div className=\"w-3 h-3 rounded-full bg-green-500\"></div>\n </div>\n\n <div className=\"flex-1 text-center ui-text-p3 font-bold text-neutral-1300 dark:text-neutral-000\">\n {title}\n </div>\n\n {/* Empty div for balance */}\n <div className=\"w-12\"></div>\n </div>\n )}\n {showSDKSelector && (\n <div\n className={cn(\n \"p-2 border-b border-neutral-200 dark:border-neutral-1100 h-14\",\n headerRow ? \"\" : \"rounded-t-lg\",\n )}\n >\n <div className=\"flex gap-3 justify-start\">\n {sdkTypes.has(\"realtime\") && (\n <TooltipButton\n tooltip=\"Realtime SDK\"\n active={resolvedSdk === \"realtime\"}\n onClick={() => handleSDKTypeChange(\"realtime\")}\n variant=\"segmented\"\n size=\"sm\"\n alwaysShowLabel={true}\n >\n Realtime\n </TooltipButton>\n )}\n\n {sdkTypes.has(\"rest\") && (\n <TooltipButton\n tooltip=\"REST SDK\"\n active={resolvedSdk === \"rest\"}\n onClick={() => handleSDKTypeChange(\"rest\")}\n variant=\"segmented\"\n size=\"sm\"\n alwaysShowLabel={true}\n >\n REST\n </TooltipButton>\n )}\n </div>\n </div>\n )}\n\n {showLanguageSelector &&\n (showFullSelector ? (\n <LanguageSelector\n languages={filteredLanguages}\n activeLanguage={activeLanguage}\n onLanguageChange={handleLanguageChange}\n />\n ) : (\n <div\n className={cn(\n \"border-b border-neutral-200 dark:border-neutral-1100 h-[2.125rem] inline-flex items-center px-3 w-full\",\n { \"rounded-t-lg\": !headerRow },\n )}\n >\n {filteredLanguages.length > 0 && (\n <div\n className={cn(\"inline-flex items-center\", {\n \"cursor-pointer\": filteredLanguages.length > 0,\n })}\n {...(filteredLanguages.length > 0 && {\n onClick: () => handleLanguageChange(filteredLanguages[0]),\n })}\n >\n <Icon\n name={getLanguageInfo(filteredLanguages[0]).icon}\n size=\"16px\"\n additionalCSS=\"mr-2\"\n />\n <span className=\"ui-text-label4 font-semibold text-neutral-800 dark:text-neutral-500 select-none\">\n {getLanguageInfo(filteredLanguages[0]).label}\n </span>\n </div>\n )}\n </div>\n ))}\n <div\n ref={codeRef}\n className=\"relative\"\n onMouseEnter={() => setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n onFocus={() => setIsHovering(true)}\n onBlur={() => setIsHovering(false)}\n tabIndex={0}\n role=\"button\"\n aria-label=\"Focusable code snippet area\"\n >\n {renderContent}\n {isHovering && activeLanguage && (\n <CopyButton\n onCopy={() => {\n const text = codeData.find(\n (code) => code.language === activeLanguage,\n )?.content;\n if (text) copy(substituteApiKey(text, selectedApiKey, false));\n }}\n isCopied={isCopied}\n />\n )}\n </div>\n {requiresApiKeySubstitution && (\n <ApiKeySelector\n apiKeys={apiKeys}\n selectedApiKey={selectedApiKey}\n onApiKeyChange={setSelectedApiKey}\n />\n )}\n </div>\n );\n};\n\nexport default CodeSnippet;\n"],"names":["React","useState","useEffect","Children","isValidElement","useRef","useCallback","useMemo","Code","cn","Icon","getLanguageInfo","stripSdkType","LanguageSelector","ApiKeySelector","useCopyToClipboard","PlainCodeView","CopyButton","TooltipButton","substituteApiKey","content","apiKey","mask","replace","split","CodeSnippet","fixed","headerRow","title","children","className","lang","onChange","apiKeys","sdk","showCodeLines","languageOrdering","codeRef","isCopied","copy","selectedApiKey","setSelectedApiKey","keys","key","length","element","current","unmaskRenderedApiKey","handleCopy","event","selection","window","getSelection","rangeCount","selectedText","toString","range","getRangeAt","contains","commonAncestorContainer","modifiedText","clipboardData","setData","preventDefault","document","addEventListener","removeEventListener","extractLanguageFromCode","codeElement","props","classNames","langClass","find","cls","startsWith","substring","codeData","languages","sdkTypes","isSinglePlainCommand","childrenArray","toArray","Set","some","includes","forEach","child","preElement","codeLanguage","add","push","codeContent","language","resolvedSdk","size","has","Array","from","showSDKSelector","filteredLanguages","filtered","filter","sort","a","b","aBase","bBase","aIndex","indexOf","bIndex","activeLanguage","requiresApiKeySubstitution","containsPlaceholder","code","isHovering","setIsHovering","hasOnlyJsonSnippet","processedChildren","targetLanguage","map","cleanLang","langInfo","processedContent","String","syntaxHighlighterKey","snippet","additionalCSS","showLines","hasSnippetForActiveLanguage","handleSDKTypeChange","type","nextLang","l","handleLanguageChange","NoSnippetMessage","activeLanguageInfo","div","name","color","p","label","showLanguageSelector","showFullSelector","renderContent","plainChild","icon","tooltip","active","onClick","variant","alwaysShowLabel","onLanguageChange","span","ref","onMouseEnter","onMouseLeave","onFocus","onBlur","tabIndex","role","aria-label","onCopy","text","onApiKeyChange"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/core/CodeSnippet.tsx"],"sourcesContent":["import React, {\n useState,\n useEffect,\n Children,\n isValidElement,\n useRef,\n useCallback,\n useMemo,\n} from \"react\";\nimport Code from \"./Code\";\nimport cn from \"./utils/cn\";\nimport Icon from \"./Icon\";\nimport { getLanguageInfo, stripSdkType } from \"./CodeSnippet/languages\";\nimport LanguageSelector from \"./CodeSnippet/LanguageSelector\";\nimport ApiKeySelector from \"./CodeSnippet/ApiKeySelector\";\nimport PlainCodeView from \"./CodeSnippet/PlainCodeView\";\nimport CopyButton from \"./CodeSnippet/CopyButton\";\nimport SegmentedControl from \"./SegmentedControl\";\n\n// Define SDK type\nexport type SDKType = \"realtime\" | \"rest\" | null;\n\n// Define API key types\nexport type ApiKeysItem = {\n app: string;\n keys: { name: string; key: string }[];\n};\n\nexport type CodeSnippetProps = {\n /**\n * If true, hides the language selector row completely\n */\n fixed?: boolean;\n /**\n * If true, renders a macOS-style window header with buttons and title\n */\n headerRow?: boolean;\n /**\n * Title to display in the header row (when headerRow is true)\n */\n title?: string;\n /**\n * Children elements with lang attribute\n */\n children: React.ReactNode;\n /**\n * Additional CSS classes\n */\n className?: string;\n /**\n * Default language to display. If not found in available languages, first available is used.\n * If found in languages but no matching snippet exists, a message is displayed.\n */\n lang: string | null;\n /**\n * Callback fired when the active language changes\n */\n onChange?: (language: string, sdk?: SDKType) => void;\n /**\n * List of API keys to display in a dropdown\n */\n apiKeys?: ApiKeysItem[];\n /**\n * Default SDK type to use for the code snippet\n */\n sdk?: SDKType;\n /**\n * Whether to show line numbers in code snippets\n */\n showCodeLines?: boolean;\n /**\n * Defines the order in which languages should be displayed.\n * Languages not in this array will be shown after those that are included.\n */\n languageOrdering?: string[];\n};\n\n// Substitution function for API key placeholders\nconst substituteApiKey = (\n content: string,\n apiKey: string,\n mask = true,\n): string => {\n return content.replace(\n /\\{\\{API_KEY\\}\\}/g,\n mask ? `${apiKey.split(\":\")[0]}:*****` : apiKey,\n );\n};\n\n/**\n * CodeSnippet component that displays code with language switching capability\n */\nconst CodeSnippet: React.FC<CodeSnippetProps> = ({\n fixed = false,\n headerRow = false,\n title = \"Code\",\n children,\n className,\n lang,\n onChange,\n apiKeys,\n sdk,\n showCodeLines = true,\n languageOrdering,\n}) => {\n const codeRef = useRef<HTMLDivElement>(null);\n\n const [selectedApiKey, setSelectedApiKey] = useState<string>(\n () => apiKeys?.[0]?.keys?.[0]?.key ?? \"\",\n );\n\n useEffect(() => {\n if (!selectedApiKey && apiKeys && apiKeys.length > 0) {\n setSelectedApiKey(apiKeys[0].keys?.[0]?.key);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [apiKeys]);\n\n useEffect(() => {\n const element = codeRef.current;\n if (!element) return;\n\n // Detects the key masking via substituteApiKey (i.e. \"abcde:*****\") and replaces it with the actual API key\n const unmaskRenderedApiKey = (content: string, apiKey: string): string => {\n return content.replace(/(['\"]?)([^:'\"]+):\\*{5}\\1/g, `$1${apiKey}$1`);\n };\n\n const handleCopy = (event: ClipboardEvent) => {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return;\n\n const selectedText = selection.toString();\n if (!selectedText) return;\n\n // Check if the selection is within our element\n const range = selection.getRangeAt(0);\n if (!element.contains(range.commonAncestorContainer)) return;\n\n const modifiedText = unmaskRenderedApiKey(selectedText, selectedApiKey);\n\n event.clipboardData?.setData(\"text/plain\", modifiedText);\n event.preventDefault();\n };\n\n document.addEventListener(\"copy\", handleCopy);\n\n return () => {\n document.removeEventListener(\"copy\", handleCopy);\n };\n }, [selectedApiKey]);\n\n const extractLanguageFromCode = useCallback(\n (codeElement: React.ReactElement | null): string | null => {\n if (!codeElement || !codeElement.props.className) return null;\n\n const classNames = codeElement.props.className.split(\" \");\n const langClass = classNames.find((cls: string) =>\n cls.startsWith(\"language-\"),\n );\n if (!langClass) return null;\n\n return langClass.substring(9); // Remove \"language-\" prefix\n },\n [],\n );\n\n const { codeData, languages, sdkTypes, isSinglePlainCommand } =\n useMemo(() => {\n const childrenArray = Children.toArray(children);\n const languages: string[] = [];\n const sdkTypes = new Set<SDKType>();\n const codeData: { language: string; content: string }[] = [];\n\n const isSinglePlainCommand =\n childrenArray.length === 1 &&\n [\"language-shell\", \"language-text\"].some(\n (lang) =>\n isValidElement(childrenArray[0]) &&\n isValidElement(childrenArray[0].props.children) &&\n childrenArray[0].props.children.props.className?.includes(lang),\n );\n\n childrenArray.forEach((child) => {\n if (!isValidElement(child)) return;\n\n const preElement = child;\n const codeElement = isValidElement(preElement.props.children)\n ? preElement.props.children\n : null;\n\n if (!codeElement) return;\n\n const codeLanguage = extractLanguageFromCode(codeElement);\n\n if (!codeLanguage) return;\n\n if (codeLanguage.startsWith(\"realtime_\")) {\n sdkTypes.add(\"realtime\");\n } else if (codeLanguage.startsWith(\"rest_\")) {\n sdkTypes.add(\"rest\");\n }\n\n if (!languages.includes(codeLanguage)) {\n languages.push(codeLanguage);\n }\n\n const codeContent = codeElement.props.children;\n codeData.push({ language: codeLanguage, content: codeContent });\n });\n\n return {\n codeData,\n languages,\n sdkTypes,\n isSinglePlainCommand,\n };\n }, [children, extractLanguageFromCode]);\n\n const resolvedSdk: SDKType = useMemo(() => {\n if (sdkTypes.size === 1 && sdk && !sdkTypes.has(sdk)) {\n return Array.from(sdkTypes)[0];\n }\n return sdk ?? null;\n }, [sdk, sdkTypes]);\n\n const showSDKSelector = sdkTypes.size > 0;\n\n const filteredLanguages = useMemo(() => {\n const filtered =\n !resolvedSdk || !showSDKSelector\n ? [...languages]\n : languages.filter((lang) => lang.startsWith(`${resolvedSdk}_`));\n\n // Apply custom ordering if provided\n if (languageOrdering && languageOrdering.length > 0) {\n filtered.sort((a, b) => {\n const aBase = stripSdkType(a);\n const bBase = stripSdkType(b);\n\n const aIndex = languageOrdering.indexOf(aBase);\n const bIndex = languageOrdering.indexOf(bBase);\n\n if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;\n if (aIndex !== -1) return -1;\n if (bIndex !== -1) return 1;\n return 0;\n });\n }\n\n return filtered;\n }, [resolvedSdk, showSDKSelector, languages, languageOrdering]);\n\n const activeLanguage = useMemo(() => {\n if (resolvedSdk && sdkTypes.has(resolvedSdk)) {\n return `${resolvedSdk}_${lang}`;\n }\n\n if (lang) return lang;\n\n if (filteredLanguages.length > 0) return filteredLanguages[0];\n\n return languages[0];\n }, [resolvedSdk, sdkTypes, lang, filteredLanguages, languages]);\n\n const requiresApiKeySubstitution = useMemo(() => {\n const containsPlaceholder = codeData.some((code) =>\n code?.content.includes(\"{{API_KEY}}\"),\n );\n\n return (\n containsPlaceholder && !!apiKeys && apiKeys.length > 0 && !!selectedApiKey\n );\n }, [codeData, apiKeys, selectedApiKey]);\n\n const [isHovering, setIsHovering] = useState(false);\n\n const hasOnlyJsonSnippet = useMemo(\n () => languages.length === 1 && languages[0] === \"json\",\n [languages],\n );\n\n const processedChildren = useMemo(() => {\n if (!activeLanguage) return [];\n\n const targetLanguage = hasOnlyJsonSnippet ? \"json\" : activeLanguage;\n\n return codeData\n .filter((code) => {\n return code?.language === targetLanguage;\n })\n .map((code) => {\n if (!code) return null;\n\n const cleanLang = hasOnlyJsonSnippet ? \"json\" : code.language;\n const langInfo = getLanguageInfo(cleanLang ?? \"\");\n\n if (\n typeof code.content === \"string\" ||\n typeof code.content === \"number\" ||\n typeof code.content === \"boolean\"\n ) {\n // Apply API key substitution if apiKeys are provided\n let processedContent = String(code.content);\n if (requiresApiKeySubstitution) {\n processedContent = substituteApiKey(\n processedContent,\n selectedApiKey,\n );\n }\n\n if (!langInfo.syntaxHighlighterKey || !cleanLang) return null;\n\n return (\n <Code\n key={code.language}\n language={langInfo.syntaxHighlighterKey || cleanLang}\n snippet={processedContent}\n additionalCSS=\"!bg-neutral-000 text-neutral-1300 dark:!bg-neutral-1300 dark:text-neutral-200 px-6 py-4\"\n showLines={showCodeLines}\n />\n );\n }\n\n return null;\n });\n }, [\n activeLanguage,\n hasOnlyJsonSnippet,\n codeData,\n requiresApiKeySubstitution,\n showCodeLines,\n selectedApiKey,\n ]);\n\n const hasSnippetForActiveLanguage = useMemo(() => {\n if (!activeLanguage) return false;\n if (hasOnlyJsonSnippet) return true;\n\n return codeData.some((code) => {\n return code?.language === activeLanguage;\n });\n }, [activeLanguage, hasOnlyJsonSnippet, codeData]);\n\n const handleSDKTypeChange = useCallback(\n (type: SDKType) => {\n const nextLang = stripSdkType(\n languages.find(\n (l) => l === `${type}_${stripSdkType(activeLanguage)}`,\n ) ??\n languages.find((l) => l.startsWith(`${type}_`)) ??\n activeLanguage,\n );\n\n if (onChange && nextLang) {\n onChange(stripSdkType(activeLanguage), type);\n }\n },\n [activeLanguage, languages, onChange],\n );\n\n const handleLanguageChange = useCallback(\n (language: string) => {\n if (onChange) {\n onChange(stripSdkType(language), resolvedSdk);\n }\n },\n [onChange, resolvedSdk],\n );\n\n const noSnippetMessage = useMemo(() => {\n if (!activeLanguage) return null;\n\n const activeLanguageInfo = getLanguageInfo(activeLanguage);\n\n return (\n <div className=\"px-16 py-6 ui-text-body2 text-neutral-800 dark:text-neutral-400 text-center flex flex-col gap-3 items-center\">\n <Icon\n name=\"icon-gui-exclamation-triangle-outline\"\n color=\"text-yellow-600 dark:text-yellow-400\"\n size=\"24px\"\n />\n <p className=\"ui-text-p3 text-neutral-700 dark:text-neutral-600\">\n You're currently viewing the {activeLanguageInfo.label} docs.\n There either isn't a {activeLanguageInfo.label} code sample for\n this example, or this feature isn't supported in{\" \"}\n {activeLanguageInfo.label}. Switch language to view this example in a\n different language, or check which SDKs support this feature.\n </p>\n </div>\n );\n }, [activeLanguage]);\n\n const showLanguageSelector = !fixed && filteredLanguages.length > 0;\n const showFullSelector = filteredLanguages.length > 1;\n\n const renderContent = useMemo(() => {\n if (!activeLanguage) return null;\n\n if (hasSnippetForActiveLanguage) {\n return processedChildren;\n }\n\n return noSnippetMessage;\n }, [\n activeLanguage,\n hasSnippetForActiveLanguage,\n processedChildren,\n noSnippetMessage,\n ]);\n\n // Render special case for plain commands (shell or text)\n if (isSinglePlainCommand) {\n const plainChild = codeData[0];\n if (plainChild) {\n const codeContent = plainChild.content;\n const language = plainChild.language;\n\n if (!language || !codeContent) return null;\n\n // Apply API key substitution if apiKeys are provided\n let processedContent = String(codeContent);\n if (requiresApiKeySubstitution) {\n processedContent = substituteApiKey(processedContent, selectedApiKey);\n }\n\n return (\n <PlainCodeView\n content={processedContent}\n className={className}\n language={language}\n icon={language === \"shell\" ? \"icon-gui-command-line-outline\" : null}\n />\n );\n }\n }\n\n return (\n <div\n className={cn(\n \"rounded-lg overflow-hidden bg-neutral-100 dark:bg-neutral-1200 border border-neutral-300 dark:border-neutral-1000 min-h-[3.375rem]\",\n className,\n )}\n >\n {headerRow && (\n <div className=\"h-[2.375rem] bg-neutral-200 dark:bg-neutral-1100 border-b border-neutral-300 dark:border-neutral-1000 flex items-center py-1 px-3 rounded-t-lg\">\n <div className=\"flex space-x-1.5\">\n <div className=\"w-3 h-3 rounded-full bg-orange-500\"></div>\n <div className=\"w-3 h-3 rounded-full bg-yellow-500\"></div>\n <div className=\"w-3 h-3 rounded-full bg-green-500\"></div>\n </div>\n\n <div className=\"flex-1 text-center ui-text-p3 font-bold text-neutral-1300 dark:text-neutral-000\">\n {title}\n </div>\n\n <div className=\"w-12\"></div>\n </div>\n )}\n\n {showSDKSelector && (\n <div\n className={cn(\n \"p-2 border-b border-neutral-300 dark:border-neutral-1000\",\n sdkTypes.size === 1 && \"p-1\",\n headerRow ? \"\" : \"rounded-t-lg\",\n )}\n >\n <div className=\"flex gap-1 justify-start\">\n {[\"realtime\", \"rest\"].map(\n (type) =>\n sdkTypes.has(type as SDKType) && (\n <SegmentedControl\n key={type}\n onClick={() => handleSDKTypeChange(type as SDKType)}\n size=\"xs\"\n active={resolvedSdk === type}\n className={cn(\n \"text-[11px] font-semibold px-2 py-1 h-auto\",\n sdkTypes.size === 1 &&\n \"pointer-events-none bg-neutral-100 dark:bg-neutral-1200 !text-neutral-800 !dark:text-neutral-500\",\n sdkTypes.size > 1 &&\n \"bg-neutral-100 dark:bg-neutral-1200\",\n sdkTypes.size > 1 &&\n resolvedSdk === type &&\n \"bg-neutral-000 dark:bg-neutral-1100\",\n )}\n >\n {type === \"realtime\" ? \"Realtime\" : \"REST\"}\n </SegmentedControl>\n ),\n )}\n </div>\n </div>\n )}\n\n {showLanguageSelector &&\n (showFullSelector ? (\n <LanguageSelector\n languages={filteredLanguages}\n activeLanguage={activeLanguage}\n onLanguageChange={handleLanguageChange}\n />\n ) : (\n <div\n className={cn(\n \"border-b border-neutral-300 dark:border-neutral-1000 h-[2.125rem] inline-flex items-center px-3 w-full\",\n { \"rounded-t-lg\": !headerRow },\n )}\n >\n {filteredLanguages.length > 0 && (\n <div\n className={cn(\"inline-flex items-center\", {\n \"cursor-pointer\": filteredLanguages.length > 0,\n })}\n {...(filteredLanguages.length > 0 && {\n onClick: () => handleLanguageChange(filteredLanguages[0]),\n })}\n >\n <Icon\n name={getLanguageInfo(filteredLanguages[0]).icon}\n size=\"16px\"\n additionalCSS=\"mr-2\"\n />\n <span className=\"ui-text-label4 font-semibold text-neutral-800 dark:text-neutral-500 select-none\">\n {getLanguageInfo(filteredLanguages[0]).label}\n </span>\n </div>\n )}\n </div>\n ))}\n <div\n ref={codeRef}\n className=\"relative\"\n onMouseEnter={() => setIsHovering(true)}\n onMouseLeave={() => setIsHovering(false)}\n onFocus={() => setIsHovering(true)}\n onBlur={() => setIsHovering(false)}\n >\n {renderContent}\n {isHovering && activeLanguage && hasSnippetForActiveLanguage && (\n <CopyButton\n onCopy={() => {\n const text = codeData.find(\n (code) => code.language === activeLanguage,\n )?.content;\n if (text)\n navigator.clipboard.writeText(\n substituteApiKey(text, selectedApiKey, false),\n );\n }}\n />\n )}\n </div>\n {requiresApiKeySubstitution && (\n <ApiKeySelector\n apiKeys={apiKeys}\n selectedApiKey={selectedApiKey}\n onApiKeyChange={setSelectedApiKey}\n />\n )}\n </div>\n );\n};\n\nexport default CodeSnippet;\n"],"names":["React","useState","useEffect","Children","isValidElement","useRef","useCallback","useMemo","Code","cn","Icon","getLanguageInfo","stripSdkType","LanguageSelector","ApiKeySelector","PlainCodeView","CopyButton","SegmentedControl","substituteApiKey","content","apiKey","mask","replace","split","CodeSnippet","fixed","headerRow","title","children","className","lang","onChange","apiKeys","sdk","showCodeLines","languageOrdering","codeRef","selectedApiKey","setSelectedApiKey","keys","key","length","element","current","unmaskRenderedApiKey","handleCopy","event","selection","window","getSelection","rangeCount","selectedText","toString","range","getRangeAt","contains","commonAncestorContainer","modifiedText","clipboardData","setData","preventDefault","document","addEventListener","removeEventListener","extractLanguageFromCode","codeElement","props","classNames","langClass","find","cls","startsWith","substring","codeData","languages","sdkTypes","isSinglePlainCommand","childrenArray","toArray","Set","some","includes","forEach","child","preElement","codeLanguage","add","push","codeContent","language","resolvedSdk","size","has","Array","from","showSDKSelector","filteredLanguages","filtered","filter","sort","a","b","aBase","bBase","aIndex","indexOf","bIndex","activeLanguage","requiresApiKeySubstitution","containsPlaceholder","code","isHovering","setIsHovering","hasOnlyJsonSnippet","processedChildren","targetLanguage","map","cleanLang","langInfo","processedContent","String","syntaxHighlighterKey","snippet","additionalCSS","showLines","hasSnippetForActiveLanguage","handleSDKTypeChange","type","nextLang","l","handleLanguageChange","noSnippetMessage","activeLanguageInfo","div","name","color","p","label","showLanguageSelector","showFullSelector","renderContent","plainChild","icon","onClick","active","onLanguageChange","span","ref","onMouseEnter","onMouseLeave","onFocus","onBlur","onCopy","text","navigator","clipboard","writeText","onApiKeyChange"],"mappings":"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"}
|
package/core/CookieMessage.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{useRef,useEffect,useState}from"react";import Cookie from"js-cookie";import _absUrl from"./url-base";const COOKIE_EXPIRY=365;const CookieMessage=({cookieId,urlBase})=>{const ref=useRef(null);const[hideCookieMessage,setHideCookieMessage]=useState(true);useEffect(()=>{const isCookieSet=Cookie.get(cookieId)?true:false;setHideCookieMessage(isCookieSet)},[cookieId]);const handleClose=()=>{Cookie.set(cookieId,"1",{expires:COOKIE_EXPIRY});ref.current?.classList.add("bottom-px","opacity-0");setTimeout(()=>setHideCookieMessage(true),500)};const absUrl=path=>_absUrl(path,urlBase);if(hideCookieMessage)return null;return React.createElement("div",{className:"ui-cookie-message",ref:ref},React.createElement("p",{className:"ui-text-p2 pr-8"},React.createElement("a",{href:absUrl("/privacy"),className:"underline"},"How we use cookies")," ","to improve your experience."),React.createElement("button",{className:"ui-btn-secondary mt-3 sm:mt-0 whitespace-nowrap",onClick:handleClose},"Accept and close"))};export default CookieMessage;
|
|
1
|
+
import React,{useRef,useEffect,useState}from"react";import Cookie from"js-cookie";import _absUrl from"./url-base";const COOKIE_EXPIRY=365;const CookieMessage=({cookieId,urlBase})=>{const ref=useRef(null);const[hideCookieMessage,setHideCookieMessage]=useState(()=>Cookie.get(cookieId)?true:false);useEffect(()=>{const isCookieSet=Cookie.get(cookieId)?true:false;if(hideCookieMessage!==isCookieSet){setHideCookieMessage(isCookieSet)}},[cookieId]);const handleClose=()=>{Cookie.set(cookieId,"1",{expires:COOKIE_EXPIRY});ref.current?.classList.add("bottom-px","opacity-0");setTimeout(()=>setHideCookieMessage(true),500)};const absUrl=path=>_absUrl(path,urlBase);if(hideCookieMessage)return null;return React.createElement("div",{className:"ui-cookie-message",ref:ref},React.createElement("p",{className:"ui-text-p2 pr-8"},React.createElement("a",{href:absUrl("/privacy"),className:"underline"},"How we use cookies")," ","to improve your experience."),React.createElement("button",{className:"ui-btn-secondary mt-3 sm:mt-0 whitespace-nowrap",onClick:handleClose},"Accept and close"))};export default CookieMessage;
|
|
2
2
|
//# sourceMappingURL=CookieMessage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/CookieMessage.tsx"],"sourcesContent":["import React, { useRef, useEffect, useState } from \"react\";\nimport Cookie from \"js-cookie\";\n\nimport _absUrl from \"./url-base\";\n\nconst COOKIE_EXPIRY = 365;\n\ntype CookieMessageProps = {\n cookieId: string;\n urlBase: string;\n};\n\nconst CookieMessage = ({ cookieId, urlBase }: CookieMessageProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const [hideCookieMessage, setHideCookieMessage] = useState(true);\n\n useEffect(() => {\n const isCookieSet = Cookie.get(cookieId) ? true : false;\n setHideCookieMessage(isCookieSet);\n }, [cookieId]);\n\n const handleClose = () => {\n Cookie.set(cookieId, \"1\", { expires: COOKIE_EXPIRY });\n\n ref.current?.classList.add(\"bottom-px\", \"opacity-0\");\n setTimeout(() => setHideCookieMessage(true), 500);\n };\n\n const absUrl = (path: string) => _absUrl(path, urlBase);\n\n // Presume the message is hidden by default\n if (hideCookieMessage) return null;\n\n return (\n <div className=\"ui-cookie-message\" ref={ref}>\n <p className=\"ui-text-p2 pr-8\">\n <a href={absUrl(\"/privacy\")} className=\"underline\">\n How we use cookies\n </a>{\" \"}\n to improve your experience.\n </p>\n <button\n className=\"ui-btn-secondary mt-3 sm:mt-0 whitespace-nowrap\"\n onClick={handleClose}\n >\n Accept and close\n </button>\n </div>\n );\n};\n\nexport default CookieMessage;\n"],"names":["React","useRef","useEffect","useState","Cookie","_absUrl","COOKIE_EXPIRY","CookieMessage","cookieId","urlBase","ref","hideCookieMessage","setHideCookieMessage","
|
|
1
|
+
{"version":3,"sources":["../../src/core/CookieMessage.tsx"],"sourcesContent":["import React, { useRef, useEffect, useState } from \"react\";\nimport Cookie from \"js-cookie\";\n\nimport _absUrl from \"./url-base\";\n\nconst COOKIE_EXPIRY = 365;\n\ntype CookieMessageProps = {\n cookieId: string;\n urlBase: string;\n};\n\nconst CookieMessage = ({ cookieId, urlBase }: CookieMessageProps) => {\n const ref = useRef<HTMLDivElement>(null);\n const [hideCookieMessage, setHideCookieMessage] = useState(() =>\n Cookie.get(cookieId) ? true : false,\n );\n\n useEffect(() => {\n const isCookieSet = Cookie.get(cookieId) ? true : false;\n if (hideCookieMessage !== isCookieSet) {\n setHideCookieMessage(isCookieSet);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [cookieId]);\n\n const handleClose = () => {\n Cookie.set(cookieId, \"1\", { expires: COOKIE_EXPIRY });\n\n ref.current?.classList.add(\"bottom-px\", \"opacity-0\");\n setTimeout(() => setHideCookieMessage(true), 500);\n };\n\n const absUrl = (path: string) => _absUrl(path, urlBase);\n\n // Presume the message is hidden by default\n if (hideCookieMessage) return null;\n\n return (\n <div className=\"ui-cookie-message\" ref={ref}>\n <p className=\"ui-text-p2 pr-8\">\n <a href={absUrl(\"/privacy\")} className=\"underline\">\n How we use cookies\n </a>{\" \"}\n to improve your experience.\n </p>\n <button\n className=\"ui-btn-secondary mt-3 sm:mt-0 whitespace-nowrap\"\n onClick={handleClose}\n >\n Accept and close\n </button>\n </div>\n );\n};\n\nexport default CookieMessage;\n"],"names":["React","useRef","useEffect","useState","Cookie","_absUrl","COOKIE_EXPIRY","CookieMessage","cookieId","urlBase","ref","hideCookieMessage","setHideCookieMessage","get","isCookieSet","handleClose","set","expires","current","classList","add","setTimeout","absUrl","path","div","className","p","a","href","button","onClick"],"mappings":"AAAA,OAAOA,OAASC,MAAM,CAAEC,SAAS,CAAEC,QAAQ,KAAQ,OAAQ,AAC3D,QAAOC,WAAY,WAAY,AAE/B,QAAOC,YAAa,YAAa,CAEjC,MAAMC,cAAgB,IAOtB,MAAMC,cAAgB,CAAC,CAAEC,QAAQ,CAAEC,OAAO,CAAsB,IAC9D,MAAMC,IAAMT,OAAuB,MACnC,KAAM,CAACU,kBAAmBC,qBAAqB,CAAGT,SAAS,IACzDC,OAAOS,GAAG,CAACL,UAAY,KAAO,OAGhCN,UAAU,KACR,MAAMY,YAAcV,OAAOS,GAAG,CAACL,UAAY,KAAO,MAClD,GAAIG,oBAAsBG,YAAa,CACrCF,qBAAqBE,YACvB,CAEF,EAAG,CAACN,SAAS,EAEb,MAAMO,YAAc,KAClBX,OAAOY,GAAG,CAACR,SAAU,IAAK,CAAES,QAASX,aAAc,EAEnDI,CAAAA,IAAIQ,OAAO,EAAEC,UAAUC,IAAI,YAAa,aACxCC,WAAW,IAAMT,qBAAqB,MAAO,IAC/C,EAEA,MAAMU,OAAS,AAACC,MAAiBlB,QAAQkB,KAAMd,SAG/C,GAAIE,kBAAmB,OAAO,KAE9B,OACE,oBAACa,OAAIC,UAAU,oBAAoBf,IAAKA,KACtC,oBAACgB,KAAED,UAAU,mBACX,oBAACE,KAAEC,KAAMN,OAAO,YAAaG,UAAU,aAAY,sBAE9C,IAAI,+BAGX,oBAACI,UACCJ,UAAU,kDACVK,QAASf,aACV,oBAKP,CAEA,gBAAeR,aAAc"}
|
package/core/Expander.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import React,{useEffect,useRef,useState}from"react";import{throttle}from"es-toolkit/compat";const Expander=({heightThreshold=200,className,fadeClassName,controlsClassName,controlsOpenedLabel,controlsClosedLabel,children})=>{const innerRef=useRef(null);const[showControls,setShowControls]=useState(false);const[contentHeight,setContentHeight]=useState(heightThreshold);const[
|
|
1
|
+
import React,{useEffect,useRef,useState}from"react";import*as RadixCollapsible from"@radix-ui/react-collapsible";import{throttle}from"es-toolkit/compat";import cn from"./utils/cn";const Expander=({heightThreshold=200,className,fadeClassName,controlsClassName,controlsOpenedLabel,controlsClosedLabel,children})=>{const innerRef=useRef(null);const[showControls,setShowControls]=useState(false);const[contentHeight,setContentHeight]=useState(heightThreshold);const[expanded,setExpanded]=useState(false);useEffect(()=>{if(innerRef.current){setContentHeight(innerRef.current.clientHeight)}setShowControls(contentHeight>=heightThreshold)},[contentHeight,heightThreshold]);useEffect(()=>{const onResize=throttle(()=>{if(innerRef.current){setContentHeight(innerRef.current.clientHeight)}},250);window.addEventListener("resize",onResize);return()=>{window.removeEventListener("resize",onResize)}},[]);const height=contentHeight<heightThreshold?"auto":expanded?contentHeight:heightThreshold;return React.createElement(RadixCollapsible.Root,{open:expanded,onOpenChange:setExpanded},React.createElement("div",{style:{height},"data-testid":"expander-container",className:cn("overflow-hidden transition-all relative",className)},showControls&&!expanded&&React.createElement("div",{className:cn("h-16 w-full bg-gradient-to-t from-white to-transparent absolute bottom-0 left-0 right-0",fadeClassName)}),React.createElement("div",{ref:innerRef},children)),showControls&&React.createElement(RadixCollapsible.Trigger,{asChild:true},React.createElement("button",{"data-testid":"expander-controls",className:cn(heightThreshold===0&&!expanded?"":"mt-4","cursor-pointer font-bold text-gui-blue-default-light hover:text-gui-blue-hover-light",controlsClassName)},expanded?controlsOpenedLabel??"View less -":controlsClosedLabel??"View all +")))};export default Expander;
|
|
2
2
|
//# sourceMappingURL=Expander.js.map
|