diff --git a/assets/AiCodeExplainer-CE0_1KFz.js b/assets/AiCodeExplainer-CE0_1KFz.js new file mode 100644 index 0000000000000000000000000000000000000000..3160a941267082dbd41c2dd0473ed338806a67a1 --- /dev/null +++ b/assets/AiCodeExplainer-CE0_1KFz.js @@ -0,0 +1,12 @@ +import{r as s,j as e}from"./react-DKy9e2uO.js";import{e as w,C,L as j,M as S}from"./index-Ck8YGBbR.js";import"./bottleneck-Cpj98o6Y.js";import"./react-dom-CpxHE_eW.js";import"./scheduler-DYLXRpC5.js";import"./idb-Dob3nYDb.js";import"./@google-D80DdW2m.js";import"./marked-CesSW9Du.js";import"./jszip-s56H2EZ-.js";const k=`const bubbleSort = (arr) => { + for (let i = 0; i < arr.length; i++) { + for (let j = 0; j < arr.length - i - 1; j++) { + if (arr[j] > arr[j + 1]) { + [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; + } + } + } + return arr; +};`,L=a=>a.replace(/&/g,"&").replace(//g,">").replace(/\b(const|let|var|function|return|if|for|=>|import|from|export|default)\b/g,'$1').replace(/(\`|'|")(.*?)(\`|'|")/g,'$1$2$3').replace(/(\/\/.*)/g,'$1').replace(/(\{|\}|\(|\)|\[|\])/g,'$1'),F=({initialCode:a})=>{const[n,p]=s.useState(a||k),[t,u]=s.useState(null),[o,f]=s.useState(!1),[d,x]=s.useState(""),[h,g]=s.useState("summary"),c=s.useRef(null),i=s.useRef(null),m=s.useCallback(async r=>{if(!r.trim()){x("Please enter some code to explain.");return}f(!0),x(""),u(null),g("summary");try{const l=await w(r);u(l)}catch(l){const v=l instanceof Error?l.message:"An unknown error occurred.";x(`Failed to get explanation: ${v}`)}finally{f(!1)}},[]);s.useEffect(()=>{a&&(p(a),m(a))},[a,m]);const y=()=>{i.current&&c.current&&(i.current.scrollTop=c.current.scrollTop,i.current.scrollLeft=c.current.scrollLeft)},b=s.useMemo(()=>L(n),[n]),N=()=>{if(!t)return null;switch(h){case"summary":return e.jsx(S,{content:t.summary});case"lineByLine":return e.jsx("div",{className:"space-y-3",children:t.lineByLine.map((r,l)=>e.jsxs("div",{className:"p-3 bg-background rounded-md border border-border",children:[e.jsxs("p",{className:"font-mono text-xs text-primary mb-1",children:["Lines: ",r.lines]}),e.jsx("p",{className:"text-sm",children:r.explanation})]},l))});case"complexity":return e.jsxs("div",{children:[e.jsxs("p",{children:[e.jsx("strong",{children:"Time Complexity:"})," ",e.jsx("span",{className:"font-mono text-amber-600",children:t.complexity.time})]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Space Complexity:"})," ",e.jsx("span",{className:"font-mono text-amber-600",children:t.complexity.space})]})]});case"suggestions":return e.jsx("ul",{className:"list-disc list-inside space-y-2",children:t.suggestions.map((r,l)=>e.jsx("li",{children:r},l))})}};return e.jsxs("div",{className:"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary",children:[e.jsxs("header",{className:"mb-6 flex-shrink-0",children:[e.jsxs("h1",{className:"text-3xl font-bold flex items-center",children:[e.jsx(C,{}),e.jsx("span",{className:"ml-3",children:"AI Code Explainer"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Get a detailed, structured analysis of any code snippet."})]}),e.jsxs("div",{className:"flex-grow flex flex-col lg:flex-row gap-6 min-h-0",children:[e.jsxs("div",{className:"flex flex-col min-h-0 lg:w-1/2",children:[e.jsx("label",{htmlFor:"code-input",className:"text-sm font-medium text-text-secondary mb-2",children:"Your Code"}),e.jsxs("div",{className:"relative flex-grow bg-surface border border-border rounded-md focus-within:ring-2 focus-within:ring-primary overflow-hidden",children:[e.jsx("textarea",{ref:c,id:"code-input",value:n,onChange:r=>p(r.target.value),onScroll:y,placeholder:"Paste your code here...",spellCheck:"false",className:"absolute inset-0 w-full h-full p-4 bg-transparent resize-none font-mono text-sm text-transparent caret-primary outline-none z-10"}),e.jsx("pre",{ref:i,"aria-hidden":"true",className:"absolute inset-0 w-full h-full p-4 font-mono text-sm text-text-primary pointer-events-none z-0 whitespace-pre-wrap overflow-auto no-scrollbar",dangerouslySetInnerHTML:{__html:b+` +`}})]}),e.jsx("div",{className:"mt-4 flex-shrink-0",children:e.jsx("button",{onClick:()=>m(n),disabled:o,className:"btn-primary w-full flex items-center justify-center px-6 py-3",children:o?e.jsx(j,{}):"Analyze Code"})})]}),e.jsxs("div",{className:"flex flex-col min-h-0 lg:w-1/2",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"AI Analysis"}),e.jsxs("div",{className:"relative flex-grow flex flex-col bg-surface border border-border rounded-md overflow-hidden",children:[e.jsx("div",{className:"flex-shrink-0 flex border-b border-border",children:["summary","lineByLine","complexity","suggestions"].map(r=>e.jsx("button",{onClick:()=>g(r),disabled:!t,className:`px-4 py-2 text-sm font-medium capitalize transition-colors ${h===r?"bg-background text-primary font-semibold":"text-text-secondary hover:bg-gray-100 disabled:text-gray-400"}`,children:r.replace(/([A-Z])/g," $1")},r))}),e.jsxs("div",{className:"p-4 flex-grow overflow-y-auto",children:[o&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(j,{})}),d&&e.jsx("p",{className:"text-red-500",children:d}),t&&!o&&N(),!o&&!t&&!d&&e.jsx("div",{className:"text-text-secondary h-full flex items-center justify-center",children:"The analysis will appear here."})]})]})]})]})]})};export{F as AiCodeExplainer}; +//# sourceMappingURL=AiCodeExplainer-CE0_1KFz.js.map diff --git a/assets/AiCodeExplainer-CE0_1KFz.js.map b/assets/AiCodeExplainer-CE0_1KFz.js.map new file mode 100644 index 0000000000000000000000000000000000000000..42dafca334881d67696529dbd4f3239e90f4ae79 --- /dev/null +++ b/assets/AiCodeExplainer-CE0_1KFz.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AiCodeExplainer-CE0_1KFz.js","sources":["../../components/features/AiCodeExplainer.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect, useMemo, useRef } from 'react';\nimport { explainCodeStructured } from '../../services/index.ts';\nimport type { StructuredExplanation } from '../../types.ts';\nimport { CpuChipIcon } from '../icons.tsx';\nimport { MarkdownRenderer, LoadingSpinner } from '../shared/index.tsx';\n\nconst exampleCode = `const bubbleSort = (arr) => {\n for (let i = 0; i < arr.length; i++) {\n for (let j = 0; j < arr.length - i - 1; j++) {\n if (arr[j] > arr[j + 1]) {\n [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];\n }\n }\n }\n return arr;\n};`;\n\ntype ExplanationTab = 'summary' | 'lineByLine' | 'complexity' | 'suggestions';\n\nconst simpleSyntaxHighlight = (code: string) => {\n const escapedCode = code\n .replace(/&/g, '&')\n .replace(//g, '>');\n\n return escapedCode\n .replace(/\\b(const|let|var|function|return|if|for|=>|import|from|export|default)\\b/g, '$1')\n .replace(/(\\`|'|\")(.*?)(\\`|'|\")/g, '$1$2$3')\n .replace(/(\\/\\/.*)/g, '$1')\n .replace(/(\\{|\\}|\\(|\\)|\\[|\\])/g, '$1');\n};\n\nexport const AiCodeExplainer: React.FC<{ initialCode?: string }> = ({ initialCode }) => {\n const [code, setCode] = useState(initialCode || exampleCode);\n const [explanation, setExplanation] = useState(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState('');\n const [activeTab, setActiveTab] = useState('summary');\n const textareaRef = useRef(null);\n const preRef = useRef(null);\n\n const handleExplain = useCallback(async (codeToExplain: string) => {\n if (!codeToExplain.trim()) {\n setError('Please enter some code to explain.');\n return;\n }\n setIsLoading(true);\n setError('');\n setExplanation(null);\n setActiveTab('summary');\n try {\n const result = await explainCodeStructured(codeToExplain);\n setExplanation(result);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to get explanation: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, []);\n \n useEffect(() => {\n if (initialCode) {\n setCode(initialCode);\n handleExplain(initialCode);\n }\n }, [initialCode, handleExplain]);\n\n const handleScroll = () => {\n if (preRef.current && textareaRef.current) {\n preRef.current.scrollTop = textareaRef.current.scrollTop;\n preRef.current.scrollLeft = textareaRef.current.scrollLeft;\n }\n };\n\n const highlightedCode = useMemo(() => simpleSyntaxHighlight(code), [code]);\n\n const renderTabContent = () => {\n if (!explanation) return null;\n switch(activeTab) {\n case 'summary':\n return ;\n case 'lineByLine':\n return (\n
\n {explanation.lineByLine.map((item, index) => (\n
\n

Lines: {item.lines}

\n

{item.explanation}

\n
\n ))}\n
\n );\n case 'complexity':\n return (\n
\n

Time Complexity: {explanation.complexity.time}

\n

Space Complexity: {explanation.complexity.space}

\n
\n );\n case 'suggestions':\n return (\n
    \n {explanation.suggestions.map((item, index) =>
  • {item}
  • )}\n
\n );\n }\n }\n\n return (\n
\n
\n

\n \n AI Code Explainer\n

\n

Get a detailed, structured analysis of any code snippet.

\n
\n
\n \n {/* Left Column: Code Input */}\n
\n \n
\n setCode(e.target.value)}\n onScroll={handleScroll}\n placeholder=\"Paste your code here...\"\n spellCheck=\"false\"\n className=\"absolute inset-0 w-full h-full p-4 bg-transparent resize-none font-mono text-sm text-transparent caret-primary outline-none z-10\"\n />\n
\n                    
\n
\n handleExplain(code)}\n disabled={isLoading}\n className=\"btn-primary w-full flex items-center justify-center px-6 py-3\"\n >\n {isLoading ? : 'Analyze Code'}\n \n
\n
\n\n {/* Right Column: AI Analysis */}\n
\n \n
\n
\n {(['summary', 'lineByLine', 'complexity', 'suggestions'] as ExplanationTab[]).map(tab => (\n \n ))}\n
\n
\n {isLoading &&
}\n {error &&

{error}

}\n {explanation && !isLoading && renderTabContent()}\n {!isLoading && !explanation && !error &&
The analysis will appear here.
}\n
\n
\n
\n
\n
\n );\n};"],"names":["exampleCode","simpleSyntaxHighlight","code","AiCodeExplainer","initialCode","setCode","useState","explanation","setExplanation","isLoading","setIsLoading","error","setError","activeTab","setActiveTab","textareaRef","useRef","preRef","handleExplain","useCallback","codeToExplain","result","explainCodeStructured","err","errorMessage","useEffect","handleScroll","highlightedCode","useMemo","renderTabContent","jsx","MarkdownRenderer","item","index","jsxs","CpuChipIcon","e","LoadingSpinner","tab"],"mappings":"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"} \ No newline at end of file diff --git a/assets/AiCodeMigrator-BXc_JDlt.js b/assets/AiCodeMigrator-BXc_JDlt.js new file mode 100644 index 0000000000000000000000000000000000000000..4e36765a1499ff732df89be160fde7788b545b2c --- /dev/null +++ b/assets/AiCodeMigrator-BXc_JDlt.js @@ -0,0 +1,8 @@ +import{r as s,j as e}from"./react-DKy9e2uO.js";import{z as L,E as A,L as w,M}from"./index-Ck8YGBbR.js";import"./bottleneck-Cpj98o6Y.js";import"./react-dom-CpxHE_eW.js";import"./scheduler-DYLXRpC5.js";import"./idb-Dob3nYDb.js";import"./@google-D80DdW2m.js";import"./marked-CesSW9Du.js";import"./jszip-s56H2EZ-.js";const k=["SASS","CSS","JavaScript","TypeScript","Python","Go","React","Vue","Angular","Tailwind CSS"],E=`// SASS +$primary-color: #333; + +body { + color: $primary-color; + font-family: sans-serif; +}`,V=({inputCode:a,fromLang:o,toLang:l})=>{const[p,g]=s.useState(a||E),[m,h]=s.useState(""),[j,S]=s.useState(o||"SASS"),[b,y]=s.useState(l||"CSS"),[n,N]=s.useState(!1),[x,u]=s.useState(""),i=s.useCallback(async(t,f,r)=>{if(!t.trim()){u("Please enter some code to migrate.");return}N(!0),u(""),h("");try{const c=L(t,f,r);let d="";for await(const C of c)d+=C,h(d)}catch(c){const d=c instanceof Error?c.message:"An unknown error occurred.";u(`Failed to migrate code: ${d}`)}finally{N(!1)}},[]);s.useEffect(()=>{a&&o&&l&&(g(a),S(o),y(l),i(a,o,l))},[a,o,l,i]);const v=({value:t,onChange:f})=>e.jsx("select",{value:t,onChange:r=>f(r.target.value),className:"w-full px-3 py-2 rounded-md bg-surface border border-border",children:k.map(r=>e.jsx("option",{value:r,children:r},r))});return e.jsxs("div",{className:"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary",children:[e.jsxs("header",{className:"mb-6",children:[e.jsxs("h1",{className:"text-3xl font-bold flex items-center",children:[e.jsx(A,{}),e.jsx("span",{className:"ml-3",children:"AI Code Migrator"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Translate code between languages, frameworks, and syntax styles."})]}),e.jsxs("div",{className:"flex-grow flex flex-col min-h-0",children:[e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-6 flex-grow min-h-0",children:[e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary",children:"From:"}),e.jsx(v,{value:j,onChange:S})]}),e.jsx("textarea",{value:p,onChange:t=>g(t.target.value),placeholder:"Paste your source code here...",className:"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm"})]}),e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary",children:"To:"}),e.jsx(v,{value:b,onChange:y})]}),e.jsxs("div",{className:"flex-grow p-1 bg-background border border-border rounded-md overflow-y-auto",children:[n&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(w,{})}),x&&e.jsx("p",{className:"p-4 text-red-500",children:x}),m&&!n&&e.jsx(M,{content:m}),!n&&!m&&!x&&e.jsx("div",{className:"text-text-secondary h-full flex items-center justify-center",children:"Migrated code will appear here."})]})]})]}),e.jsx("button",{onClick:()=>i(p,j,b),disabled:n,className:"btn-primary mt-4 w-full max-w-sm mx-auto flex items-center justify-center px-6 py-3",children:n?e.jsx(w,{}):"Migrate Code"})]})]})};export{V as AiCodeMigrator}; +//# sourceMappingURL=AiCodeMigrator-BXc_JDlt.js.map diff --git a/assets/AiCodeMigrator-BXc_JDlt.js.map b/assets/AiCodeMigrator-BXc_JDlt.js.map new file mode 100644 index 0000000000000000000000000000000000000000..e42fce15c44478f4f6730de7bb821a3592f81db4 --- /dev/null +++ b/assets/AiCodeMigrator-BXc_JDlt.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AiCodeMigrator-BXc_JDlt.js","sources":["../../components/features/AiCodeMigrator.tsx"],"sourcesContent":["\n\nimport React, { useState, useCallback, useEffect } from 'react';\nimport { migrateCodeStream } from '../../services/index.ts';\nimport { ArrowPathIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { MarkdownRenderer } from '../shared/index.tsx';\n\nconst languages = ['SASS', 'CSS', 'JavaScript', 'TypeScript', 'Python', 'Go', 'React', 'Vue', 'Angular', 'Tailwind CSS'];\n\nconst exampleCode = `// SASS\n$primary-color: #333;\n\nbody {\n color: $primary-color;\n font-family: sans-serif;\n}`;\n\nexport const AiCodeMigrator: React.FC<{ inputCode?: string, fromLang?: string, toLang?: string }> = ({ inputCode: initialCode, fromLang: initialFrom, toLang: initialTo }) => {\n const [inputCode, setInputCode] = useState(initialCode || exampleCode);\n const [outputCode, setOutputCode] = useState('');\n const [fromLang, setFromLang] = useState(initialFrom || 'SASS');\n const [toLang, setToLang] = useState(initialTo || 'CSS');\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState('');\n\n const handleMigrate = useCallback(async (code: string, from: string, to: string) => {\n if (!code.trim()) {\n setError('Please enter some code to migrate.');\n return;\n }\n setIsLoading(true);\n setError('');\n setOutputCode('');\n try {\n const stream = migrateCodeStream(code, from, to);\n let fullResponse = '';\n for await (const chunk of stream) {\n fullResponse += chunk;\n setOutputCode(fullResponse);\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to migrate code: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n useEffect(() => {\n if (initialCode && initialFrom && initialTo) {\n setInputCode(initialCode);\n setFromLang(initialFrom);\n setToLang(initialTo);\n handleMigrate(initialCode, initialFrom, initialTo);\n }\n }, [initialCode, initialFrom, initialTo, handleMigrate]);\n\n const LanguageSelector: React.FC<{ value: string, onChange: (val: string) => void }> = ({ value, onChange }) => (\n \n );\n\n return (\n
\n
\n

AI Code Migrator

\n

Translate code between languages, frameworks, and syntax styles.

\n
\n
\n
\n
\n
\n \n \n
\n setInputCode(e.target.value)}\n placeholder=\"Paste your source code here...\"\n className=\"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm\"\n />\n
\n
\n
\n \n \n
\n
\n {isLoading &&
}\n {error &&

{error}

}\n {outputCode && !isLoading && }\n {!isLoading && !outputCode && !error &&
Migrated code will appear here.
}\n
\n
\n
\n handleMigrate(inputCode, fromLang, toLang)}\n disabled={isLoading}\n className=\"btn-primary mt-4 w-full max-w-sm mx-auto flex items-center justify-center px-6 py-3\"\n >\n {isLoading ? : 'Migrate Code'}\n \n
\n
\n );\n};"],"names":["languages","exampleCode","AiCodeMigrator","initialCode","initialFrom","initialTo","inputCode","setInputCode","useState","outputCode","setOutputCode","fromLang","setFromLang","toLang","setToLang","isLoading","setIsLoading","error","setError","handleMigrate","useCallback","code","from","to","stream","migrateCodeStream","fullResponse","chunk","err","errorMessage","useEffect","LanguageSelector","value","onChange","jsx","e","lang","jsxs","ArrowPathIcon","LoadingSpinner","MarkdownRenderer"],"mappings":"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"} \ No newline at end of file diff --git a/assets/AiCodingChallenge-BPl6fZNR.js b/assets/AiCodingChallenge-BPl6fZNR.js new file mode 100644 index 0000000000000000000000000000000000000000..72221fd25a6263cde545e621a01df4be45499d5f --- /dev/null +++ b/assets/AiCodingChallenge-BPl6fZNR.js @@ -0,0 +1,2 @@ +import{r as t,j as e}from"./react-DKy9e2uO.js";import{o as f,B as h,L as m,M as u}from"./index-Ck8YGBbR.js";import"./bottleneck-Cpj98o6Y.js";import"./react-dom-CpxHE_eW.js";import"./scheduler-DYLXRpC5.js";import"./idb-Dob3nYDb.js";import"./@google-D80DdW2m.js";import"./marked-CesSW9Du.js";import"./jszip-s56H2EZ-.js";const v=()=>{const[a,o]=t.useState(""),[s,c]=t.useState(!1),[l,i]=t.useState(""),d=t.useCallback(async()=>{c(!0),i(""),o("");try{const r=f(null);let n="";for await(const x of r)n+=x,o(n)}catch(r){const n=r instanceof Error?r.message:"An unknown error occurred.";i(`Failed to generate challenge: ${n}`)}finally{c(!1)}},[]);return t.useEffect(()=>{d()},[]),e.jsxs("div",{className:"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary",children:[e.jsxs("header",{className:"mb-6 flex justify-between items-center",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-3xl font-bold flex items-center",children:[e.jsx(h,{}),e.jsx("span",{className:"ml-3",children:"AI Coding Challenge Generator"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Generate a unique coding problem to test your skills."})]}),e.jsx("button",{onClick:d,disabled:s,className:"btn-primary flex items-center justify-center px-6 py-3",children:s?e.jsx(m,{}):"Generate New Challenge"})]}),e.jsxs("div",{className:"flex-grow p-4 bg-surface border border-border rounded-md overflow-y-auto",children:[s&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(m,{})}),l&&e.jsx("p",{className:"text-red-500",children:l}),a&&!s&&e.jsx(u,{content:a}),!s&&!a&&!l&&e.jsx("div",{className:"text-text-secondary h-full flex items-center justify-center",children:'Click "Generate New Challenge" to start.'})]})]})};export{v as AiCodingChallenge}; +//# sourceMappingURL=AiCodingChallenge-BPl6fZNR.js.map diff --git a/assets/AiCodingChallenge-BPl6fZNR.js.map b/assets/AiCodingChallenge-BPl6fZNR.js.map new file mode 100644 index 0000000000000000000000000000000000000000..82f4d9417b89ce68733ba9da07da20202698b1a0 --- /dev/null +++ b/assets/AiCodingChallenge-BPl6fZNR.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AiCodingChallenge-BPl6fZNR.js","sources":["../../components/features/AiCodingChallenge.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect } from 'react';\nimport { generateCodingChallengeStream } from '../../services/index.ts';\nimport { BeakerIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { MarkdownRenderer } from '../shared/index.tsx';\n\nexport const AiCodingChallenge: React.FC = () => {\n const [challenge, setChallenge] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState('');\n\n const handleGenerate = useCallback(async () => {\n setIsLoading(true);\n setError('');\n setChallenge('');\n try {\n const stream = generateCodingChallengeStream(null);\n let fullResponse = '';\n for await (const chunk of stream) {\n fullResponse += chunk;\n setChallenge(fullResponse);\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to generate challenge: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n useEffect(() => {\n // Generate a challenge on initial load for a better user experience\n handleGenerate();\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n
\n
\n
\n

\n \n AI Coding Challenge Generator\n

\n

Generate a unique coding problem to test your skills.

\n
\n \n {isLoading ? : 'Generate New Challenge'}\n \n
\n
\n {isLoading && (\n
\n \n
\n )}\n {error &&

{error}

}\n {challenge && !isLoading && (\n \n )}\n {!isLoading && !challenge && !error && (\n
\n Click \"Generate New Challenge\" to start.\n
\n )}\n
\n
\n );\n};"],"names":["AiCodingChallenge","challenge","setChallenge","useState","isLoading","setIsLoading","error","setError","handleGenerate","useCallback","stream","generateCodingChallengeStream","fullResponse","chunk","err","errorMessage","useEffect","jsxs","jsx","BeakerIcon","LoadingSpinner","MarkdownRenderer"],"mappings":"8TAMO,MAAMA,EAA8B,IAAM,CAC7C,KAAM,CAACC,EAAWC,CAAY,EAAIC,EAAAA,SAAiB,EAAE,EAC/C,CAACC,EAAWC,CAAY,EAAIF,EAAAA,SAAkB,EAAK,EACnD,CAACG,EAAOC,CAAQ,EAAIJ,EAAAA,SAAiB,EAAE,EAEvCK,EAAiBC,EAAAA,YAAY,SAAY,CAC3CJ,EAAa,EAAI,EACjBE,EAAS,EAAE,EACXL,EAAa,EAAE,EACf,GAAI,CACA,MAAMQ,EAASC,EAA8B,IAAI,EACjD,IAAIC,EAAe,GACnB,gBAAiBC,KAASH,EACtBE,GAAgBC,EAChBX,EAAaU,CAAY,CAEjC,OAASE,EAAK,CACV,MAAMC,EAAeD,aAAe,MAAQA,EAAI,QAAU,6BAC1DP,EAAS,iCAAiCQ,CAAY,EAAE,CAC5D,QAAA,CACIV,EAAa,EAAK,CACtB,CACJ,EAAG,CAAA,CAAE,EAELW,OAAAA,EAAAA,UAAU,IAAM,CAEZR,EAAA,CAEJ,EAAG,CAAA,CAAE,EAGDS,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,yCACd,SAAA,CAAAA,OAAC,MAAA,CACG,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,uCACV,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAW,EACZD,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,+BAAA,CAA6B,CAAA,EACxD,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,uDAAA,CAAqD,CAAA,EACjG,EACAA,EAAAA,IAAC,SAAA,CACG,QAASV,EACT,SAAUJ,EACV,UAAU,yDAET,SAAAA,EAAYc,EAAAA,IAACE,EAAA,CAAA,CAAe,EAAK,wBAAA,CAAA,CACtC,EACJ,EACAH,EAAAA,KAAC,MAAA,CAAI,UAAU,2EACV,SAAA,CAAAb,SACK,MAAA,CAAI,UAAU,0CACZ,SAAAc,MAACE,IAAe,EACnB,EAEJd,GAASY,EAAAA,IAAC,IAAA,CAAE,UAAU,eAAgB,SAAAZ,EAAM,EAC5CL,GAAa,CAACG,GACXc,EAAAA,IAACG,EAAA,CAAiB,QAASpB,EAAW,EAExC,CAACG,GAAa,CAACH,GAAa,CAACK,GAC3BY,EAAAA,IAAC,MAAA,CAAI,UAAU,8DAA8D,SAAA,0CAAA,CAE7E,CAAA,CAAA,CAER,CAAA,EACJ,CAER"} \ No newline at end of file diff --git a/assets/AiCommitGenerator-C6eo_GuV.js b/assets/AiCommitGenerator-C6eo_GuV.js new file mode 100644 index 0000000000000000000000000000000000000000..44e5a19f8c6b420a534cf8382e2ea41c18f29bb5 --- /dev/null +++ b/assets/AiCommitGenerator-C6eo_GuV.js @@ -0,0 +1,14 @@ +import{r,j as e}from"./react-DKy9e2uO.js";import{b,G as y,L as u,A as N,j as w}from"./index-Ck8YGBbR.js";import"./bottleneck-Cpj98o6Y.js";import"./react-dom-CpxHE_eW.js";import"./scheduler-DYLXRpC5.js";import"./idb-Dob3nYDb.js";import"./@google-D80DdW2m.js";import"./marked-CesSW9Du.js";import"./jszip-s56H2EZ-.js";const v=`diff --git a/src/components/Button.tsx b/src/components/Button.tsx +index 1b2c3d4..5e6f7g8 100644 +--- a/src/components/Button.tsx ++++ b/src/components/Button.tsx +@@ -1,7 +1,7 @@ + import React from 'react'; + + interface ButtonProps { +- text: string; ++ label: string; + onClick: () => void; + } +`,L=({diff:a})=>{const[x,d]=r.useState(a||v),[s,f]=r.useState(""),[t,p]=r.useState(!1),[c,i]=r.useState(""),m=r.useCallback(async n=>{if(!n.trim()){i("Please paste a diff to generate a message.");return}p(!0),i(""),f("");try{const o=b(n);let l="";for await(const j of o)l+=j,f(l)}catch(o){const l=o instanceof Error?o.message:"An unknown error occurred.";i(`Failed to generate message: ${l}`)}finally{p(!1)}},[]);r.useEffect(()=>{a&&(d(a),m(a))},[a,m]);const h=()=>{navigator.clipboard.writeText(s)},g=()=>{w(s,"commit_message.txt","text/plain")};return e.jsxs("div",{className:"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary",children:[e.jsxs("header",{className:"mb-6",children:[e.jsxs("h1",{className:"text-3xl font-bold flex items-center",children:[e.jsx(y,{}),e.jsx("span",{className:"ml-3",children:"AI Commit Message Generator"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Paste your diff and let Gemini craft the perfect commit message."})]}),e.jsxs("div",{className:"flex-grow flex flex-col gap-4 min-h-0",children:[e.jsxs("div",{className:"flex flex-col flex-1 min-h-0",children:[e.jsx("label",{htmlFor:"diff-input",className:"text-sm font-medium text-text-secondary mb-2",children:"Git Diff"}),e.jsx("textarea",{id:"diff-input",value:x,onChange:n=>d(n.target.value),placeholder:"Paste your git diff here...",className:"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm text-text-primary focus:ring-2 focus:ring-primary focus:outline-none"})]}),e.jsx("div",{className:"flex-shrink-0",children:e.jsx("button",{onClick:()=>m(x),disabled:t,className:"btn-primary w-full max-w-xs mx-auto flex items-center justify-center px-6 py-3",children:t?e.jsx(u,{}):"Generate Commit Message"})}),e.jsxs("div",{className:"flex flex-col flex-1 min-h-0",children:[e.jsxs("div",{className:"flex justify-between items-center mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary",children:"Generated Message"}),s&&!t&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:h,className:"px-3 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200",children:"Copy"}),e.jsxs("button",{onClick:g,className:"flex items-center gap-1 px-3 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200",children:[e.jsx(N,{className:"w-4 h-4"})," Download"]})]})]}),e.jsxs("div",{className:"relative flex-grow p-4 bg-surface border border-border rounded-md overflow-y-auto",children:[t&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(u,{})}),c&&e.jsx("p",{className:"text-red-500",children:c}),s&&!t&&e.jsx("pre",{className:"whitespace-pre-wrap font-sans text-text-primary",children:s}),!t&&!s&&!c&&e.jsx("div",{className:"text-text-secondary h-full flex items-center justify-center",children:"The commit message will appear here."})]})]})]})]})};export{L as AiCommitGenerator}; +//# sourceMappingURL=AiCommitGenerator-C6eo_GuV.js.map diff --git a/assets/AiCommitGenerator-C6eo_GuV.js.map b/assets/AiCommitGenerator-C6eo_GuV.js.map new file mode 100644 index 0000000000000000000000000000000000000000..6574378aaa3f6f68d2ae3b8b48d9df4b6ba8d983 --- /dev/null +++ b/assets/AiCommitGenerator-C6eo_GuV.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AiCommitGenerator-C6eo_GuV.js","sources":["../../components/features/AiCommitGenerator.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect } from 'react';\nimport { generateCommitMessageStream, downloadFile } from '../../services/index.ts';\nimport { GitBranchIcon, ArrowDownTrayIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\n\nconst exampleDiff = `diff --git a/src/components/Button.tsx b/src/components/Button.tsx\nindex 1b2c3d4..5e6f7g8 100644\n--- a/src/components/Button.tsx\n+++ b/src/components/Button.tsx\n@@ -1,7 +1,7 @@\n import React from 'react';\n\n interface ButtonProps {\n- text: string;\n+ label: string;\n onClick: () => void;\n }\n`;\n\nexport const AiCommitGenerator: React.FC<{ diff?: string }> = ({ diff: initialDiff }) => {\n const [diff, setDiff] = useState(initialDiff || exampleDiff);\n const [message, setMessage] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState('');\n\n const handleGenerate = useCallback(async (diffToAnalyze: string) => {\n if (!diffToAnalyze.trim()) {\n setError('Please paste a diff to generate a message.');\n return;\n }\n setIsLoading(true);\n setError('');\n setMessage('');\n try {\n const stream = generateCommitMessageStream(diffToAnalyze);\n let fullResponse = '';\n for await (const chunk of stream) {\n fullResponse += chunk;\n setMessage(fullResponse);\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to generate message: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n useEffect(() => {\n if (initialDiff) {\n setDiff(initialDiff);\n handleGenerate(initialDiff);\n }\n }, [initialDiff, handleGenerate]);\n \n const handleCopy = () => {\n navigator.clipboard.writeText(message);\n };\n \n const handleDownload = () => {\n downloadFile(message, 'commit_message.txt', 'text/plain');\n };\n\n return (\n
\n
\n

\n \n AI Commit Message Generator\n

\n

Paste your diff and let Gemini craft the perfect commit message.

\n
\n
\n
\n \n setDiff(e.target.value)}\n placeholder=\"Paste your git diff here...\"\n className=\"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm text-text-primary focus:ring-2 focus:ring-primary focus:outline-none\"\n />\n
\n
\n handleGenerate(diff)}\n disabled={isLoading}\n className=\"btn-primary w-full max-w-xs mx-auto flex items-center justify-center px-6 py-3\"\n >\n {isLoading ? : 'Generate Commit Message'}\n \n
\n
\n
\n \n {message && !isLoading && (\n
\n \n \n
\n )}\n
\n
\n {isLoading && (\n
\n \n
\n )}\n {error &&

{error}

}\n {message && !isLoading && (\n
{message}
\n )}\n {!isLoading && !message && !error && (\n
\n The commit message will appear here.\n
\n )}\n
\n
\n
\n
\n );\n};"],"names":["exampleDiff","AiCommitGenerator","initialDiff","diff","setDiff","useState","message","setMessage","isLoading","setIsLoading","error","setError","handleGenerate","useCallback","diffToAnalyze","stream","generateCommitMessageStream","fullResponse","chunk","err","errorMessage","useEffect","handleCopy","handleDownload","downloadFile","jsxs","jsx","GitBranchIcon","e","LoadingSpinner","ArrowDownTrayIcon"],"mappings":"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"} \ No newline at end of file diff --git a/assets/AiFeatureBuilder-qJcM7Vps.js b/assets/AiFeatureBuilder-qJcM7Vps.js new file mode 100644 index 0000000000000000000000000000000000000000..ab2b701e70fe7c49bbf6d58cd2d26f42b90d7e34 --- /dev/null +++ b/assets/AiFeatureBuilder-qJcM7Vps.js @@ -0,0 +1,8 @@ +import{r,j as e}from"./react-DKy9e2uO.js";import{c as O,g as D,s as I,a as P,b as A,C as $,D as w,B as G,G as B,L as v,d as L,M as N}from"./index-Ck8YGBbR.js";import"./bottleneck-Cpj98o6Y.js";import"./react-dom-CpxHE_eW.js";import"./scheduler-DYLXRpC5.js";import"./idb-Dob3nYDb.js";import"./@google-D80DdW2m.js";import"./marked-CesSW9Du.js";import"./jszip-s56H2EZ-.js";const V=()=>{const[i,S]=r.useState('A simple "Hello World" React component with a button that shows an alert.'),[f,x]=r.useState([]),[p,u]=r.useState(""),[h,b]=r.useState(""),[n,c]=r.useState(null),[d,g]=r.useState(!1),[j,m]=r.useState(""),[o,l]=r.useState("CODE");r.useEffect(()=>{(async()=>{const s=await L();x(s),s.length>0&&c(s[0])})()},[]);const k=r.useCallback(async()=>{if(!i.trim()){m("Please enter a feature description.");return}g(!0),m(""),await O(),x([]),u(""),b(""),c(null),l("CODE");try{const t=await D(i);for(const s of t)await I(s);if(x(t),t.length>0){const s=t.find(a=>a.filePath.endsWith(".tsx")||a.filePath.endsWith(".jsx"));if(c(s||t[0]),s){const a=P(s.content);let C="";for await(const M of a)C+=M,u(C)}const T=t.map(a=>`File: ${a.filePath} + +${a.content}`).join(` +--- +`),E=A(T);let y="";for await(const a of E)y+=a,b(y)}}catch(t){const s=t instanceof Error?t.message:"An unknown error occurred.";m(`Failed to generate feature: ${s}`)}finally{g(!1)}},[i]),F=()=>{switch(o){case"TESTS":return e.jsx(N,{content:p});case"COMMIT":return e.jsx("pre",{className:"w-full h-full p-4 whitespace-pre-wrap font-sans text-sm text-text-primary",children:h});case"CODE":default:return n?e.jsx(N,{content:`\`\`\`tsx +${n.content} +\`\`\``}):e.jsx("div",{className:"flex items-center justify-center h-full text-text-secondary",children:"Select a file to view its content."})}};return e.jsxs("div",{className:"h-full flex flex-col text-text-primary bg-surface",children:[e.jsx("header",{className:"p-4 border-b border-border flex-shrink-0",children:e.jsxs("h1",{className:"text-xl font-bold flex items-center",children:[e.jsx($,{}),e.jsx("span",{className:"ml-3",children:"AI Feature Builder"})]})}),e.jsxs("div",{className:"flex-grow flex min-h-0",children:[e.jsxs("aside",{className:"w-64 bg-surface border-r border-border p-4 flex flex-col",children:[e.jsx("h2",{className:"text-sm font-semibold text-text-secondary mb-2",children:"Generated Files"}),e.jsx("div",{className:"overflow-y-auto space-y-1",children:f.map(t=>e.jsxs("div",{onClick:()=>{c(t),l("CODE")},className:`flex items-center space-x-2 p-2 rounded-md cursor-pointer text-sm ${(n==null?void 0:n.filePath)===t.filePath&&o==="CODE"?"bg-primary/10 text-primary":"hover:bg-gray-100"}`,children:[e.jsx(w,{}),e.jsx("span",{children:t.filePath.split("/").pop()})]},t.filePath))})]}),e.jsxs("main",{className:"flex-1 flex flex-col min-w-0",children:[e.jsxs("div",{className:"flex-grow flex flex-col bg-background",children:[e.jsxs("div",{className:"border-b border-border flex items-center bg-surface",children:[e.jsxs("button",{onClick:()=>l("CODE"),className:`flex items-center gap-2 px-4 py-2 text-sm ${o==="CODE"?"bg-background border-b-2 border-primary text-text-primary":"text-text-secondary hover:bg-gray-50"}`,children:[e.jsx(w,{})," Code"]}),p&&e.jsxs("button",{onClick:()=>l("TESTS"),className:`flex items-center gap-2 px-4 py-2 text-sm ${o==="TESTS"?"bg-background border-b-2 border-primary text-text-primary":"text-text-secondary hover:bg-gray-50"}`,children:[e.jsx(G,{})," Tests"]}),h&&e.jsxs("button",{onClick:()=>l("COMMIT"),className:`flex items-center gap-2 px-4 py-2 text-sm ${o==="COMMIT"?"bg-background border-b-2 border-primary text-text-primary":"text-text-secondary hover:bg-gray-50"}`,children:[e.jsx(B,{})," Commit"]})]}),e.jsx("div",{className:"flex-grow p-2 overflow-auto",children:d&&!f.length?e.jsx("div",{className:"flex justify-center items-center h-full",children:e.jsx(v,{})}):F()})]}),e.jsxs("div",{className:"flex-shrink-0 p-4 border-t border-border bg-surface",children:[e.jsx("textarea",{value:i,onChange:t=>S(t.target.value),placeholder:"e.g., A user profile card with an avatar, name, and bio.",className:"w-full p-2 bg-background border border-border rounded-md resize-none text-sm h-20"}),e.jsx("button",{onClick:k,disabled:d,className:"btn-primary mt-2 w-full flex items-center justify-center gap-2 px-4 py-2",children:d?e.jsxs(e.Fragment,{children:[e.jsx(v,{})," Generating..."]}):"Generate Feature"}),j&&e.jsx("p",{className:"text-red-600 text-xs mt-2 text-center",children:j})]})]})]})]})};export{V as AiFeatureBuilder}; +//# sourceMappingURL=AiFeatureBuilder-qJcM7Vps.js.map diff --git a/assets/AiFeatureBuilder-qJcM7Vps.js.map b/assets/AiFeatureBuilder-qJcM7Vps.js.map new file mode 100644 index 0000000000000000000000000000000000000000..352773b53ecd7a0fa188f74bb200b6ed0c951fd8 --- /dev/null +++ b/assets/AiFeatureBuilder-qJcM7Vps.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AiFeatureBuilder-qJcM7Vps.js","sources":["../../components/features/AiFeatureBuilder.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect } from 'react';\nimport type { GeneratedFile } from '../../types.ts';\nimport { generateFeature, generateUnitTestsStream, generateCommitMessageStream, saveFile, getAllFiles, clearAllFiles } from '../../services/index.ts';\nimport { CpuChipIcon, DocumentTextIcon, BeakerIcon, GitBranchIcon } from '../icons.tsx';\nimport { LoadingSpinner, MarkdownRenderer } from '../shared/index.tsx';\n\ntype ActiveTab = 'CODE' | 'TESTS' | 'COMMIT';\n\nexport const AiFeatureBuilder: React.FC = () => {\n const [prompt, setPrompt] = useState('A simple \"Hello World\" React component with a button that shows an alert.');\n const [generatedFiles, setGeneratedFiles] = useState([]);\n const [unitTests, setUnitTests] = useState('');\n const [commitMessage, setCommitMessage] = useState('');\n const [selectedFile, setSelectedFile] = useState(null);\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState('');\n const [activeTab, setActiveTab] = useState('CODE');\n \n useEffect(() => {\n const loadFiles = async () => {\n const files = await getAllFiles();\n setGeneratedFiles(files);\n if (files.length > 0) setSelectedFile(files[0]);\n };\n loadFiles();\n }, []);\n\n const handleGenerate = useCallback(async () => {\n if (!prompt.trim()) { setError('Please enter a feature description.'); return; }\n setIsLoading(true);\n setError('');\n await clearAllFiles(); // Start fresh for each generation\n setGeneratedFiles([]);\n setUnitTests('');\n setCommitMessage('');\n setSelectedFile(null);\n setActiveTab('CODE');\n\n try {\n const resultFiles = await generateFeature(prompt);\n for (const file of resultFiles) { await saveFile(file); }\n setGeneratedFiles(resultFiles);\n\n if (resultFiles.length > 0) {\n const componentFile = resultFiles.find(f => f.filePath.endsWith('.tsx') || f.filePath.endsWith('.jsx'));\n setSelectedFile(componentFile || resultFiles[0]);\n\n if (componentFile) {\n const testStream = generateUnitTestsStream(componentFile.content);\n let tests = '';\n for await (const chunk of testStream) { tests += chunk; setUnitTests(tests); }\n }\n\n const diffContext = resultFiles.map(f => `File: ${f.filePath}\\n\\n${f.content}`).join('\\n---\\n');\n const commitStream = generateCommitMessageStream(diffContext);\n let commit = '';\n for await (const chunk of commitStream) { commit += chunk; setCommitMessage(commit); }\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to generate feature: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, [prompt]);\n \n const renderContent = () => {\n switch (activeTab) {\n case 'TESTS': return ;\n case 'COMMIT': return
{commitMessage}
;\n case 'CODE':\n default:\n return selectedFile ? :
Select a file to view its content.
;\n }\n }\n\n return (\n
\n
\n

AI Feature Builder

\n
\n\n
\n \n\n
\n
\n
\n \n {unitTests && }\n {commitMessage && }\n
\n
\n {isLoading && !generatedFiles.length ?
: renderContent()}\n
\n
\n \n
\n