admin08077 commited on
Commit
d4e36ef
·
verified ·
1 Parent(s): e025d49

Upload 204 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. assets/AiCodeExplainer-CE0_1KFz.js +12 -0
  2. assets/AiCodeExplainer-CE0_1KFz.js.map +1 -0
  3. assets/AiCodeMigrator-BXc_JDlt.js +8 -0
  4. assets/AiCodeMigrator-BXc_JDlt.js.map +1 -0
  5. assets/AiCodingChallenge-BPl6fZNR.js +2 -0
  6. assets/AiCodingChallenge-BPl6fZNR.js.map +1 -0
  7. assets/AiCommitGenerator-C6eo_GuV.js +14 -0
  8. assets/AiCommitGenerator-C6eo_GuV.js.map +1 -0
  9. assets/AiFeatureBuilder-qJcM7Vps.js +8 -0
  10. assets/AiFeatureBuilder-qJcM7Vps.js.map +1 -0
  11. assets/AiImageGenerator-BYtIGaX5.js +2 -0
  12. assets/AiImageGenerator-BYtIGaX5.js.map +1 -0
  13. assets/AiPullRequestAssistant-auR4G7bZ.js +25 -0
  14. assets/AiPullRequestAssistant-auR4G7bZ.js.map +1 -0
  15. assets/AiStyleTransfer-DgF2wuEc.js +4 -0
  16. assets/AiStyleTransfer-DgF2wuEc.js.map +1 -0
  17. assets/AiUnitTestGenerator-Bawbasui.js +9 -0
  18. assets/AiUnitTestGenerator-Bawbasui.js.map +1 -0
  19. assets/AsyncCallTreeViewer-D_OioVtl.js +23 -0
  20. assets/AsyncCallTreeViewer-D_OioVtl.js.map +1 -0
  21. assets/AudioToCode-DhNgjuEC.js +2 -0
  22. assets/AudioToCode-DhNgjuEC.js.map +1 -0
  23. assets/ChangelogGenerator-DhzKekFT.js +13 -0
  24. assets/ChangelogGenerator-DhzKekFT.js.map +1 -0
  25. assets/CodeDiffGhost-Q06Vp3v6.js +18 -0
  26. assets/CodeDiffGhost-Q06Vp3v6.js.map +1 -0
  27. assets/CodeFormatter-B5J1ivDG.js +8 -0
  28. assets/CodeFormatter-B5J1ivDG.js.map +1 -0
  29. assets/CodeReviewBot-2UF5jWqT.js +12 -0
  30. assets/CodeReviewBot-2UF5jWqT.js.map +1 -0
  31. assets/CodeSpellChecker-BolIHiVP.js +6 -0
  32. assets/CodeSpellChecker-BolIHiVP.js.map +1 -0
  33. assets/ColorPaletteGenerator-Cvsu53-R.js +2 -0
  34. assets/ColorPaletteGenerator-Cvsu53-R.js.map +1 -0
  35. assets/CronJobBuilder-DxMd1_TG.js +2 -0
  36. assets/CronJobBuilder-DxMd1_TG.js.map +1 -0
  37. assets/CssGridEditor-Tggo3uo4.js +7 -0
  38. assets/CssGridEditor-Tggo3uo4.js.map +1 -0
  39. assets/DigitalWhiteboard-mqmKu9Bh.js +3 -0
  40. assets/DigitalWhiteboard-mqmKu9Bh.js.map +1 -0
  41. assets/JsonTreeNavigator-wiByc32v.js +13 -0
  42. assets/JsonTreeNavigator-wiByc32v.js.map +1 -0
  43. assets/LogicFlowBuilder-iHo46zDC.js +2 -0
  44. assets/LogicFlowBuilder-iHo46zDC.js.map +1 -0
  45. assets/MarkdownSlides-JjWHLefE.js +24 -0
  46. assets/MarkdownSlides-JjWHLefE.js.map +1 -0
  47. assets/MetaTagEditor-uPETDQxa.js +17 -0
  48. assets/MetaTagEditor-uPETDQxa.js.map +1 -0
  49. assets/NetworkVisualizer-Cx-AAdTT.js +2 -0
  50. assets/NetworkVisualizer-Cx-AAdTT.js.map +1 -0
assets/AiCodeExplainer-CE0_1KFz.js ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 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) => {
2
+ for (let i = 0; i < arr.length; i++) {
3
+ for (let j = 0; j < arr.length - i - 1; j++) {
4
+ if (arr[j] > arr[j + 1]) {
5
+ [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
6
+ }
7
+ }
8
+ }
9
+ return arr;
10
+ };`,L=a=>a.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\b(const|let|var|function|return|if|for|=>|import|from|export|default)\b/g,'<span class="text-indigo-600 font-semibold">$1</span>').replace(/(\`|'|")(.*?)(\`|'|")/g,'<span class="text-emerald-700">$1$2$3</span>').replace(/(\/\/.*)/g,'<span class="text-gray-500 italic">$1</span>').replace(/(\{|\}|\(|\)|\[|\])/g,'<span class="text-gray-600">$1</span>'),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+`
11
+ `}})]}),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};
12
+ //# sourceMappingURL=AiCodeExplainer-CE0_1KFz.js.map
assets/AiCodeExplainer-CE0_1KFz.js.map ADDED
@@ -0,0 +1 @@
 
 
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, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;');\n\n return escapedCode\n .replace(/\\b(const|let|var|function|return|if|for|=>|import|from|export|default)\\b/g, '<span class=\"text-indigo-600 font-semibold\">$1</span>')\n .replace(/(\\`|'|\")(.*?)(\\`|'|\")/g, '<span class=\"text-emerald-700\">$1$2$3</span>')\n .replace(/(\\/\\/.*)/g, '<span class=\"text-gray-500 italic\">$1</span>')\n .replace(/(\\{|\\}|\\(|\\)|\\[|\\])/g, '<span class=\"text-gray-600\">$1</span>');\n};\n\nexport const AiCodeExplainer: React.FC<{ initialCode?: string }> = ({ initialCode }) => {\n const [code, setCode] = useState<string>(initialCode || exampleCode);\n const [explanation, setExplanation] = useState<StructuredExplanation | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n const [activeTab, setActiveTab] = useState<ExplanationTab>('summary');\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const preRef = useRef<HTMLPreElement>(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 <MarkdownRenderer content={explanation.summary} />;\n case 'lineByLine':\n return (\n <div className=\"space-y-3\">\n {explanation.lineByLine.map((item, index) => (\n <div key={index} className=\"p-3 bg-background rounded-md border border-border\">\n <p className=\"font-mono text-xs text-primary mb-1\">Lines: {item.lines}</p>\n <p className=\"text-sm\">{item.explanation}</p>\n </div>\n ))}\n </div>\n );\n case 'complexity':\n return (\n <div>\n <p><strong>Time Complexity:</strong> <span className=\"font-mono text-amber-600\">{explanation.complexity.time}</span></p>\n <p><strong>Space Complexity:</strong> <span className=\"font-mono text-amber-600\">{explanation.complexity.space}</span></p>\n </div>\n );\n case 'suggestions':\n return (\n <ul className=\"list-disc list-inside space-y-2\">\n {explanation.suggestions.map((item, index) => <li key={index}>{item}</li>)}\n </ul>\n );\n }\n }\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6 flex-shrink-0\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <CpuChipIcon />\n <span className=\"ml-3\">AI Code Explainer</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Get a detailed, structured analysis of any code snippet.</p>\n </header>\n <div className=\"flex-grow flex flex-col lg:flex-row gap-6 min-h-0\">\n \n {/* Left Column: Code Input */}\n <div className=\"flex flex-col min-h-0 lg:w-1/2\">\n <label htmlFor=\"code-input\" className=\"text-sm font-medium text-text-secondary mb-2\">Your Code</label>\n <div className=\"relative flex-grow bg-surface border border-border rounded-md focus-within:ring-2 focus-within:ring-primary overflow-hidden\">\n <textarea\n ref={textareaRef}\n id=\"code-input\"\n value={code}\n onChange={(e) => 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 <pre \n ref={preRef}\n aria-hidden=\"true\"\n 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\"\n dangerouslySetInnerHTML={{ __html: highlightedCode + '\\n' }}\n />\n </div>\n <div className=\"mt-4 flex-shrink-0\">\n <button\n onClick={() => handleExplain(code)}\n disabled={isLoading}\n className=\"btn-primary w-full flex items-center justify-center px-6 py-3\"\n >\n {isLoading ? <LoadingSpinner/> : 'Analyze Code'}\n </button>\n </div>\n </div>\n\n {/* Right Column: AI Analysis */}\n <div className=\"flex flex-col min-h-0 lg:w-1/2\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">AI Analysis</label>\n <div className=\"relative flex-grow flex flex-col bg-surface border border-border rounded-md overflow-hidden\">\n <div className=\"flex-shrink-0 flex border-b border-border\">\n {(['summary', 'lineByLine', 'complexity', 'suggestions'] as ExplanationTab[]).map(tab => (\n <button key={tab} onClick={() => setActiveTab(tab)} disabled={!explanation}\n className={`px-4 py-2 text-sm font-medium capitalize transition-colors ${activeTab === tab ? 'bg-background text-primary font-semibold' : 'text-text-secondary hover:bg-gray-100 disabled:text-gray-400'}`}>\n {tab.replace(/([A-Z])/g, ' $1')}\n </button>\n ))}\n </div>\n <div className=\"p-4 flex-grow overflow-y-auto\">\n {isLoading && <div className=\"flex items-center justify-center h-full\"><LoadingSpinner /></div>}\n {error && <p className=\"text-red-500\">{error}</p>}\n {explanation && !isLoading && renderTabContent()}\n {!isLoading && !explanation && !error && <div className=\"text-text-secondary h-full flex items-center justify-center\">The analysis will appear here.</div>}\n </div>\n </div>\n </div>\n </div>\n </div>\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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"}
assets/AiCodeMigrator-BXc_JDlt.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ 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
2
+ $primary-color: #333;
3
+
4
+ body {
5
+ color: $primary-color;
6
+ font-family: sans-serif;
7
+ }`,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};
8
+ //# sourceMappingURL=AiCodeMigrator-BXc_JDlt.js.map
assets/AiCodeMigrator-BXc_JDlt.js.map ADDED
@@ -0,0 +1 @@
 
 
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<string>(initialCode || exampleCode);\n const [outputCode, setOutputCode] = useState<string>('');\n const [fromLang, setFromLang] = useState(initialFrom || 'SASS');\n const [toLang, setToLang] = useState(initialTo || 'CSS');\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\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 <select value={value} onChange={e => onChange(e.target.value)} className=\"w-full px-3 py-2 rounded-md bg-surface border border-border\">\n {languages.map(lang => <option key={lang} value={lang}>{lang}</option>)}\n </select>\n );\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\"><ArrowPathIcon /><span className=\"ml-3\">AI Code Migrator</span></h1>\n <p className=\"text-text-secondary mt-1\">Translate code between languages, frameworks, and syntax styles.</p>\n </header>\n <div className=\"flex-grow flex flex-col min-h-0\">\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6 flex-grow min-h-0\">\n <div className=\"flex flex-col h-full\">\n <div className=\"mb-2\">\n <label className=\"text-sm font-medium text-text-secondary\">From:</label>\n <LanguageSelector value={fromLang} onChange={setFromLang} />\n </div>\n <textarea\n value={inputCode}\n onChange={(e) => 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 </div>\n <div className=\"flex flex-col h-full\">\n <div className=\"mb-2\">\n <label className=\"text-sm font-medium text-text-secondary\">To:</label>\n <LanguageSelector value={toLang} onChange={setToLang} />\n </div>\n <div className=\"flex-grow p-1 bg-background border border-border rounded-md overflow-y-auto\">\n {isLoading && <div className=\"flex items-center justify-center h-full\"><LoadingSpinner /></div>}\n {error && <p className=\"p-4 text-red-500\">{error}</p>}\n {outputCode && !isLoading && <MarkdownRenderer content={outputCode} />}\n {!isLoading && !outputCode && !error && <div className=\"text-text-secondary h-full flex items-center justify-center\">Migrated code will appear here.</div>}\n </div>\n </div>\n </div>\n <button\n onClick={() => 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 ? <LoadingSpinner /> : 'Migrate Code'}\n </button>\n </div>\n </div>\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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"}
assets/AiCodingChallenge-BPl6fZNR.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ 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};
2
+ //# sourceMappingURL=AiCodingChallenge-BPl6fZNR.js.map
assets/AiCodingChallenge-BPl6fZNR.js.map ADDED
@@ -0,0 +1 @@
 
 
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<string>('');\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\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 <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6 flex justify-between items-center\">\n <div>\n <h1 className=\"text-3xl font-bold flex items-center\">\n <BeakerIcon />\n <span className=\"ml-3\">AI Coding Challenge Generator</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Generate a unique coding problem to test your skills.</p>\n </div>\n <button\n onClick={handleGenerate}\n disabled={isLoading}\n className=\"btn-primary flex items-center justify-center px-6 py-3\"\n >\n {isLoading ? <LoadingSpinner /> : 'Generate New Challenge'}\n </button>\n </header>\n <div className=\"flex-grow p-4 bg-surface border border-border rounded-md overflow-y-auto\">\n {isLoading && (\n <div className=\"flex items-center justify-center h-full\">\n <LoadingSpinner />\n </div>\n )}\n {error && <p className=\"text-red-500\">{error}</p>}\n {challenge && !isLoading && (\n <MarkdownRenderer content={challenge} />\n )}\n {!isLoading && !challenge && !error && (\n <div className=\"text-text-secondary h-full flex items-center justify-center\">\n Click \"Generate New Challenge\" to start.\n </div>\n )}\n </div>\n </div>\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"}
assets/AiCommitGenerator-C6eo_GuV.js ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 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
2
+ index 1b2c3d4..5e6f7g8 100644
3
+ --- a/src/components/Button.tsx
4
+ +++ b/src/components/Button.tsx
5
+ @@ -1,7 +1,7 @@
6
+ import React from 'react';
7
+
8
+ interface ButtonProps {
9
+ - text: string;
10
+ + label: string;
11
+ onClick: () => void;
12
+ }
13
+ `,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};
14
+ //# sourceMappingURL=AiCommitGenerator-C6eo_GuV.js.map
assets/AiCommitGenerator-C6eo_GuV.js.map ADDED
@@ -0,0 +1 @@
 
 
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<string>(initialDiff || exampleDiff);\n const [message, setMessage] = useState<string>('');\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\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 <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <GitBranchIcon />\n <span className=\"ml-3\">AI Commit Message Generator</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Paste your diff and let Gemini craft the perfect commit message.</p>\n </header>\n <div className=\"flex-grow flex flex-col gap-4 min-h-0\">\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label htmlFor=\"diff-input\" className=\"text-sm font-medium text-text-secondary mb-2\">Git Diff</label>\n <textarea\n id=\"diff-input\"\n value={diff}\n onChange={(e) => 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 </div>\n <div className=\"flex-shrink-0\">\n <button\n onClick={() => 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 ? <LoadingSpinner /> : 'Generate Commit Message'}\n </button>\n </div>\n <div className=\"flex flex-col flex-1 min-h-0\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"text-sm font-medium text-text-secondary\">Generated Message</label>\n {message && !isLoading && (\n <div className=\"flex items-center gap-2\">\n <button onClick={handleCopy} className=\"px-3 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200\">Copy</button>\n <button onClick={handleDownload} className=\"flex items-center gap-1 px-3 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200\">\n <ArrowDownTrayIcon className=\"w-4 h-4\" /> Download\n </button>\n </div>\n )}\n </div>\n <div className=\"relative flex-grow p-4 bg-surface border border-border rounded-md overflow-y-auto\">\n {isLoading && (\n <div className=\"flex items-center justify-center h-full\">\n <LoadingSpinner />\n </div>\n )}\n {error && <p className=\"text-red-500\">{error}</p>}\n {message && !isLoading && (\n <pre className=\"whitespace-pre-wrap font-sans text-text-primary\">{message}</pre>\n )}\n {!isLoading && !message && !error && (\n <div className=\"text-text-secondary h-full flex items-center justify-center\">\n The commit message will appear here.\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\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":"2TAKA,MAAMA,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcPC,EAAiD,CAAC,CAAE,KAAMC,KAAkB,CACrF,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAiBH,GAAeF,CAAW,EAC7D,CAACM,EAASC,CAAU,EAAIF,EAAAA,SAAiB,EAAE,EAC3C,CAACG,EAAWC,CAAY,EAAIJ,EAAAA,SAAkB,EAAK,EACnD,CAACK,EAAOC,CAAQ,EAAIN,EAAAA,SAAiB,EAAE,EAEvCO,EAAiBC,cAAY,MAAOC,GAA0B,CAChE,GAAI,CAACA,EAAc,OAAQ,CACvBH,EAAS,4CAA4C,EACrD,MACJ,CACAF,EAAa,EAAI,EACjBE,EAAS,EAAE,EACXJ,EAAW,EAAE,EACb,GAAI,CACA,MAAMQ,EAASC,EAA4BF,CAAa,EACxD,IAAIG,EAAe,GACnB,gBAAiBC,KAASH,EACtBE,GAAgBC,EAChBX,EAAWU,CAAY,CAE/B,OAASE,EAAK,CACV,MAAMC,EAAeD,aAAe,MAAQA,EAAI,QAAU,6BAC1DR,EAAS,+BAA+BS,CAAY,EAAE,CAC1D,QAAA,CACIX,EAAa,EAAK,CACtB,CACJ,EAAG,CAAA,CAAE,EAELY,EAAAA,UAAU,IAAM,CACRnB,IACAE,EAAQF,CAAW,EACnBU,EAAeV,CAAW,EAElC,EAAG,CAACA,EAAaU,CAAc,CAAC,EAEhC,MAAMU,EAAa,IAAM,CACrB,UAAU,UAAU,UAAUhB,CAAO,CACzC,EAEMiB,EAAiB,IAAM,CACzBC,EAAalB,EAAS,qBAAsB,YAAY,CAC5D,EAEA,OACImB,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,uCACV,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAc,EACfD,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,6BAAA,CAA2B,CAAA,EACtD,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,kEAAA,CAAgE,CAAA,EAC5G,EACAD,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACX,SAAA,CAAAC,MAAC,QAAA,CAAM,QAAQ,aAAa,UAAU,+CAA+C,SAAA,WAAQ,EAC7FA,EAAAA,IAAC,WAAA,CACG,GAAG,aACH,MAAOvB,EACP,SAAWyB,GAAMxB,EAAQwB,EAAE,OAAO,KAAK,EACvC,YAAY,8BACZ,UAAU,6JAAA,CAAA,CACd,EACJ,EACAF,EAAAA,IAAC,MAAA,CAAI,UAAU,gBACX,SAAAA,EAAAA,IAAC,SAAA,CACG,QAAS,IAAMd,EAAeT,CAAI,EAClC,SAAUK,EACV,UAAU,iFAET,SAAAA,EAAYkB,EAAAA,IAACG,EAAA,CAAA,CAAe,EAAK,yBAAA,CAAA,EAE1C,EACAJ,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACX,SAAA,CAAAC,EAAAA,IAAC,QAAA,CAAM,UAAU,0CAA0C,SAAA,oBAAiB,EAC3EpB,GAAW,CAACE,GACTiB,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACX,SAAA,CAAAC,MAAC,SAAA,CAAO,QAASJ,EAAY,UAAU,6DAA6D,SAAA,OAAI,EACxGG,EAAAA,KAAC,SAAA,CAAO,QAASF,EAAgB,UAAU,qFACvC,SAAA,CAAAG,EAAAA,IAACI,EAAA,CAAkB,UAAU,SAAA,CAAU,EAAE,WAAA,CAAA,CAC7C,CAAA,CAAA,CACJ,CAAA,EAER,EACAL,EAAAA,KAAC,MAAA,CAAI,UAAU,oFACV,SAAA,CAAAjB,SACK,MAAA,CAAI,UAAU,0CACZ,SAAAkB,MAACG,IAAe,EACnB,EAEJnB,GAASgB,EAAAA,IAAC,IAAA,CAAE,UAAU,eAAgB,SAAAhB,EAAM,EAC5CJ,GAAW,CAACE,SACT,MAAA,CAAI,UAAU,kDAAmD,SAAAF,EAAQ,EAE3E,CAACE,GAAa,CAACF,GAAW,CAACI,GACzBgB,EAAAA,IAAC,MAAA,CAAI,UAAU,8DAA8D,SAAA,sCAAA,CAE7E,CAAA,CAAA,CAER,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,EACJ,CAER"}
assets/AiFeatureBuilder-qJcM7Vps.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ 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}
2
+
3
+ ${a.content}`).join(`
4
+ ---
5
+ `),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
6
+ ${n.content}
7
+ \`\`\``}):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};
8
+ //# sourceMappingURL=AiFeatureBuilder-qJcM7Vps.js.map
assets/AiFeatureBuilder-qJcM7Vps.js.map ADDED
@@ -0,0 +1 @@
 
 
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<string>('A simple \"Hello World\" React component with a button that shows an alert.');\n const [generatedFiles, setGeneratedFiles] = useState<GeneratedFile[]>([]);\n const [unitTests, setUnitTests] = useState<string>('');\n const [commitMessage, setCommitMessage] = useState<string>('');\n const [selectedFile, setSelectedFile] = useState<GeneratedFile | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n const [activeTab, setActiveTab] = useState<ActiveTab>('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 <MarkdownRenderer content={unitTests} />;\n case 'COMMIT': return <pre className=\"w-full h-full p-4 whitespace-pre-wrap font-sans text-sm text-text-primary\">{commitMessage}</pre>;\n case 'CODE':\n default:\n return selectedFile ? <MarkdownRenderer content={`\\`\\`\\`tsx\\n${selectedFile.content}\\n\\`\\`\\``} /> : <div className=\"flex items-center justify-center h-full text-text-secondary\">Select a file to view its content.</div>;\n }\n }\n\n return (\n <div className=\"h-full flex flex-col text-text-primary bg-surface\">\n <header className=\"p-4 border-b border-border flex-shrink-0\">\n <h1 className=\"text-xl font-bold flex items-center\"><CpuChipIcon /><span className=\"ml-3\">AI Feature Builder</span></h1>\n </header>\n\n <div className=\"flex-grow flex min-h-0\">\n <aside className=\"w-64 bg-surface border-r border-border p-4 flex flex-col\">\n <h2 className=\"text-sm font-semibold text-text-secondary mb-2\">Generated Files</h2>\n <div className=\"overflow-y-auto space-y-1\">\n {generatedFiles.map(file => (\n <div key={file.filePath} onClick={() => { setSelectedFile(file); setActiveTab('CODE'); }} className={`flex items-center space-x-2 p-2 rounded-md cursor-pointer text-sm ${selectedFile?.filePath === file.filePath && activeTab === 'CODE' ? 'bg-primary/10 text-primary' : 'hover:bg-gray-100'}`}>\n <DocumentTextIcon /><span>{file.filePath.split('/').pop()}</span>\n </div>\n ))}\n </div>\n </aside>\n\n <main className=\"flex-1 flex flex-col min-w-0\">\n <div className=\"flex-grow flex flex-col bg-background\">\n <div className=\"border-b border-border flex items-center bg-surface\">\n <button onClick={() => setActiveTab('CODE')} className={`flex items-center gap-2 px-4 py-2 text-sm ${activeTab === 'CODE' ? 'bg-background border-b-2 border-primary text-text-primary' : 'text-text-secondary hover:bg-gray-50'}`}><DocumentTextIcon /> Code</button>\n {unitTests && <button onClick={() => setActiveTab('TESTS')} className={`flex items-center gap-2 px-4 py-2 text-sm ${activeTab === 'TESTS' ? 'bg-background border-b-2 border-primary text-text-primary' : 'text-text-secondary hover:bg-gray-50'}`}><BeakerIcon /> Tests</button>}\n {commitMessage && <button onClick={() => setActiveTab('COMMIT')} className={`flex items-center gap-2 px-4 py-2 text-sm ${activeTab === 'COMMIT' ? 'bg-background border-b-2 border-primary text-text-primary' : 'text-text-secondary hover:bg-gray-50'}`}><GitBranchIcon /> Commit</button>}\n </div>\n <div className=\"flex-grow p-2 overflow-auto\">\n {isLoading && !generatedFiles.length ? <div className=\"flex justify-center items-center h-full\"><LoadingSpinner/></div> : renderContent()}\n </div>\n </div>\n \n <div className=\"flex-shrink-0 p-4 border-t border-border bg-surface\">\n <textarea value={prompt} onChange={(e) => setPrompt(e.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\"/>\n <button onClick={handleGenerate} disabled={isLoading} className=\"btn-primary mt-2 w-full flex items-center justify-center gap-2 px-4 py-2\">\n {isLoading ? <><LoadingSpinner /> Generating...</> : 'Generate Feature'}\n </button>\n {error && <p className=\"text-red-600 text-xs mt-2 text-center\">{error}</p>}\n </div>\n </main>\n </div>\n </div>\n );\n};"],"names":["AiFeatureBuilder","prompt","setPrompt","useState","generatedFiles","setGeneratedFiles","unitTests","setUnitTests","commitMessage","setCommitMessage","selectedFile","setSelectedFile","isLoading","setIsLoading","error","setError","activeTab","setActiveTab","useEffect","files","getAllFiles","handleGenerate","useCallback","clearAllFiles","resultFiles","generateFeature","file","saveFile","componentFile","f","testStream","generateUnitTestsStream","tests","chunk","diffContext","commitStream","generateCommitMessageStream","commit","err","errorMessage","renderContent","jsx","MarkdownRenderer","jsxs","CpuChipIcon","DocumentTextIcon","BeakerIcon","GitBranchIcon","LoadingSpinner","e","Fragment"],"mappings":"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"}
assets/AiImageGenerator-BYtIGaX5.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as o,j as e}from"./react-DKy9e2uO.js";import{J as f,K as b,L as m,S as j,A as y}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 p=["A majestic lion wearing a crown, painted in the style of Van Gogh.","A futuristic cityscape on another planet with two moons in the sky.","A cozy, magical library inside a giant tree.","A surreal image of a ship sailing on a sea of clouds.","An astronaut riding a space-themed bicycle on the moon."],E=()=>{const[t,i]=o.useState("A photorealistic image of a futuristic city at sunset, with flying cars."),[s,c]=o.useState(null),[a,d]=o.useState(!1),[n,l]=o.useState(""),u=o.useCallback(async()=>{if(!t.trim()){l("Please enter a prompt to generate an image.");return}d(!0),l(""),c(null);try{const r=await f(t);c(r)}catch(r){const h=r instanceof Error?r.message:"An unknown error occurred.";l(`Failed to generate image: ${h}`)}finally{d(!1)}},[t]),g=()=>{const r=p[Math.floor(Math.random()*p.length)];i(r)},x=()=>{if(!s)return;const r=document.createElement("a");r.href=s,r.download=`${t.slice(0,30).replace(/\s/g,"_")}.png`,document.body.appendChild(r),r.click(),document.body.removeChild(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(b,{}),e.jsx("span",{className:"ml-3",children:"AI Image Generator"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Generate stunning, high-quality images from text prompts using Imagen 3."})]}),e.jsxs("div",{className:"flex flex-col gap-4 mb-4",children:[e.jsx("label",{htmlFor:"prompt-input",className:"text-sm font-medium text-text-secondary",children:"Your Prompt"}),e.jsx("textarea",{id:"prompt-input",value:t,onChange:r=>i(r.target.value),placeholder:"e.g., A cute cat wearing a wizard hat",className:"w-full p-3 rounded-md bg-surface border border-border focus:ring-2 focus:ring-primary focus:outline-none resize-y",rows:3}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{onClick:u,disabled:a,className:"btn-primary w-full flex items-center justify-center px-6 py-3",children:a?e.jsx(m,{}):"Generate Image"}),e.jsx("button",{onClick:g,disabled:a,className:"px-4 py-3 bg-surface border border-border rounded-md hover:bg-gray-100 transition-colors",title:"Surprise Me!",children:e.jsx(j,{})})]})]}),e.jsxs("div",{className:"flex-grow flex items-center justify-center bg-background border-2 border-dashed border-border rounded-lg p-4 relative overflow-auto",children:[a&&e.jsx(m,{}),n&&e.jsx("p",{className:"text-red-500 text-center",children:n}),s&&!a&&e.jsxs(e.Fragment,{children:[e.jsx("img",{src:s,alt:t||"Generated by AI",className:"max-w-full max-h-full object-contain rounded-md shadow-lg"}),e.jsx("button",{onClick:x,className:"absolute top-4 right-4 p-2 bg-black/30 text-white rounded-full hover:bg-black/50 backdrop-blur-sm",title:"Download Image",children:e.jsx(y,{})})]}),!a&&!s&&!n&&e.jsx("div",{className:"text-center text-text-secondary",children:e.jsx("p",{children:"Your generated image will appear here."})})]})]})};export{E as AiImageGenerator};
2
+ //# sourceMappingURL=AiImageGenerator-BYtIGaX5.js.map
assets/AiImageGenerator-BYtIGaX5.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiImageGenerator-BYtIGaX5.js","sources":["../../components/features/AiImageGenerator.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { generateImage } from '../../services/index.ts';\nimport { ImageGeneratorIcon, SparklesIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { ArrowDownTrayIcon } from '../icons.tsx';\n\nconst surprisePrompts = [\n 'A majestic lion wearing a crown, painted in the style of Van Gogh.',\n 'A futuristic cityscape on another planet with two moons in the sky.',\n 'A cozy, magical library inside a giant tree.',\n 'A surreal image of a ship sailing on a sea of clouds.',\n 'An astronaut riding a space-themed bicycle on the moon.',\n];\n\nexport const AiImageGenerator: React.FC = () => {\n const [prompt, setPrompt] = useState<string>('A photorealistic image of a futuristic city at sunset, with flying cars.');\n const [imageUrl, setImageUrl] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n\n const handleGenerate = useCallback(async () => {\n if (!prompt.trim()) {\n setError('Please enter a prompt to generate an image.');\n return;\n }\n setIsLoading(true);\n setError('');\n setImageUrl(null);\n try {\n const resultUrl = await generateImage(prompt);\n setImageUrl(resultUrl);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to generate image: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, [prompt]);\n\n const handleSurpriseMe = () => {\n const randomPrompt = surprisePrompts[Math.floor(Math.random() * surprisePrompts.length)];\n setPrompt(randomPrompt);\n };\n \n const handleDownload = () => {\n if (!imageUrl) return;\n const link = document.createElement('a');\n link.href = imageUrl;\n link.download = `${prompt.slice(0, 30).replace(/\\s/g, '_')}.png`;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n }\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <ImageGeneratorIcon />\n <span className=\"ml-3\">AI Image Generator</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Generate stunning, high-quality images from text prompts using Imagen 3.</p>\n </header>\n \n <div className=\"flex flex-col gap-4 mb-4\">\n <label htmlFor=\"prompt-input\" className=\"text-sm font-medium text-text-secondary\">Your Prompt</label>\n <textarea\n id=\"prompt-input\"\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n placeholder=\"e.g., A cute cat wearing a wizard hat\"\n className=\"w-full p-3 rounded-md bg-surface border border-border focus:ring-2 focus:ring-primary focus:outline-none resize-y\"\n rows={3}\n />\n <div className=\"flex gap-2\">\n <button\n onClick={handleGenerate}\n disabled={isLoading}\n className=\"btn-primary w-full flex items-center justify-center px-6 py-3\"\n >\n {isLoading ? <LoadingSpinner /> : 'Generate Image'}\n </button>\n <button\n onClick={handleSurpriseMe}\n disabled={isLoading}\n className=\"px-4 py-3 bg-surface border border-border rounded-md hover:bg-gray-100 transition-colors\"\n title=\"Surprise Me!\"\n >\n <SparklesIcon />\n </button>\n </div>\n </div>\n\n <div className=\"flex-grow flex items-center justify-center bg-background border-2 border-dashed border-border rounded-lg p-4 relative overflow-auto\">\n {isLoading && <LoadingSpinner />}\n {error && <p className=\"text-red-500 text-center\">{error}</p>}\n {imageUrl && !isLoading && (\n <>\n <img src={imageUrl} alt={prompt || \"Generated by AI\"} className=\"max-w-full max-h-full object-contain rounded-md shadow-lg\" />\n <button \n onClick={handleDownload}\n className=\"absolute top-4 right-4 p-2 bg-black/30 text-white rounded-full hover:bg-black/50 backdrop-blur-sm\"\n title=\"Download Image\"\n >\n <ArrowDownTrayIcon />\n </button>\n </>\n )}\n {!isLoading && !imageUrl && !error && (\n <div className=\"text-center text-text-secondary\">\n <p>Your generated image will appear here.</p>\n </div>\n )}\n </div>\n </div>\n );\n};"],"names":["surprisePrompts","AiImageGenerator","prompt","setPrompt","useState","imageUrl","setImageUrl","isLoading","setIsLoading","error","setError","handleGenerate","useCallback","resultUrl","generateImage","err","errorMessage","handleSurpriseMe","randomPrompt","handleDownload","link","jsxs","jsx","ImageGeneratorIcon","e","LoadingSpinner","SparklesIcon","Fragment","ArrowDownTrayIcon"],"mappings":"qUAMA,MAAMA,EAAkB,CACpB,qEACA,sEACA,+CACA,wDACA,yDACJ,EAEaC,EAA6B,IAAM,CAC5C,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAiB,0EAA0E,EACjH,CAACC,EAAUC,CAAW,EAAIF,EAAAA,SAAwB,IAAI,EACtD,CAACG,EAAWC,CAAY,EAAIJ,EAAAA,SAAkB,EAAK,EACnD,CAACK,EAAOC,CAAQ,EAAIN,EAAAA,SAAiB,EAAE,EAEvCO,EAAiBC,EAAAA,YAAY,SAAY,CAC3C,GAAI,CAACV,EAAO,OAAQ,CAChBQ,EAAS,6CAA6C,EACtD,MACJ,CACAF,EAAa,EAAI,EACjBE,EAAS,EAAE,EACXJ,EAAY,IAAI,EAChB,GAAI,CACA,MAAMO,EAAY,MAAMC,EAAcZ,CAAM,EAC5CI,EAAYO,CAAS,CACzB,OAASE,EAAK,CACV,MAAMC,EAAeD,aAAe,MAAQA,EAAI,QAAU,6BAC1DL,EAAS,6BAA6BM,CAAY,EAAE,CACxD,QAAA,CACIR,EAAa,EAAK,CACtB,CACJ,EAAG,CAACN,CAAM,CAAC,EAELe,EAAmB,IAAM,CAC3B,MAAMC,EAAelB,EAAgB,KAAK,MAAM,KAAK,OAAA,EAAWA,EAAgB,MAAM,CAAC,EACvFG,EAAUe,CAAY,CAC1B,EAEMC,EAAiB,IAAM,CACzB,GAAI,CAACd,EAAU,OACf,MAAMe,EAAO,SAAS,cAAc,GAAG,EACvCA,EAAK,KAAOf,EACZe,EAAK,SAAW,GAAGlB,EAAO,MAAM,EAAG,EAAE,EAAE,QAAQ,MAAO,GAAG,CAAC,OAC1D,SAAS,KAAK,YAAYkB,CAAI,EAC9BA,EAAK,MAAA,EACL,SAAS,KAAK,YAAYA,CAAI,CAClC,EAEA,OACIC,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,uCACV,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAmB,EACpBD,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,oBAAA,CAAkB,CAAA,EAC7C,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,0EAAA,CAAwE,CAAA,EACpH,EAEAD,EAAAA,KAAC,MAAA,CAAI,UAAU,2BACX,SAAA,CAAAC,MAAC,QAAA,CAAM,QAAQ,eAAe,UAAU,0CAA0C,SAAA,cAAW,EAC7FA,EAAAA,IAAC,WAAA,CACG,GAAG,eACH,MAAOpB,EACP,SAAWsB,GAAMrB,EAAUqB,EAAE,OAAO,KAAK,EACzC,YAAY,wCACZ,UAAU,oHACV,KAAM,CAAA,CAAA,EAEVH,EAAAA,KAAC,MAAA,CAAI,UAAU,aACX,SAAA,CAAAC,EAAAA,IAAC,SAAA,CACG,QAASX,EACT,SAAUJ,EACV,UAAU,gEAET,SAAAA,EAAYe,EAAAA,IAACG,EAAA,CAAA,CAAe,EAAK,gBAAA,CAAA,EAEtCH,EAAAA,IAAC,SAAA,CACG,QAASL,EACT,SAAUV,EACV,UAAU,2FACV,MAAM,eAEN,eAACmB,EAAA,CAAA,CAAa,CAAA,CAAA,CAClB,CAAA,CACJ,CAAA,EACJ,EAEAL,EAAAA,KAAC,MAAA,CAAI,UAAU,sIACV,SAAA,CAAAd,SAAckB,EAAA,EAAe,EAC7BhB,GAASa,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA4B,SAAAb,EAAM,EACxDJ,GAAY,CAACE,GACVc,EAAAA,KAAAM,EAAAA,SAAA,CACI,SAAA,CAAAL,MAAC,OAAI,IAAKjB,EAAU,IAAKH,GAAU,kBAAmB,UAAU,4DAA4D,EAC5HoB,EAAAA,IAAC,SAAA,CACC,QAASH,EACT,UAAU,oGACV,MAAM,iBAEJ,eAACS,EAAA,CAAA,CAAkB,CAAA,CAAA,CACvB,EACJ,EAEH,CAACrB,GAAa,CAACF,GAAY,CAACI,GACzBa,EAAAA,IAAC,MAAA,CAAI,UAAU,kCACX,SAAAA,EAAAA,IAAC,IAAA,CAAE,kDAAsC,CAAA,CAC7C,CAAA,CAAA,CAER,CAAA,EACJ,CAER"}
assets/AiPullRequestAssistant-auR4G7bZ.js ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as t,j as e}from"./react-DKy9e2uO.js";import{c as k}from"./diff-DcU-ljqw.js";import{q as $,v as T,L as A}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 P=`function Greeter(props) {
2
+ return <h1>Hello, {props.name}!</h1>;
3
+ }`,B=`function Greeter({ name, enthusiasmLevel = 1 }) {
4
+ const punctuation = '!'.repeat(enthusiasmLevel);
5
+ return <h1>Hello, {name}{punctuation}</h1>;
6
+ }`,O=()=>{const[a,v]=t.useState(P),[o,N]=t.useState(B),[x,u]=t.useState(!1),[p,l]=t.useState(""),[n,h]=t.useState(""),[c,f]=t.useState(""),[b,L]=t.useState("feature/new-logic"),[g,R]=t.useState("main"),[i,y]=t.useState("feat"),[d,G]=t.useState(""),[m,w]=t.useState(`1.
7
+ 2.
8
+ 3.`),S=t.useCallback(async()=>{if(!a.trim()&&!o.trim()){l("Please provide code to generate a summary.");return}u(!0),l("");try{const s=k("component.tsx",a,o),r=await $(s);h(r.title),f(`${r.summary}
9
+
10
+ **Key Changes:**
11
+ ${r.changes.map(C=>`- ${C}`).join(`
12
+ `)}`)}catch(s){const r=s instanceof Error?s.message:"An unknown error occurred.";l(`Failed to generate summary: ${r}`)}finally{u(!1)}},[a,o]),j=t.useMemo(()=>`
13
+ # ${i}: ${n}
14
+ ${d?`
15
+ **Closes:** ${d}
16
+ `:""}
17
+ **Branch:** \`${b}\` -> \`${g}\`
18
+
19
+ ## Description
20
+ ${c}
21
+
22
+ ## Testing Steps
23
+ ${m}
24
+ `.trim(),[n,c,b,g,i,d,m]);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(T,{}),e.jsx("span",{className:"ml-3",children:"AI Pull Request Assistant"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Generate a PR summary from code changes and populate a full template."})]}),e.jsxs("div",{className:"flex-grow grid grid-cols-1 lg:grid-cols-2 gap-6 min-h-0",children:[e.jsxs("div",{className:"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:"before-code",className:"text-sm font-medium text-text-secondary mb-2",children:"Before"}),e.jsx("textarea",{id:"before-code",value:a,onChange:s=>v(s.target.value),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 flex-1 min-h-0",children:[e.jsx("label",{htmlFor:"after-code",className:"text-sm font-medium text-text-secondary mb-2",children:"After"}),e.jsx("textarea",{id:"after-code",value:o,onChange:s=>N(s.target.value),className:"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm"})]}),e.jsx("button",{onClick:S,disabled:x,className:"btn-primary w-full flex items-center justify-center px-6 py-3",children:x?e.jsx(A,{}):"Generate Title & Description"}),p&&e.jsx("p",{className:"text-red-500 text-xs text-center",children:p})]}),e.jsxs("div",{className:"flex flex-col gap-4 min-h-0",children:[e.jsxs("form",{className:"flex flex-col gap-2 overflow-y-auto pr-2 bg-surface border border-border p-4 rounded-lg h-1/2",children:[e.jsxs("div",{className:"flex gap-2",children:[e.jsxs("div",{className:"w-1/4",children:[e.jsx("label",{className:"block text-xs",children:"Type"}),e.jsxs("select",{value:i,onChange:s=>y(s.target.value),className:"w-full mt-1 p-1 rounded bg-background border border-border text-sm",children:[e.jsx("option",{children:"feat"}),e.jsx("option",{children:"fix"}),e.jsx("option",{children:"chore"}),e.jsx("option",{children:"docs"}),e.jsx("option",{children:"refactor"})]})]}),e.jsxs("div",{className:"w-3/4",children:[e.jsx("label",{className:"block text-xs",children:"Title"}),e.jsx("input",{type:"text",value:n,onChange:s=>h(s.target.value),className:"w-full mt-1 p-1 rounded bg-background border border-border text-sm"})]})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs",children:"Description"}),e.jsx("textarea",{value:c,onChange:s=>f(s.target.value),className:"w-full mt-1 p-1 rounded bg-background border border-border resize-y h-24 text-sm"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-xs",children:"Testing Steps"}),e.jsx("textarea",{value:m,onChange:s=>w(s.target.value),className:"w-full mt-1 p-1 rounded bg-background border border-border resize-y h-16 text-sm"})]})]}),e.jsxs("div",{className:"flex flex-col h-1/2",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:"Markdown Preview"}),e.jsx("button",{onClick:()=>navigator.clipboard.writeText(j),className:"px-3 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200",children:"Copy Markdown"})]}),e.jsx("div",{className:"relative flex-grow",children:e.jsx("pre",{className:"w-full h-full bg-background border border-border p-4 rounded-md text-sm overflow-auto whitespace-pre-wrap",children:j})})]})]})]})]})};export{O as AiPullRequestAssistant};
25
+ //# sourceMappingURL=AiPullRequestAssistant-auR4G7bZ.js.map
assets/AiPullRequestAssistant-auR4G7bZ.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiPullRequestAssistant-auR4G7bZ.js","sources":["../../components/features/AiPullRequestAssistant.tsx"],"sourcesContent":["import React, { useState, useMemo, useCallback } from 'react';\nimport * as Diff from 'diff';\nimport { generatePrSummaryStructured } from '../../services/index.ts';\nimport type { StructuredPrSummary } from '../../types.ts';\nimport { AiPullRequestAssistantIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\n\nconst exampleBefore = `function Greeter(props) {\n return <h1>Hello, {props.name}!</h1>;\n}`;\nconst exampleAfter = `function Greeter({ name, enthusiasmLevel = 1 }) {\n const punctuation = '!'.repeat(enthusiasmLevel);\n return <h1>Hello, {name}{punctuation}</h1>;\n}`;\n\nexport const AiPullRequestAssistant: React.FC = () => {\n const [beforeCode, setBeforeCode] = useState<string>(exampleBefore);\n const [afterCode, setAfterCode] = useState<string>(exampleAfter);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n\n // Form state\n const [title, setTitle] = useState('');\n const [description, setDescription] = useState('');\n const [fromBranch, setFromBranch] = useState('feature/new-logic');\n const [toBranch, setToBranch] = useState('main');\n const [changeType, setChangeType] = useState('feat');\n const [relatedIssue, setRelatedIssue] = useState('');\n const [testingSteps, setTestingSteps] = useState('1. \\n2. \\n3.');\n\n const handleGenerateSummary = useCallback(async () => {\n if (!beforeCode.trim() && !afterCode.trim()) {\n setError('Please provide code to generate a summary.');\n return;\n }\n setIsLoading(true);\n setError('');\n \n try {\n const diff = Diff.createPatch('component.tsx', beforeCode, afterCode);\n const result: StructuredPrSummary = await generatePrSummaryStructured(diff);\n setTitle(result.title);\n setDescription(`${result.summary}\\n\\n**Key Changes:**\\n${result.changes.map(c => `- ${c}`).join('\\n')}`);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to generate summary: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, [beforeCode, afterCode]);\n\n const markdownPreview = useMemo(() => {\n return `\n# ${changeType}: ${title}\n${relatedIssue ? `\\n**Closes:** ${relatedIssue}\\n` : ''}\n**Branch:** \\`${fromBranch}\\` -> \\`${toBranch}\\`\n\n## Description\n${description}\n\n## Testing Steps\n${testingSteps}\n `.trim();\n }, [title, description, fromBranch, toBranch, changeType, relatedIssue, testingSteps]);\n \n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <AiPullRequestAssistantIcon />\n <span className=\"ml-3\">AI Pull Request Assistant</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Generate a PR summary from code changes and populate a full template.</p>\n </header>\n <div className=\"flex-grow grid grid-cols-1 lg:grid-cols-2 gap-6 min-h-0\">\n {/* Left side: Inputs and Generator */}\n <div className=\"flex flex-col gap-4 min-h-0\">\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label htmlFor=\"before-code\" className=\"text-sm font-medium text-text-secondary mb-2\">Before</label>\n <textarea id=\"before-code\" value={beforeCode} onChange={e => setBeforeCode(e.target.value)} className=\"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm\" />\n </div>\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label htmlFor=\"after-code\" className=\"text-sm font-medium text-text-secondary mb-2\">After</label>\n <textarea id=\"after-code\" value={afterCode} onChange={e => setAfterCode(e.target.value)} className=\"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm\" />\n </div>\n <button onClick={handleGenerateSummary} disabled={isLoading} className=\"btn-primary w-full flex items-center justify-center px-6 py-3\">\n {isLoading ? <LoadingSpinner /> : 'Generate Title & Description'}\n </button>\n {error && <p className=\"text-red-500 text-xs text-center\">{error}</p>}\n </div>\n\n {/* Right side: Form and Preview */}\n <div className=\"flex flex-col gap-4 min-h-0\">\n <form className=\"flex flex-col gap-2 overflow-y-auto pr-2 bg-surface border border-border p-4 rounded-lg h-1/2\">\n <div className=\"flex gap-2\">\n <div className=\"w-1/4\"><label className=\"block text-xs\">Type</label><select value={changeType} onChange={e => setChangeType(e.target.value)} className=\"w-full mt-1 p-1 rounded bg-background border border-border text-sm\"><option>feat</option><option>fix</option><option>chore</option><option>docs</option><option>refactor</option></select></div>\n <div className=\"w-3/4\"><label className=\"block text-xs\">Title</label><input type=\"text\" value={title} onChange={e => setTitle(e.target.value)} className=\"w-full mt-1 p-1 rounded bg-background border border-border text-sm\"/></div>\n </div>\n <div><label className=\"block text-xs\">Description</label><textarea value={description} onChange={e => setDescription(e.target.value)} className=\"w-full mt-1 p-1 rounded bg-background border border-border resize-y h-24 text-sm\"/></div>\n <div><label className=\"block text-xs\">Testing Steps</label><textarea value={testingSteps} onChange={e => setTestingSteps(e.target.value)} className=\"w-full mt-1 p-1 rounded bg-background border border-border resize-y h-16 text-sm\"/></div>\n </form>\n <div className=\"flex flex-col h-1/2\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"text-sm font-medium text-text-secondary\">Markdown Preview</label>\n <button onClick={() => navigator.clipboard.writeText(markdownPreview)} className=\"px-3 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200\">Copy Markdown</button>\n </div>\n <div className=\"relative flex-grow\"><pre className=\"w-full h-full bg-background border border-border p-4 rounded-md text-sm overflow-auto whitespace-pre-wrap\">{markdownPreview}</pre></div>\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["exampleBefore","exampleAfter","AiPullRequestAssistant","beforeCode","setBeforeCode","useState","afterCode","setAfterCode","isLoading","setIsLoading","error","setError","title","setTitle","description","setDescription","fromBranch","setFromBranch","toBranch","setToBranch","changeType","setChangeType","relatedIssue","setRelatedIssue","testingSteps","setTestingSteps","handleGenerateSummary","useCallback","diff","Diff.createPatch","result","generatePrSummaryStructured","c","err","errorMessage","markdownPreview","useMemo","jsxs","jsx","AiPullRequestAssistantIcon","e","LoadingSpinner"],"mappings":"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"}
assets/AiStyleTransfer-DgF2wuEc.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ import{r as s,j as e}from"./react-DKy9e2uO.js";import{t as y,S as j,L as x,M as b}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 g="function my_func(x,y){return x+y;}",N=`- Use camelCase for function names.
2
+ - Add a space after commas in argument lists.
3
+ - Use semicolons at the end of statements.`,E=()=>{const[r,f]=s.useState(g),[a,u]=s.useState(N),[l,d]=s.useState(""),[o,m]=s.useState(!1),[i,c]=s.useState(""),p=s.useCallback(async()=>{if(!r.trim()||!a.trim()){c("Please provide both code and a style guide.");return}m(!0),c(""),d("");try{const t=y({code:r,styleGuide:a});let n="";for await(const h of t)n+=h,d(n)}catch(t){const n=t instanceof Error?t.message:"An unknown error occurred.";c(`Failed to transfer style: ${n}`)}finally{m(!1)}},[r,a]);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(j,{}),e.jsx("span",{className:"ml-3",children:"AI Code Style Transfer"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Rewrite code to match a specific style guide using AI."})]}),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:"input-code",className:"text-sm font-medium text-text-secondary mb-2",children:"Original Code"}),e.jsx("textarea",{id:"input-code",value:r,onChange:t=>f(t.target.value),className:"flex-grow p-4 bg-surface border border-border rounded-md resize-y font-mono text-sm"})]}),e.jsxs("div",{className:"flex flex-col flex-1 min-h-0",children:[e.jsx("label",{htmlFor:"style-guide",className:"text-sm font-medium text-text-secondary mb-2",children:"Style Guide"}),e.jsx("textarea",{id:"style-guide",value:a,onChange:t=>u(t.target.value),className:"flex-grow p-4 bg-surface border border-border rounded-md resize-y font-mono text-sm"})]}),e.jsx("div",{className:"flex-shrink-0",children:e.jsx("button",{onClick:p,disabled:o,className:"btn-primary w-full max-w-xs mx-auto flex items-center justify-center px-6 py-3",children:o?e.jsx(x,{}):"Rewrite Code"})}),e.jsxs("div",{className:"flex flex-col flex-1 min-h-0",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"Rewritten Code"}),e.jsxs("div",{className:"flex-grow p-1 bg-background border border-border rounded-md overflow-y-auto",children:[o&&!l&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(x,{})}),i&&e.jsx("p",{className:"p-4 text-red-500",children:i}),l&&e.jsx(b,{content:l}),!o&&!l&&!i&&e.jsx("div",{className:"text-text-secondary h-full flex items-center justify-center",children:"Rewritten code will appear here."})]})]})]})]})};export{E as AiStyleTransfer};
4
+ //# sourceMappingURL=AiStyleTransfer-DgF2wuEc.js.map
assets/AiStyleTransfer-DgF2wuEc.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiStyleTransfer-DgF2wuEc.js","sources":["../../components/features/AiStyleTransfer.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { transferCodeStyleStream } from '../../services/index.ts';\nimport { SparklesIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { MarkdownRenderer } from '../shared/index.tsx';\n\nconst exampleCode = `function my_func(x,y){return x+y;}`;\nconst exampleStyleGuide = `- Use camelCase for function names.\n- Add a space after commas in argument lists.\n- Use semicolons at the end of statements.`;\n\nexport const AiStyleTransfer: React.FC = () => {\n const [inputCode, setInputCode] = useState<string>(exampleCode);\n const [styleGuide, setStyleGuide] = useState<string>(exampleStyleGuide);\n const [outputCode, setOutputCode] = useState<string>('');\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n\n const handleGenerate = useCallback(async () => {\n if (!inputCode.trim() || !styleGuide.trim()) {\n setError('Please provide both code and a style guide.');\n return;\n }\n setIsLoading(true);\n setError('');\n setOutputCode('');\n try {\n const stream = transferCodeStyleStream({ code: inputCode, styleGuide });\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 transfer style: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, [inputCode, styleGuide]);\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <SparklesIcon />\n <span className=\"ml-3\">AI Code Style Transfer</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Rewrite code to match a specific style guide using AI.</p>\n </header>\n <div className=\"flex-grow flex flex-col gap-4 min-h-0\">\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label htmlFor=\"input-code\" className=\"text-sm font-medium text-text-secondary mb-2\">Original Code</label>\n <textarea\n id=\"input-code\"\n value={inputCode}\n onChange={(e) => setInputCode(e.target.value)}\n className=\"flex-grow p-4 bg-surface border border-border rounded-md resize-y font-mono text-sm\"\n />\n </div>\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label htmlFor=\"style-guide\" className=\"text-sm font-medium text-text-secondary mb-2\">Style Guide</label>\n <textarea\n id=\"style-guide\"\n value={styleGuide}\n onChange={(e) => setStyleGuide(e.target.value)}\n className=\"flex-grow p-4 bg-surface border border-border rounded-md resize-y font-mono text-sm\"\n />\n </div>\n <div className=\"flex-shrink-0\">\n <button\n onClick={handleGenerate}\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 ? <LoadingSpinner /> : 'Rewrite Code'}\n </button>\n </div>\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">Rewritten Code</label>\n <div className=\"flex-grow p-1 bg-background border border-border rounded-md overflow-y-auto\">\n {isLoading && !outputCode && <div className=\"flex items-center justify-center h-full\"><LoadingSpinner /></div>}\n {error && <p className=\"p-4 text-red-500\">{error}</p>}\n {outputCode && <MarkdownRenderer content={outputCode} />}\n {!isLoading && !outputCode && !error && <div className=\"text-text-secondary h-full flex items-center justify-center\">Rewritten code will appear here.</div>}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["exampleCode","exampleStyleGuide","AiStyleTransfer","inputCode","setInputCode","useState","styleGuide","setStyleGuide","outputCode","setOutputCode","isLoading","setIsLoading","error","setError","handleGenerate","useCallback","stream","transferCodeStyleStream","fullResponse","chunk","err","errorMessage","jsxs","jsx","SparklesIcon","e","LoadingSpinner","MarkdownRenderer"],"mappings":"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"}
assets/AiUnitTestGenerator-Bawbasui.js ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import{r as a,j as e}from"./react-DKy9e2uO.js";import{a as h,B as g,L as m,j,A as b,M as y}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 N=`import React from 'react';
2
+
3
+ export const Greeting = ({ name }) => {
4
+ if (!name) {
5
+ return <div>Hello, Guest!</div>;
6
+ }
7
+ return <div>Hello, {name}!</div>;
8
+ };`,E=()=>{const[n,f]=a.useState(N),[s,i]=a.useState(""),[r,d]=a.useState(!1),[l,c]=a.useState(""),p=a.useCallback(async()=>{if(!n.trim()){c("Please enter some code to generate tests for.");return}d(!0),c(""),i("");try{const t=h(n);let o="";for await(const u of t)o+=u,i(o)}catch(t){const o=t instanceof Error?t.message:"An unknown error occurred.";c(`Failed to generate tests: ${o}`)}finally{d(!1)}},[n]),x=t=>t.replace(/^```(?:\w+\n)?/,"").replace(/```$/,"");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(g,{}),e.jsx("span",{className:"ml-3",children:"AI Unit Test Generator"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Provide a function or component and let AI write the tests."})]}),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:"code-input",className:"text-sm font-medium text-text-secondary mb-2",children:"Source Code"}),e.jsx("textarea",{id:"code-input",value:n,onChange:t=>f(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 focus:ring-2 focus:ring-primary focus:outline-none"})]}),e.jsx("div",{className:"flex-shrink-0",children:e.jsx("button",{onClick:p,disabled:r,className:"btn-primary w-full max-w-xs mx-auto flex items-center justify-center px-6 py-3",children:r?e.jsx(m,{}):"Generate Unit Tests"})}),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 Tests"}),s&&!r&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{onClick:()=>navigator.clipboard.writeText(x(s)),className:"px-3 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200",children:"Copy Code"}),e.jsxs("button",{onClick:()=>j(x(s),"tests.tsx","text/typescript"),className:"flex items-center gap-1 px-3 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200",children:[e.jsx(b,{className:"w-4 h-4"})," Download"]})]})]}),e.jsxs("div",{className:"flex-grow p-1 bg-background border border-border rounded-md overflow-y-auto",children:[r&&!s&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(m,{})}),l&&e.jsx("p",{className:"p-4 text-red-500",children:l}),s&&e.jsx(y,{content:s}),!r&&!s&&!l&&e.jsx("div",{className:"text-text-secondary h-full flex items-center justify-center",children:"The generated tests will appear here."})]})]})]})]})};export{E as AiUnitTestGenerator};
9
+ //# sourceMappingURL=AiUnitTestGenerator-Bawbasui.js.map
assets/AiUnitTestGenerator-Bawbasui.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiUnitTestGenerator-Bawbasui.js","sources":["../../components/features/AiUnitTestGenerator.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { generateUnitTestsStream, downloadFile } from '../../services/index.ts';\nimport { BeakerIcon, ArrowDownTrayIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { MarkdownRenderer } from '../shared/index.tsx';\n\nconst exampleCode = `import React from 'react';\n\nexport const Greeting = ({ name }) => {\n if (!name) {\n return <div>Hello, Guest!</div>;\n }\n return <div>Hello, {name}!</div>;\n};`;\n\nexport const AiUnitTestGenerator: React.FC = () => {\n const [code, setCode] = useState<string>(exampleCode);\n const [tests, setTests] = useState<string>('');\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n\n const handleGenerate = useCallback(async () => {\n if (!code.trim()) {\n setError('Please enter some code to generate tests for.');\n return;\n }\n setIsLoading(true);\n setError('');\n setTests('');\n try {\n const stream = generateUnitTestsStream(code);\n let fullResponse = '';\n for await (const chunk of stream) {\n fullResponse += chunk;\n setTests(fullResponse);\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to generate tests: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, [code]);\n \n const cleanCodeForDownload = (markdown: string) => {\n return markdown.replace(/^```(?:\\w+\\n)?/, '').replace(/```$/, '');\n }\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <BeakerIcon />\n <span className=\"ml-3\">AI Unit Test Generator</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Provide a function or component and let AI write the tests.</p>\n </header>\n <div className=\"flex-grow flex flex-col gap-4 min-h-0\">\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label htmlFor=\"code-input\" className=\"text-sm font-medium text-text-secondary mb-2\">Source Code</label>\n <textarea\n id=\"code-input\"\n value={code}\n onChange={(e) => setCode(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 focus:ring-2 focus:ring-primary focus:outline-none\"\n />\n </div>\n <div className=\"flex-shrink-0\">\n <button\n onClick={handleGenerate}\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 ? <LoadingSpinner /> : 'Generate Unit Tests'}\n </button>\n </div>\n <div className=\"flex flex-col flex-1 min-h-0\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"text-sm font-medium text-text-secondary\">Generated Tests</label>\n {tests && !isLoading && (\n <div className=\"flex items-center gap-2\">\n <button onClick={() => navigator.clipboard.writeText(cleanCodeForDownload(tests))} className=\"px-3 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200\">Copy Code</button>\n <button onClick={() => downloadFile(cleanCodeForDownload(tests), 'tests.tsx', 'text/typescript')} className=\"flex items-center gap-1 px-3 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200\">\n <ArrowDownTrayIcon className=\"w-4 h-4\" /> Download\n </button>\n </div>\n )}\n </div>\n <div className=\"flex-grow p-1 bg-background border border-border rounded-md overflow-y-auto\">\n {isLoading && !tests && (\n <div className=\"flex items-center justify-center h-full\">\n <LoadingSpinner />\n </div>\n )}\n {error && <p className=\"p-4 text-red-500\">{error}</p>}\n {tests && <MarkdownRenderer content={tests} />}\n {!isLoading && !tests && !error && (\n <div className=\"text-text-secondary h-full flex items-center justify-center\">\n The generated tests will appear here.\n </div>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["exampleCode","AiUnitTestGenerator","code","setCode","useState","tests","setTests","isLoading","setIsLoading","error","setError","handleGenerate","useCallback","stream","generateUnitTestsStream","fullResponse","chunk","err","errorMessage","cleanCodeForDownload","markdown","jsxs","jsx","BeakerIcon","e","LoadingSpinner","downloadFile","ArrowDownTrayIcon","MarkdownRenderer"],"mappings":"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"}
assets/AsyncCallTreeViewer-D_OioVtl.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as d,j as e,R as h}from"./react-DKy9e2uO.js";import{N 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 p=`{
2
+ "name": "startApp",
3
+ "duration": 500,
4
+ "children": [
5
+ {
6
+ "name": "fetchUserData",
7
+ "duration": 300,
8
+ "children": [
9
+ { "name": "authenticate", "duration": 100 },
10
+ { "name": "fetchProfile", "duration": 150 }
11
+ ]
12
+ },
13
+ {
14
+ "name": "loadInitialAssets",
15
+ "duration": 450,
16
+ "children": [
17
+ { "name": "loadImage.png", "duration": 200 },
18
+ { "name": "loadScript.js", "duration": 250 }
19
+ ]
20
+ }
21
+ ]
22
+ }`,x=({node:t,level:i,maxDuration:s})=>{const[a,c]=h.useState(!0),n=t.children&&t.children.length>0;return e.jsxs("div",{className:"my-1",children:[e.jsxs("div",{className:"flex items-center p-2 rounded-md hover:bg-gray-100",style:{paddingLeft:`${i*20+8}px`},children:[n&&e.jsx("button",{onClick:()=>c(!a),className:`mr-2 text-text-secondary w-4 h-4 flex-shrink-0 transform transition-transform ${a?"rotate-90":""}`,children:"▶"}),!n&&e.jsx("div",{className:"w-6 mr-2 flex-shrink-0"}),e.jsxs("div",{className:"flex-grow flex items-center justify-between gap-4",children:[e.jsx("span",{className:"truncate",children:t.name}),e.jsxs("div",{className:"flex items-center gap-2 flex-shrink-0",children:[e.jsx("div",{className:"w-24 h-4 bg-gray-200 rounded-full overflow-hidden",children:e.jsx("div",{className:"h-4 bg-primary",style:{width:`${t.duration/s*100}%`}})}),e.jsxs("span",{className:"text-primary w-16 text-right",children:[t.duration.toFixed(0),"ms"]})]})]})]}),a&&n&&e.jsx("div",{children:t.children.map((r,l)=>e.jsx(x,{node:r,level:i+1,maxDuration:s},l))})]})},I=()=>{const[t,i]=d.useState(p),[s,a]=d.useState(""),{treeData:c,maxDuration:n}=d.useMemo(()=>{try{const r=JSON.parse(t);let l=0;const m=o=>{o.duration>l&&(l=o.duration),o.children&&o.children.forEach(m)};return m(r),a(""),{treeData:r,maxDuration:l}}catch{return a("Invalid JSON format."),{treeData:null,maxDuration:0}}},[t]);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 flex items-center",children:[e.jsx(u,{}),e.jsx("span",{className:"ml-3",children:"Async Call Tree Viewer"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Paste a JSON structure to visualize an asynchronous function call tree."})]}),e.jsxs("div",{className:"flex-grow flex flex-col gap-4 min-h-0",children:[e.jsxs("div",{className:"flex flex-col h-2/5 min-h-[200px]",children:[e.jsx("label",{htmlFor:"json-input",className:"text-sm font-medium text-text-secondary mb-2",children:"JSON Input"}),e.jsx("textarea",{id:"json-input",value:t,onChange:r=>i(r.target.value),className:`flex-grow p-4 bg-surface border ${s?"border-red-500":"border-border"} rounded-md resize-y font-mono text-sm`,spellCheck:"false"}),s&&e.jsx("p",{className:"text-red-500 text-xs mt-1",children:s})]}),e.jsxs("div",{className:"flex flex-col flex-grow min-h-0",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"Visual Tree"}),e.jsx("div",{className:"flex-grow bg-surface p-4 rounded-lg text-sm overflow-y-auto border border-border",children:c?e.jsx(x,{node:c,level:0,maxDuration:n}):e.jsx("div",{className:"text-text-secondary",children:s||"Enter valid JSON to see the tree."})})]})]})]})};export{I as AsyncCallTreeViewer};
23
+ //# sourceMappingURL=AsyncCallTreeViewer-D_OioVtl.js.map
assets/AsyncCallTreeViewer-D_OioVtl.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AsyncCallTreeViewer-D_OioVtl.js","sources":["../../components/features/AsyncCallTreeViewer.tsx"],"sourcesContent":["\n\nimport React, { useState, useMemo } from 'react';\nimport { ChartBarIcon } from '../icons.tsx';\n\ninterface CallNode {\n name: string;\n duration: number;\n children?: CallNode[];\n}\n\nconst exampleJson = `{\n \"name\": \"startApp\",\n \"duration\": 500,\n \"children\": [\n {\n \"name\": \"fetchUserData\",\n \"duration\": 300,\n \"children\": [\n { \"name\": \"authenticate\", \"duration\": 100 },\n { \"name\": \"fetchProfile\", \"duration\": 150 }\n ]\n },\n {\n \"name\": \"loadInitialAssets\",\n \"duration\": 450,\n \"children\": [\n { \"name\": \"loadImage.png\", \"duration\": 200 },\n { \"name\": \"loadScript.js\", \"duration\": 250 }\n ]\n }\n ]\n}`;\n\n\nconst TreeNode: React.FC<{ node: CallNode, level: number, maxDuration: number }> = ({ node, level, maxDuration }) => {\n const [isOpen, setIsOpen] = React.useState(true);\n const hasChildren = node.children && node.children.length > 0;\n\n return (\n <div className=\"my-1\">\n <div\n className=\"flex items-center p-2 rounded-md hover:bg-gray-100\"\n style={{ paddingLeft: `${level * 20 + 8}px` }}\n >\n {hasChildren && (\n <button onClick={() => setIsOpen(!isOpen)} className={`mr-2 text-text-secondary w-4 h-4 flex-shrink-0 transform transition-transform ${isOpen ? 'rotate-90' : ''}`}>\n ▶\n </button>\n )}\n {!hasChildren && <div className=\"w-6 mr-2 flex-shrink-0\" />}\n <div className=\"flex-grow flex items-center justify-between gap-4\">\n <span className=\"truncate\">{node.name}</span>\n <div className=\"flex items-center gap-2 flex-shrink-0\">\n <div className=\"w-24 h-4 bg-gray-200 rounded-full overflow-hidden\">\n <div className=\"h-4 bg-primary\" style={{ width: `${(node.duration / maxDuration) * 100}%` }}/>\n </div>\n <span className=\"text-primary w-16 text-right\">{node.duration.toFixed(0)}ms</span>\n </div>\n </div>\n </div>\n {isOpen && hasChildren && (\n <div>\n {node.children!.map((child, index) => (\n <TreeNode key={index} node={child} level={level + 1} maxDuration={maxDuration} />\n ))}\n </div>\n )}\n </div>\n );\n};\n\n\nexport const AsyncCallTreeViewer: React.FC = () => {\n const [jsonInput, setJsonInput] = useState(exampleJson);\n const [error, setError] = useState('');\n\n const { treeData, maxDuration } = useMemo(() => {\n try {\n const data: CallNode = JSON.parse(jsonInput);\n let max = 0;\n const findMax = (node: CallNode) => {\n if (node.duration > max) max = node.duration;\n if (node.children) node.children.forEach(findMax);\n };\n findMax(data);\n setError('');\n return { treeData: data, maxDuration: max };\n } catch (e) {\n setError('Invalid JSON format.');\n return { treeData: null, maxDuration: 0 };\n }\n }, [jsonInput]);\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl flex items-center\">\n <ChartBarIcon />\n <span className=\"ml-3\">Async Call Tree Viewer</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Paste a JSON structure to visualize an asynchronous function call tree.</p>\n </header>\n <div className=\"flex-grow flex flex-col gap-4 min-h-0\">\n <div className=\"flex flex-col h-2/5 min-h-[200px]\">\n <label htmlFor=\"json-input\" className=\"text-sm font-medium text-text-secondary mb-2\">JSON Input</label>\n <textarea\n id=\"json-input\"\n value={jsonInput}\n onChange={e => setJsonInput(e.target.value)}\n className={`flex-grow p-4 bg-surface border ${error ? 'border-red-500' : 'border-border'} rounded-md resize-y font-mono text-sm`}\n spellCheck=\"false\"\n />\n {error && <p className=\"text-red-500 text-xs mt-1\">{error}</p>}\n </div>\n <div className=\"flex flex-col flex-grow min-h-0\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">Visual Tree</label>\n <div className=\"flex-grow bg-surface p-4 rounded-lg text-sm overflow-y-auto border border-border\">\n {treeData ? <TreeNode node={treeData} level={0} maxDuration={maxDuration} /> : <div className=\"text-text-secondary\">{error || 'Enter valid JSON to see the tree.'}</div>}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["exampleJson","TreeNode","node","level","maxDuration","isOpen","setIsOpen","React","hasChildren","jsxs","jsx","child","index","AsyncCallTreeViewer","jsonInput","setJsonInput","useState","error","setError","treeData","useMemo","data","max","findMax","ChartBarIcon","e"],"mappings":"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"}
assets/AudioToCode-DhNgjuEC.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as t,j as e}from"./react-DKy9e2uO.js";import{O as y,Q as R,R as v,L as h,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 B=()=>{const[o,x]=t.useState(!1),[n,d]=t.useState(!1),[c,f]=t.useState(""),[u,i]=t.useState(""),r=t.useRef(null),l=t.useRef([]),g=async()=>{if(i(""),f(""),!navigator.mediaDevices||!navigator.mediaDevices.getUserMedia){i("Audio recording is not supported by your browser.");return}try{const s=await navigator.mediaDevices.getUserMedia({audio:!0});r.current=new MediaRecorder(s),r.current.ondataavailable=a=>{l.current.push(a.data)},r.current.onstop=j,r.current.start(),x(!0)}catch{i("Microphone access was denied. Please enable it in your browser settings.")}},b=()=>{r.current&&o&&(r.current.stop(),r.current.stream.getTracks().forEach(s=>s.stop()),x(!1),d(!0))},j=t.useCallback(async()=>{if(l.current.length===0){d(!1);return}const s=new Blob(l.current,{type:"audio/webm"});l.current=[];try{const a=await y(s),m=R(a,"audio/webm");let p="";for await(const w of m)p+=w,f(p)}catch(a){const m=a instanceof Error?a.message:"An unknown error occurred.";i(`Failed to transcribe audio: ${m}`)}finally{d(!1)}},[]);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 text-center",children:[e.jsxs("h1",{className:"text-3xl font-bold flex items-center justify-center",children:[e.jsx(v,{}),e.jsx("span",{className:"ml-3",children:"AI Audio-to-Code"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Speak your programming ideas and watch them turn into code."})]}),e.jsxs("div",{className:"flex-grow flex flex-col items-center gap-6 min-h-0",children:[e.jsxs("div",{className:"flex flex-col items-center justify-center bg-surface p-6 rounded-lg w-full max-w-lg border border-border",children:[e.jsx("button",{onClick:o?b:g,className:`w-24 h-24 rounded-full flex items-center justify-center text-white font-bold text-lg transition-all ${o?"bg-red-500 animate-pulse":"bg-primary"}`,disabled:n,children:n?e.jsx(h,{}):o?"Stop":"Record"}),e.jsx("p",{className:"mt-4 text-text-secondary",children:n?"Transcribing...":o?"Recording in progress...":"Click to start recording"})]}),e.jsxs("div",{className:"flex flex-col h-full w-full max-w-3xl",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"Generated Code"}),e.jsxs("div",{className:"flex-grow p-1 bg-background border border-border rounded-md overflow-y-auto min-h-[200px]",children:[n&&!c&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(h,{})}),u&&e.jsx("p",{className:"p-4 text-red-500",children:u}),c&&e.jsx(N,{content:c}),!n&&!c&&!u&&e.jsx("div",{className:"text-text-secondary h-full flex items-center justify-center",children:"Code will appear here."})]})]})]})]})};export{B as AudioToCode};
2
+ //# sourceMappingURL=AudioToCode-DhNgjuEC.js.map
assets/AudioToCode-DhNgjuEC.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AudioToCode-DhNgjuEC.js","sources":["../../components/features/AudioToCode.tsx"],"sourcesContent":["import React, { useState, useRef, useCallback } from 'react';\nimport { transcribeAudioToCodeStream, blobToBase64 } from '../../services/index.ts';\nimport { MicrophoneIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { MarkdownRenderer } from '../shared/index.tsx';\n\nexport const AudioToCode: React.FC = () => {\n const [isRecording, setIsRecording] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [code, setCode] = useState('');\n const [error, setError] = useState('');\n const mediaRecorderRef = useRef<MediaRecorder | null>(null);\n const audioChunksRef = useRef<Blob[]>([]);\n\n const handleStartRecording = async () => {\n setError('');\n setCode('');\n if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n setError('Audio recording is not supported by your browser.');\n return;\n }\n try {\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\n mediaRecorderRef.current = new MediaRecorder(stream);\n mediaRecorderRef.current.ondataavailable = event => {\n audioChunksRef.current.push(event.data);\n };\n mediaRecorderRef.current.onstop = handleTranscribe;\n mediaRecorderRef.current.start();\n setIsRecording(true);\n } catch (err) {\n setError('Microphone access was denied. Please enable it in your browser settings.');\n }\n };\n\n const handleStopRecording = () => {\n if (mediaRecorderRef.current && isRecording) {\n mediaRecorderRef.current.stop();\n mediaRecorderRef.current.stream.getTracks().forEach(track => track.stop());\n setIsRecording(false);\n setIsLoading(true);\n }\n };\n\n const handleTranscribe = useCallback(async () => {\n if (audioChunksRef.current.length === 0) {\n setIsLoading(false);\n return;\n }\n const audioBlob = new Blob(audioChunksRef.current, { type: 'audio/webm' });\n audioChunksRef.current = [];\n try {\n const base64Audio = await blobToBase64(audioBlob);\n const stream = transcribeAudioToCodeStream(base64Audio, 'audio/webm');\n let fullResponse = '';\n for await (const chunk of stream) {\n fullResponse += chunk;\n setCode(fullResponse);\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to transcribe audio: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6 text-center\">\n <h1 className=\"text-3xl font-bold flex items-center justify-center\">\n <MicrophoneIcon />\n <span className=\"ml-3\">AI Audio-to-Code</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Speak your programming ideas and watch them turn into code.</p>\n </header>\n <div className=\"flex-grow flex flex-col items-center gap-6 min-h-0\">\n <div className=\"flex flex-col items-center justify-center bg-surface p-6 rounded-lg w-full max-w-lg border border-border\">\n <button\n onClick={isRecording ? handleStopRecording : handleStartRecording}\n className={`w-24 h-24 rounded-full flex items-center justify-center text-white font-bold text-lg transition-all ${isRecording ? 'bg-red-500 animate-pulse' : 'bg-primary'}`}\n disabled={isLoading}\n >\n {isLoading ? <LoadingSpinner/> : isRecording ? 'Stop' : 'Record'}\n </button>\n <p className=\"mt-4 text-text-secondary\">\n {isLoading ? 'Transcribing...' : isRecording ? 'Recording in progress...' : 'Click to start recording'}\n </p>\n </div>\n <div className=\"flex flex-col h-full w-full max-w-3xl\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">Generated Code</label>\n <div className=\"flex-grow p-1 bg-background border border-border rounded-md overflow-y-auto min-h-[200px]\">\n {isLoading && !code && (\n <div className=\"flex items-center justify-center h-full\"><LoadingSpinner /></div>\n )}\n {error && <p className=\"p-4 text-red-500\">{error}</p>}\n {code && <MarkdownRenderer content={code} />}\n {!isLoading && !code && !error && (\n <div className=\"text-text-secondary h-full flex items-center justify-center\">Code will appear here.</div>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["AudioToCode","isRecording","setIsRecording","useState","isLoading","setIsLoading","code","setCode","error","setError","mediaRecorderRef","useRef","audioChunksRef","handleStartRecording","stream","event","handleTranscribe","handleStopRecording","track","useCallback","audioBlob","base64Audio","blobToBase64","transcribeAudioToCodeStream","fullResponse","chunk","err","errorMessage","jsxs","jsx","MicrophoneIcon","LoadingSpinner","MarkdownRenderer"],"mappings":"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"}
assets/ChangelogGenerator-DhzKekFT.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as a,j as e}from"./react-DKy9e2uO.js";import{w as u,G as f,L as x,M as p}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 b=`commit 3a4b5c...
2
+ Author: Dev One <dev.one@example.com>
3
+ Date: Mon Jul 15 11:30:00 2024 -0400
4
+
5
+ feat: add user login page
6
+
7
+ commit 1a2b3c...
8
+ Author: Dev Two <dev.two@example.com>
9
+ Date: Mon Jul 15 10:00:00 2024 -0400
10
+
11
+ fix: correct typo in header
12
+ `,S=()=>{const[s,d]=a.useState(b),[r,n]=a.useState(""),[o,c]=a.useState(!1),[i,l]=a.useState(""),g=a.useCallback(async()=>{if(!s.trim()){l("Please paste your git log output.");return}c(!0),l(""),n("");try{const t=u(s);let m="";for await(const h of t)m+=h,n(m)}catch(t){l(t instanceof Error?t.message:"An unknown error occurred.")}finally{c(!1)}},[s]);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(f,{}),e.jsx("span",{className:"ml-3",children:"AI Changelog Generator"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Generate a markdown changelog from your raw git log."})]}),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:"commit-input",className:"text-sm font-medium text-text-secondary mb-2",children:"Raw Git Log"}),e.jsx("textarea",{id:"commit-input",value:s,onChange:t=>d(t.target.value),className:"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm"})]}),e.jsx("div",{className:"flex-shrink-0",children:e.jsx("button",{onClick:g,disabled:o,className:"btn-primary w-full max-w-xs mx-auto flex items-center justify-center px-6 py-3",children:o?e.jsx(x,{}):"Generate Changelog"})}),e.jsxs("div",{className:"flex flex-col flex-1 min-h-0",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"Generated Changelog.md"}),e.jsxs("div",{className:"relative flex-grow p-4 bg-background border border-border rounded-md overflow-y-auto",children:[o&&!r&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(x,{})}),i&&e.jsx("p",{className:"text-red-500",children:i}),r&&e.jsx(p,{content:r}),!o&&r&&e.jsx("button",{onClick:()=>navigator.clipboard.writeText(r),className:"absolute top-2 right-2 px-2 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200",children:"Copy"})]})]})]})]})};export{S as ChangelogGenerator};
13
+ //# sourceMappingURL=ChangelogGenerator-DhzKekFT.js.map
assets/ChangelogGenerator-DhzKekFT.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"ChangelogGenerator-DhzKekFT.js","sources":["../../components/features/ChangelogGenerator.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { generateChangelogFromLogStream } from '../../services/index.ts';\nimport { GitBranchIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { MarkdownRenderer } from '../shared/index.tsx';\n\nconst exampleLog = `commit 3a4b5c...\nAuthor: Dev One <dev.one@example.com>\nDate: Mon Jul 15 11:30:00 2024 -0400\n\n feat: add user login page\n\ncommit 1a2b3c...\nAuthor: Dev Two <dev.two@example.com>\nDate: Mon Jul 15 10:00:00 2024 -0400\n\n fix: correct typo in header\n`;\n\nexport const ChangelogGenerator: React.FC = () => {\n const [log, setLog] = useState(exampleLog);\n const [changelog, setChangelog] = useState('');\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState('');\n\n const handleGenerate = useCallback(async () => {\n if (!log.trim()) {\n setError('Please paste your git log output.');\n return;\n }\n setIsLoading(true);\n setError('');\n setChangelog('');\n try {\n const stream = generateChangelogFromLogStream(log);\n let fullResponse = '';\n for await (const chunk of stream) {\n fullResponse += chunk;\n setChangelog(fullResponse);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'An unknown error occurred.');\n } finally {\n setIsLoading(false);\n }\n }, [log]);\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <GitBranchIcon />\n <span className=\"ml-3\">AI Changelog Generator</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Generate a markdown changelog from your raw git log.</p>\n </header>\n <div className=\"flex-grow flex flex-col gap-4 min-h-0\">\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label htmlFor=\"commit-input\" className=\"text-sm font-medium text-text-secondary mb-2\">Raw Git Log</label>\n <textarea\n id=\"commit-input\"\n value={log}\n onChange={(e) => setLog(e.target.value)}\n className=\"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm\"\n />\n </div>\n <div className=\"flex-shrink-0\">\n <button onClick={handleGenerate} disabled={isLoading} className=\"btn-primary w-full max-w-xs mx-auto flex items-center justify-center px-6 py-3\">\n {isLoading ? <LoadingSpinner /> : 'Generate Changelog'}\n </button>\n </div>\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">Generated Changelog.md</label>\n <div className=\"relative flex-grow p-4 bg-background border border-border rounded-md overflow-y-auto\">\n {isLoading && !changelog && <div className=\"flex items-center justify-center h-full\"><LoadingSpinner /></div>}\n {error && <p className=\"text-red-500\">{error}</p>}\n {changelog && <MarkdownRenderer content={changelog} />}\n {!isLoading && changelog && <button onClick={() => navigator.clipboard.writeText(changelog)} className=\"absolute top-2 right-2 px-2 py-1 bg-gray-100 text-xs rounded-md hover:bg-gray-200\">Copy</button>}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["exampleLog","ChangelogGenerator","log","setLog","useState","changelog","setChangelog","isLoading","setIsLoading","error","setError","handleGenerate","useCallback","stream","generateChangelogFromLogStream","fullResponse","chunk","err","jsxs","jsx","GitBranchIcon","e","LoadingSpinner","MarkdownRenderer"],"mappings":"8TAMA,MAAMA,EAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaNC,EAA+B,IAAM,CAC9C,KAAM,CAACC,EAAKC,CAAM,EAAIC,EAAAA,SAASJ,CAAU,EACnC,CAACK,EAAWC,CAAY,EAAIF,EAAAA,SAAS,EAAE,EACvC,CAACG,EAAWC,CAAY,EAAIJ,EAAAA,SAAS,EAAK,EAC1C,CAACK,EAAOC,CAAQ,EAAIN,EAAAA,SAAS,EAAE,EAE/BO,EAAiBC,EAAAA,YAAY,SAAY,CAC3C,GAAI,CAACV,EAAI,OAAQ,CACbQ,EAAS,mCAAmC,EAC5C,MACJ,CACAF,EAAa,EAAI,EACjBE,EAAS,EAAE,EACXJ,EAAa,EAAE,EACf,GAAI,CACA,MAAMO,EAASC,EAA+BZ,CAAG,EACjD,IAAIa,EAAe,GACnB,gBAAiBC,KAASH,EACtBE,GAAgBC,EAChBV,EAAaS,CAAY,CAEjC,OAASE,EAAK,CACVP,EAASO,aAAe,MAAQA,EAAI,QAAU,4BAA4B,CAC9E,QAAA,CACIT,EAAa,EAAK,CACtB,CACJ,EAAG,CAACN,CAAG,CAAC,EAER,OACIgB,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,uCACV,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAc,EACfD,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,wBAAA,CAAsB,CAAA,EACjD,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,sDAAA,CAAoD,CAAA,EAChG,EACAD,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACX,SAAA,CAAAC,MAAC,QAAA,CAAM,QAAQ,eAAe,UAAU,+CAA+C,SAAA,cAAW,EAClGA,EAAAA,IAAC,WAAA,CACG,GAAG,eACH,MAAOjB,EACP,SAAWmB,GAAMlB,EAAOkB,EAAE,OAAO,KAAK,EACtC,UAAU,wFAAA,CAAA,CACd,EACJ,QACC,MAAA,CAAI,UAAU,gBACX,SAAAF,EAAAA,IAAC,UAAO,QAASR,EAAgB,SAAUJ,EAAW,UAAU,iFAC3D,SAAAA,QAAae,EAAA,EAAe,EAAK,qBACtC,EACJ,EACAJ,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACX,SAAA,CAAAC,EAAAA,IAAC,QAAA,CAAM,UAAU,+CAA+C,SAAA,yBAAsB,EACtFD,EAAAA,KAAC,MAAA,CAAI,UAAU,uFACV,SAAA,CAAAX,GAAa,CAACF,GAAac,EAAAA,IAAC,MAAA,CAAI,UAAU,0CAA0C,SAAAA,EAAAA,IAACG,IAAe,CAAA,CAAE,EACtGb,GAASU,EAAAA,IAAC,IAAA,CAAE,UAAU,eAAgB,SAAAV,EAAM,EAC5CJ,GAAac,EAAAA,IAACI,EAAA,CAAiB,QAASlB,CAAA,CAAW,EACnD,CAACE,GAAaF,GAAac,EAAAA,IAAC,UAAO,QAAS,IAAM,UAAU,UAAU,UAAUd,CAAS,EAAG,UAAU,oFAAoF,SAAA,MAAA,CAAI,CAAA,CAAA,CACnM,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,EACJ,CAER"}
assets/CodeDiffGhost-Q06Vp3v6.js ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r,j as e}from"./react-DKy9e2uO.js";import{U 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 x=`function UserProfile({ user }) {
2
+ return (
3
+ <div className="profile">
4
+ <h1>{user.name}</h1>
5
+ <p>{user.email}</p>
6
+ </div>
7
+ );
8
+ }`,h=`function UserProfile({ user }) {
9
+ const { name, email, avatar } = user;
10
+ return (
11
+ <div className="profile-card">
12
+ <img src={avatar} alt={name} />
13
+ <h2>{name}</h2>
14
+ <a href={\`mailto:\${email}\`}>{email}</a>
15
+ </div>
16
+ );
17
+ }`,z=()=>{const[c,d]=r.useState(x),[a,m]=r.useState(h),[n,i]=r.useState(""),[l,o]=r.useState(!1),s=r.useRef(null),f=()=>{s.current&&clearInterval(s.current),o(!0),i(""),s.current=window.setInterval(()=>{i(t=>t.length<a.length?a.substring(0,t.length+1):(s.current&&clearInterval(s.current),o(!1),a))},15)};return r.useEffect(()=>()=>{s.current&&clearInterval(s.current)},[]),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 flex items-center",children:[e.jsx(u,{}),e.jsx("span",{className:"ml-3",children:"Code Diff Ghost"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:'Visualize code changes with a "ghost typing" effect.'})]}),e.jsx("div",{className:"flex justify-center mb-4",children:e.jsx("button",{onClick:f,disabled:l,className:"btn-primary px-6 py-2",children:l?"Visualizing...":"Show Changes"})}),e.jsxs("div",{className:"flex-grow grid grid-cols-1 lg:grid-cols-2 gap-6 h-full overflow-hidden font-mono text-sm",children:[e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsx("label",{htmlFor:"before-code",className:"text-sm font-medium text-text-secondary mb-2",children:"Before"}),e.jsx("textarea",{id:"before-code",value:c,onChange:t=>d(t.target.value),className:"flex-grow p-4 bg-surface border border-border rounded-md text-red-600 whitespace-pre-wrap resize-none",spellCheck:"false"})]}),e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsx("label",{htmlFor:"after-code",className:"text-sm font-medium text-text-secondary mb-2",children:"After"}),e.jsxs("div",{className:"relative flex-grow",children:[e.jsx("textarea",{id:"after-code",value:a,onChange:t=>m(t.target.value),className:"absolute inset-0 w-full h-full p-4 bg-surface border border-border rounded-md text-emerald-700 whitespace-pre-wrap resize-none z-0",spellCheck:"false"}),(l||n)&&e.jsxs("pre",{className:"absolute inset-0 w-full h-full p-4 bg-surface pointer-events-none text-emerald-700 whitespace-pre-wrap z-10",children:[n,l&&e.jsx("span",{className:"animate-pulse",children:"|"})]})]})]})]})]})};export{z as CodeDiffGhost};
18
+ //# sourceMappingURL=CodeDiffGhost-Q06Vp3v6.js.map
assets/CodeDiffGhost-Q06Vp3v6.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CodeDiffGhost-Q06Vp3v6.js","sources":["../../components/features/CodeDiffGhost.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport { EyeIcon } from '../icons.tsx';\n\nconst initialOldCode = `function UserProfile({ user }) {\n return (\n <div className=\"profile\">\n <h1>{user.name}</h1>\n <p>{user.email}</p>\n </div>\n );\n}`;\n\nconst initialNewCode = `function UserProfile({ user }) {\n const { name, email, avatar } = user;\n return (\n <div className=\"profile-card\">\n <img src={avatar} alt={name} />\n <h2>{name}</h2>\n <a href={\\`mailto:\\${email}\\`}>{email}</a>\n </div>\n );\n}`;\n\nexport const CodeDiffGhost: React.FC = () => {\n const [oldCode, setOldCode] = useState(initialOldCode);\n const [newCode, setNewCode] = useState(initialNewCode);\n const [typedCode, setTypedCode] = useState('');\n const [isRunning, setIsRunning] = useState(false);\n const intervalRef = useRef<number | null>(null);\n\n const startAnimation = () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n setIsRunning(true);\n setTypedCode('');\n \n intervalRef.current = window.setInterval(() => {\n setTypedCode(prev => {\n if (prev.length < newCode.length) {\n return newCode.substring(0, prev.length + 1);\n }\n if (intervalRef.current) clearInterval(intervalRef.current);\n setIsRunning(false);\n return newCode;\n });\n }, 15);\n };\n\n useEffect(() => {\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current);\n };\n }, []);\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl flex items-center\">\n <EyeIcon />\n <span className=\"ml-3\">Code Diff Ghost</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Visualize code changes with a \"ghost typing\" effect.</p>\n </header>\n <div className=\"flex justify-center mb-4\">\n <button\n onClick={startAnimation}\n disabled={isRunning}\n className=\"btn-primary px-6 py-2\"\n >\n {isRunning ? 'Visualizing...' : 'Show Changes'}\n </button>\n </div>\n <div className=\"flex-grow grid grid-cols-1 lg:grid-cols-2 gap-6 h-full overflow-hidden font-mono text-sm\">\n <div className=\"flex flex-col h-full\">\n <label htmlFor=\"before-code\" className=\"text-sm font-medium text-text-secondary mb-2\">Before</label>\n <textarea\n id=\"before-code\"\n value={oldCode}\n onChange={e => setOldCode(e.target.value)}\n className=\"flex-grow p-4 bg-surface border border-border rounded-md text-red-600 whitespace-pre-wrap resize-none\"\n spellCheck=\"false\"\n />\n </div>\n <div className=\"flex flex-col h-full\">\n <label htmlFor=\"after-code\" className=\"text-sm font-medium text-text-secondary mb-2\">After</label>\n <div className=\"relative flex-grow\">\n <textarea\n id=\"after-code\"\n value={newCode}\n onChange={e => setNewCode(e.target.value)}\n className=\"absolute inset-0 w-full h-full p-4 bg-surface border border-border rounded-md text-emerald-700 whitespace-pre-wrap resize-none z-0\"\n spellCheck=\"false\"\n />\n {(isRunning || typedCode) && (\n <pre className=\"absolute inset-0 w-full h-full p-4 bg-surface pointer-events-none text-emerald-700 whitespace-pre-wrap z-10\">\n {typedCode}{isRunning && <span className=\"animate-pulse\">|</span>}\n </pre>\n )}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["initialOldCode","initialNewCode","CodeDiffGhost","oldCode","setOldCode","useState","newCode","setNewCode","typedCode","setTypedCode","isRunning","setIsRunning","intervalRef","useRef","startAnimation","prev","useEffect","jsxs","jsx","EyeIcon","e"],"mappings":"oSAGA,MAAMA,EAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GASjBC,EAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAWVC,EAA0B,IAAM,CACzC,KAAM,CAACC,EAASC,CAAU,EAAIC,EAAAA,SAASL,CAAc,EAC/C,CAACM,EAASC,CAAU,EAAIF,EAAAA,SAASJ,CAAc,EAC/C,CAACO,EAAWC,CAAY,EAAIJ,EAAAA,SAAS,EAAE,EACvC,CAACK,EAAWC,CAAY,EAAIN,EAAAA,SAAS,EAAK,EAC1CO,EAAcC,EAAAA,OAAsB,IAAI,EAExCC,EAAiB,IAAM,CACrBF,EAAY,SAAS,cAAcA,EAAY,OAAO,EAC1DD,EAAa,EAAI,EACjBF,EAAa,EAAE,EAEfG,EAAY,QAAU,OAAO,YAAY,IAAM,CAC3CH,EAAaM,GACLA,EAAK,OAAST,EAAQ,OACfA,EAAQ,UAAU,EAAGS,EAAK,OAAS,CAAC,GAE3CH,EAAY,SAAS,cAAcA,EAAY,OAAO,EAC1DD,EAAa,EAAK,EACXL,EACV,CACL,EAAG,EAAE,CACT,EAEAU,OAAAA,EAAAA,UAAU,IACC,IAAM,CACLJ,EAAY,SAAS,cAAcA,EAAY,OAAO,CAC9D,EACD,CAAA,CAAE,EAGDK,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,6BACV,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAQ,EACTD,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,iBAAA,CAAe,CAAA,EAC1C,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,sDAAA,CAAoD,CAAA,EAChG,EACAA,EAAAA,IAAC,MAAA,CAAI,UAAU,2BACX,SAAAA,EAAAA,IAAC,SAAA,CACG,QAASJ,EACT,SAAUJ,EACV,UAAU,wBAET,WAAY,iBAAmB,cAAA,CAAA,EAExC,EACAO,EAAAA,KAAC,MAAA,CAAI,UAAU,2FACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACX,SAAA,CAAAC,MAAC,QAAA,CAAM,QAAQ,cAAc,UAAU,+CAA+C,SAAA,SAAM,EAC5FA,EAAAA,IAAC,WAAA,CACG,GAAG,cACH,MAAOf,EACP,SAAUiB,GAAKhB,EAAWgB,EAAE,OAAO,KAAK,EACxC,UAAU,wGACV,WAAW,OAAA,CAAA,CACf,EACJ,EACCH,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACZ,SAAA,CAAAC,MAAC,QAAA,CAAM,QAAQ,aAAa,UAAU,+CAA+C,SAAA,QAAK,EACzFD,EAAAA,KAAC,MAAA,CAAI,UAAU,qBACZ,SAAA,CAAAC,EAAAA,IAAC,WAAA,CACG,GAAG,aACH,MAAOZ,EACP,SAAUc,GAAKb,EAAWa,EAAE,OAAO,KAAK,EACxC,UAAU,qIACV,WAAW,OAAA,CAAA,GAEbV,GAAaF,IACXS,EAAAA,KAAC,MAAA,CAAI,UAAU,8GACV,SAAA,CAAAT,EAAWE,GAAaQ,EAAAA,IAAC,OAAA,CAAK,UAAU,gBAAgB,SAAA,GAAA,CAAC,CAAA,CAAA,CAC9D,CAAA,CAAA,CAER,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,EACJ,CAER"}
assets/CodeFormatter-B5J1ivDG.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import{r,j as e}from"./react-DKy9e2uO.js";import{k as p,i as h,L as d,M as j}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 g=`const MyComponent = (props) => {
2
+ const {name, items}=props
3
+ if(!items || items.length === 0){
4
+ return <p>No items found for {name}</p>;
5
+ }
6
+ return <ul>{items.map(item=> <li key={item.id}>{item.name}</li>)}</ul>
7
+ }`,I=()=>{const[s,x]=r.useState(g),[o,i]=r.useState(""),[a,c]=r.useState(!1),[n,m]=r.useState(""),f=r.useCallback(async()=>{if(!s.trim()){m("Please enter some code to format.");return}c(!0),m(""),i("");try{const t=p(s);let l="";for await(const u of t)l+=u,i(l)}catch(t){const l=t instanceof Error?t.message:"An unknown error occurred.";m(`Failed to format code: ${l}`)}finally{c(!1)}},[s]);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(h,{}),e.jsx("span",{className:"ml-3",children:"AI Code Formatter"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Clean up your code with AI-powered formatting, like a smart Prettier."})]}),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.jsx("label",{htmlFor:"code-input",className:"text-sm font-medium text-text-secondary mb-2",children:"Input"}),e.jsx("textarea",{id:"code-input",value:s,onChange:t=>x(t.target.value),placeholder:"Paste your unformatted 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.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"Output"}),e.jsxs("div",{className:"flex-grow p-1 bg-background border border-border rounded-md overflow-y-auto",children:[a&&!o&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(d,{})}),n&&e.jsx("p",{className:"p-4 text-red-500",children:n}),o&&e.jsx(j,{content:o}),!a&&!o&&!n&&e.jsx("div",{className:"text-text-secondary h-full flex items-center justify-center",children:"Formatted code will appear here."})]})]})]}),e.jsx("button",{onClick:f,disabled:a,className:"btn-primary mt-4 w-full max-w-sm mx-auto flex items-center justify-center px-6 py-3",children:a?e.jsx(d,{}):"Format Code"})]})]})};export{I as CodeFormatter};
8
+ //# sourceMappingURL=CodeFormatter-B5J1ivDG.js.map
assets/CodeFormatter-B5J1ivDG.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CodeFormatter-B5J1ivDG.js","sources":["../../components/features/CodeFormatter.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { formatCodeStream } from '../../services/index.ts';\nimport { CodeBracketSquareIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { MarkdownRenderer } from '../shared/index.tsx';\n\nconst exampleCode = `const MyComponent = (props) => {\n const {name, items}=props\n if(!items || items.length === 0){\n return <p>No items found for {name}</p>;\n }\n return <ul>{items.map(item=> <li key={item.id}>{item.name}</li>)}</ul>\n}`;\n\nexport const CodeFormatter: React.FC = () => {\n const [inputCode, setInputCode] = useState<string>(exampleCode);\n const [formattedCode, setFormattedCode] = useState<string>('');\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n\n const handleFormat = useCallback(async () => {\n if (!inputCode.trim()) {\n setError('Please enter some code to format.');\n return;\n }\n setIsLoading(true);\n setError('');\n setFormattedCode('');\n try {\n const stream = formatCodeStream(inputCode);\n let fullResponse = '';\n for await (const chunk of stream) {\n fullResponse += chunk;\n setFormattedCode(fullResponse);\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to format code: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, [inputCode]);\n \n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <CodeBracketSquareIcon />\n <span className=\"ml-3\">AI Code Formatter</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Clean up your code with AI-powered formatting, like a smart Prettier.</p>\n </header>\n <div className=\"flex-grow flex flex-col min-h-0\">\n <div className=\"grid grid-cols-1 lg:grid-cols-2 gap-6 flex-grow min-h-0\">\n <div className=\"flex flex-col h-full\">\n <label htmlFor=\"code-input\" className=\"text-sm font-medium text-text-secondary mb-2\">Input</label>\n <textarea\n id=\"code-input\"\n value={inputCode}\n onChange={(e) => setInputCode(e.target.value)}\n placeholder=\"Paste your unformatted code here...\"\n className=\"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm\"\n />\n </div>\n <div className=\"flex flex-col h-full\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">Output</label>\n <div className=\"flex-grow p-1 bg-background border border-border rounded-md overflow-y-auto\">\n {isLoading && !formattedCode && (\n <div className=\"flex items-center justify-center h-full\">\n <LoadingSpinner />\n </div>\n )}\n {error && <p className=\"p-4 text-red-500\">{error}</p>}\n {formattedCode && <MarkdownRenderer content={formattedCode} />}\n {!isLoading && !formattedCode && !error && (\n <div className=\"text-text-secondary h-full flex items-center justify-center\">\n Formatted code will appear here.\n </div>\n )}\n </div>\n </div>\n </div>\n <button\n onClick={handleFormat}\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 ? <LoadingSpinner /> : 'Format Code'}\n </button>\n </div>\n </div>\n );\n};"],"names":["exampleCode","CodeFormatter","inputCode","setInputCode","useState","formattedCode","setFormattedCode","isLoading","setIsLoading","error","setError","handleFormat","useCallback","stream","formatCodeStream","fullResponse","chunk","err","errorMessage","jsxs","jsx","CodeBracketSquareIcon","e","LoadingSpinner","MarkdownRenderer"],"mappings":"yTAMA,MAAMA,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQPC,EAA0B,IAAM,CACzC,KAAM,CAACC,EAAWC,CAAY,EAAIC,EAAAA,SAAiBJ,CAAW,EACxD,CAACK,EAAeC,CAAgB,EAAIF,EAAAA,SAAiB,EAAE,EACvD,CAACG,EAAWC,CAAY,EAAIJ,EAAAA,SAAkB,EAAK,EACnD,CAACK,EAAOC,CAAQ,EAAIN,EAAAA,SAAiB,EAAE,EAEvCO,EAAeC,EAAAA,YAAY,SAAY,CACzC,GAAI,CAACV,EAAU,OAAQ,CACnBQ,EAAS,mCAAmC,EAC5C,MACJ,CACAF,EAAa,EAAI,EACjBE,EAAS,EAAE,EACXJ,EAAiB,EAAE,EACnB,GAAI,CACA,MAAMO,EAASC,EAAiBZ,CAAS,EACzC,IAAIa,EAAe,GACnB,gBAAiBC,KAASH,EACtBE,GAAgBC,EAChBV,EAAiBS,CAAY,CAErC,OAASE,EAAK,CACV,MAAMC,EAAeD,aAAe,MAAQA,EAAI,QAAU,6BAC1DP,EAAS,0BAA0BQ,CAAY,EAAE,CACrD,QAAA,CACIV,EAAa,EAAK,CACtB,CACJ,EAAG,CAACN,CAAS,CAAC,EAEd,OACIiB,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,uCACV,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAsB,EACvBD,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,mBAAA,CAAiB,CAAA,EAC5C,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,uEAAA,CAAqE,CAAA,EACjH,EACAD,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,0DACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACX,SAAA,CAAAC,MAAC,QAAA,CAAM,QAAQ,aAAa,UAAU,+CAA+C,SAAA,QAAK,EAC1FA,EAAAA,IAAC,WAAA,CACG,GAAG,aACH,MAAOlB,EACP,SAAWoB,GAAMnB,EAAamB,EAAE,OAAO,KAAK,EAC5C,YAAY,sCACZ,UAAU,wFAAA,CAAA,CACd,EACJ,EACAH,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACX,SAAA,CAAAC,EAAAA,IAAC,QAAA,CAAM,UAAU,+CAA+C,SAAA,SAAM,EACtED,EAAAA,KAAC,MAAA,CAAI,UAAU,8EACX,SAAA,CAAAZ,GAAa,CAACF,GACVe,EAAAA,IAAC,MAAA,CAAI,UAAU,0CACX,SAAAA,EAAAA,IAACG,IAAe,CAAA,CACpB,EAEHd,GAASW,EAAAA,IAAC,IAAA,CAAE,UAAU,mBAAoB,SAAAX,EAAM,EAChDJ,GAAiBe,EAAAA,IAACI,EAAA,CAAiB,QAASnB,CAAA,CAAe,EAC3D,CAACE,GAAa,CAACF,GAAiB,CAACI,GAC9BW,EAAAA,IAAC,MAAA,CAAI,UAAU,8DAA8D,SAAA,kCAAA,CAE7E,CAAA,CAAA,CAER,CAAA,CAAA,CACJ,CAAA,EACJ,EACCA,EAAAA,IAAC,SAAA,CACE,QAAST,EACT,SAAUJ,EACV,UAAU,sFAET,SAAAA,EAAYa,EAAAA,IAACG,EAAA,CAAA,CAAe,EAAK,aAAA,CAAA,CACtC,CAAA,CACJ,CAAA,EACJ,CAER"}
assets/CodeReviewBot-2UF5jWqT.js ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r,j as e}from"./react-DKy9e2uO.js";import{r as p,C as h,L as m,M as j}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=`function UserList(users) {
2
+ if (users.length = 0) {
3
+ return "no users";
4
+ } else {
5
+ return (
6
+ users.map(u => {
7
+ return <li>{u.name}</li>
8
+ })
9
+ )
10
+ }
11
+ }`,L=()=>{const[t,x]=r.useState(v),[a,c]=r.useState(""),[o,d]=r.useState(!1),[n,i]=r.useState(""),u=r.useCallback(async()=>{if(!t.trim()){i("Please enter some code to review.");return}d(!0),i(""),c("");try{const s=p(t);let l="";for await(const f of s)l+=f,c(l)}catch(s){const l=s instanceof Error?s.message:"An unknown error occurred.";i(`Failed to get review: ${l}`)}finally{d(!1)}},[t]);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(h,{}),e.jsx("span",{className:"ml-3",children:"AI Code Review Bot"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Get an automated code review from Gemini."})]}),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:"code-input",className:"text-sm font-medium text-text-secondary mb-2",children:"Code to Review"}),e.jsx("textarea",{id:"code-input",value:t,onChange:s=>x(s.target.value),placeholder:"Paste your code here...",className:"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm"})]}),e.jsx("div",{className:"flex-shrink-0",children:e.jsx("button",{onClick:u,disabled:o,className:"btn-primary w-full max-w-xs mx-auto flex items-center justify-center px-6 py-3",children:o?e.jsx(m,{}):"Request Review"})}),e.jsxs("div",{className:"flex flex-col flex-1 min-h-0",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"AI Feedback"}),e.jsxs("div",{className:"flex-grow p-4 bg-background border border-border rounded-md overflow-y-auto",children:[o&&!a&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(m,{})}),n&&e.jsx("p",{className:"text-red-500",children:n}),a&&e.jsx(j,{content:a}),!o&&!a&&!n&&e.jsx("div",{className:"text-text-secondary h-full flex items-center justify-center",children:"Review will appear here."})]})]})]})]})};export{L as CodeReviewBot};
12
+ //# sourceMappingURL=CodeReviewBot-2UF5jWqT.js.map
assets/CodeReviewBot-2UF5jWqT.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CodeReviewBot-2UF5jWqT.js","sources":["../../components/features/CodeReviewBot.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { reviewCodeStream } from '../../services/index.ts';\nimport { CpuChipIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { MarkdownRenderer } from '../shared/index.tsx';\n\nconst exampleCode = `function UserList(users) {\n if (users.length = 0) {\n return \"no users\";\n } else {\n return (\n users.map(u => {\n return <li>{u.name}</li>\n })\n )\n }\n}`;\n\nexport const CodeReviewBot: React.FC = () => {\n const [code, setCode] = useState<string>(exampleCode);\n const [review, setReview] = useState<string>('');\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n\n const handleGenerate = useCallback(async () => {\n if (!code.trim()) {\n setError('Please enter some code to review.');\n return;\n }\n setIsLoading(true);\n setError('');\n setReview('');\n try {\n const stream = reviewCodeStream(code);\n let fullResponse = '';\n for await (const chunk of stream) {\n fullResponse += chunk;\n setReview(fullResponse);\n }\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to get review: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, [code]);\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <CpuChipIcon />\n <span className=\"ml-3\">AI Code Review Bot</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Get an automated code review from Gemini.</p>\n </header>\n <div className=\"flex-grow flex flex-col gap-4 min-h-0\">\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label htmlFor=\"code-input\" className=\"text-sm font-medium text-text-secondary mb-2\">Code to Review</label>\n <textarea\n id=\"code-input\"\n value={code}\n onChange={(e) => setCode(e.target.value)}\n placeholder=\"Paste your code here...\"\n className=\"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm\"\n />\n </div>\n <div className=\"flex-shrink-0\">\n <button\n onClick={handleGenerate}\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 ? <LoadingSpinner /> : 'Request Review'}\n </button>\n </div>\n <div className=\"flex flex-col flex-1 min-h-0\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">AI Feedback</label>\n <div className=\"flex-grow p-4 bg-background border border-border rounded-md overflow-y-auto\">\n {isLoading && !review && <div className=\"flex items-center justify-center h-full\"><LoadingSpinner /></div>}\n {error && <p className=\"text-red-500\">{error}</p>}\n {review && <MarkdownRenderer content={review} />}\n {!isLoading && !review && !error && <div className=\"text-text-secondary h-full flex items-center justify-center\">Review will appear here.</div>}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["exampleCode","CodeReviewBot","code","setCode","useState","review","setReview","isLoading","setIsLoading","error","setError","handleGenerate","useCallback","stream","reviewCodeStream","fullResponse","chunk","err","errorMessage","jsxs","jsx","CpuChipIcon","e","LoadingSpinner","MarkdownRenderer"],"mappings":"yTAMA,MAAMA,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAYPC,EAA0B,IAAM,CACzC,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAiBJ,CAAW,EAC9C,CAACK,EAAQC,CAAS,EAAIF,EAAAA,SAAiB,EAAE,EACzC,CAACG,EAAWC,CAAY,EAAIJ,EAAAA,SAAkB,EAAK,EACnD,CAACK,EAAOC,CAAQ,EAAIN,EAAAA,SAAiB,EAAE,EAEvCO,EAAiBC,EAAAA,YAAY,SAAY,CAC3C,GAAI,CAACV,EAAK,OAAQ,CACdQ,EAAS,mCAAmC,EAC5C,MACJ,CACAF,EAAa,EAAI,EACjBE,EAAS,EAAE,EACXJ,EAAU,EAAE,EACZ,GAAI,CACA,MAAMO,EAASC,EAAiBZ,CAAI,EACpC,IAAIa,EAAe,GACnB,gBAAiBC,KAASH,EACtBE,GAAgBC,EAChBV,EAAUS,CAAY,CAE9B,OAASE,EAAK,CACV,MAAMC,EAAeD,aAAe,MAAQA,EAAI,QAAU,6BAC1DP,EAAS,yBAAyBQ,CAAY,EAAE,CACpD,QAAA,CACIV,EAAa,EAAK,CACtB,CACJ,EAAG,CAACN,CAAI,CAAC,EAET,OACIiB,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,uCACV,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAY,EACbD,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,oBAAA,CAAkB,CAAA,EAC7C,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,2CAAA,CAAyC,CAAA,EACrF,EACAD,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACX,SAAA,CAAAC,MAAC,QAAA,CAAM,QAAQ,aAAa,UAAU,+CAA+C,SAAA,iBAAc,EACnGA,EAAAA,IAAC,WAAA,CACG,GAAG,aACH,MAAOlB,EACP,SAAWoB,GAAMnB,EAAQmB,EAAE,OAAO,KAAK,EACvC,YAAY,0BACZ,UAAU,wFAAA,CAAA,CACd,EACJ,EACCF,EAAAA,IAAC,MAAA,CAAI,UAAU,gBACZ,SAAAA,EAAAA,IAAC,SAAA,CACG,QAAST,EACT,SAAUJ,EACV,UAAU,iFAET,SAAAA,EAAYa,EAAAA,IAACG,EAAA,CAAA,CAAe,EAAK,gBAAA,CAAA,EAE1C,EACAJ,EAAAA,KAAC,MAAA,CAAI,UAAU,+BACX,SAAA,CAAAC,EAAAA,IAAC,QAAA,CAAM,UAAU,+CAA+C,SAAA,cAAW,EAC3ED,EAAAA,KAAC,MAAA,CAAI,UAAU,8EACV,SAAA,CAAAZ,GAAa,CAACF,GAAUe,EAAAA,IAAC,MAAA,CAAI,UAAU,0CAA0C,SAAAA,EAAAA,IAACG,IAAe,CAAA,CAAE,EACnGd,GAASW,EAAAA,IAAC,IAAA,CAAE,UAAU,eAAgB,SAAAX,EAAM,EAC5CJ,GAAUe,EAAAA,IAACI,EAAA,CAAiB,QAASnB,CAAA,CAAQ,EAC5C,CAACE,GAAa,CAACF,GAAU,CAACI,GAASW,EAAAA,IAAC,MAAA,CAAI,UAAU,8DAA8D,SAAA,0BAAA,CAAwB,CAAA,CAAA,CAC9I,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,EACJ,CAER"}
assets/CodeSpellChecker-BolIHiVP.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import{r as o,j as e,R as c}from"./react-DKy9e2uO.js";import{B as l}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 i=["funtion","functoin","funciton","contructor","cosntructor","consle","conosle","cosnole","varable","varaible","vairable","docment","docuemnt","docmunet","componnet","componenet","compnent","retunr","retrun","asnyc","asycn","awai","awiat","promse","resolv","rejct","catach","thne","lenght","lengt","prperty","undefinded","nul","booleon","numbar","srtring","arrya","objcet","elemnt","attriubte","eveent","listner","handeler","clieck","submitt","resposne","requset","stauts","eror","sucess","implemnt","overide","extned","pbulic","prvate","procted","statci","abstact","interace","enmu","moduel","packge","importt","exprot","defualt","namspace","tyep","clsas","whiel","swich","cse","brek","contiune","thrwo","finnaly"],r=new RegExp(`\\b(${i.join("|")})\\b`,"gi"),m=c.memo(({text:t})=>{const s=o.useMemo(()=>t.split(r).map((n,a)=>r.test(n)?e.jsx("span",{className:"underline decoration-red-500 decoration-wavy",title:"Possible typo",children:n},a):n),[t]);return e.jsx(e.Fragment,{children:s})}),j=()=>{const[t,s]=o.useState(`funtion myFunction() {
2
+ consle.log("Hello World");
3
+ const myVarable = docment.getElementById("root");
4
+ // This is a React componnet
5
+ }`);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 flex items-center",children:[e.jsx(l,{}),e.jsx("span",{className:"ml-3",children:"Code Spell Checker"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"A simple tool that finds and highlights common typos in code."})]}),e.jsxs("div",{className:"relative flex-grow font-mono text-sm bg-surface border border-border rounded-lg p-4 overflow-auto",children:[e.jsx("textarea",{value:t,onChange:n=>s(n.target.value),className:"absolute inset-0 w-full h-full p-4 bg-transparent text-transparent caret-primary resize-none z-10",spellCheck:"false"}),e.jsx("pre",{className:"absolute inset-0 w-full h-full p-4 pointer-events-none whitespace-pre-wrap","aria-hidden":"true",children:e.jsx(m,{text:t})})]}),e.jsx("p",{className:"text-xs text-text-secondary mt-2 text-center",children:"This checker uses a predefined list of common typos and does not use AI."})]})};export{j as CodeSpellChecker};
6
+ //# sourceMappingURL=CodeSpellChecker-BolIHiVP.js.map
assets/CodeSpellChecker-BolIHiVP.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CodeSpellChecker-BolIHiVP.js","sources":["../../components/features/CodeSpellChecker.tsx"],"sourcesContent":["import React, { useState, useMemo } from 'react';\nimport { BeakerIcon } from '../icons.tsx';\n\nconst commonTypos = [\n 'funtion', 'functoin', 'funciton', 'contructor', 'cosntructor',\n 'consle', 'conosle', 'cosnole', 'varable', 'varaible', 'vairable',\n 'docment', 'docuemnt', 'docmunet', 'componnet', 'componenet', 'compnent',\n 'retunr', 'retrun', 'asnyc', 'asycn', 'awai', 'awiat', 'promse',\n 'resolv', 'rejct', 'catach', 'thne', 'lenght', 'lengt', 'prperty',\n 'undefinded', 'nul', 'booleon', 'numbar', 'srtring', 'arrya', 'objcet',\n 'elemnt', 'attriubte', 'eveent', 'listner', 'handeler', 'clieck',\n 'submitt', 'resposne', 'requset', 'stauts', 'eror', 'sucess',\n 'implemnt', 'overide', 'extned', 'pbulic', 'prvate', 'procted',\n 'statci', 'abstact', 'interace', 'enmu', 'moduel', 'packge',\n 'importt', 'exprot', 'defualt', 'namspace', 'tyep', 'clsas',\n 'whiel', 'swich', 'cse', 'brek', 'contiune', 'thrwo', 'finnaly'\n];\n\nconst typoRegex = new RegExp(`\\\\b(${commonTypos.join('|')})\\\\b`, 'gi');\n\nconst HighlightedText: React.FC<{ text: string }> = React.memo(({ text }) => {\n const parts = useMemo(() => {\n return text.split(typoRegex).map((part, i) => {\n if (typoRegex.test(part)) {\n return <span key={i} className=\"underline decoration-red-500 decoration-wavy\" title={`Possible typo`}>{part}</span>;\n }\n return part;\n });\n }, [text]);\n\n return <>{parts}</>;\n});\n\nexport const CodeSpellChecker: React.FC = () => {\n const [code, setCode] = useState('funtion myFunction() {\\n consle.log(\"Hello World\");\\n const myVarable = docment.getElementById(\"root\");\\n // This is a React componnet\\n}');\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl flex items-center\">\n <BeakerIcon />\n <span className=\"ml-3\">Code Spell Checker</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">A simple tool that finds and highlights common typos in code.</p>\n </header>\n <div className=\"relative flex-grow font-mono text-sm bg-surface border border-border rounded-lg p-4 overflow-auto\">\n <textarea\n value={code}\n onChange={(e) => setCode(e.target.value)}\n className=\"absolute inset-0 w-full h-full p-4 bg-transparent text-transparent caret-primary resize-none z-10\"\n spellCheck=\"false\"\n />\n <pre className=\"absolute inset-0 w-full h-full p-4 pointer-events-none whitespace-pre-wrap\" aria-hidden=\"true\">\n <HighlightedText text={code} />\n </pre>\n </div>\n <p className=\"text-xs text-text-secondary mt-2 text-center\">This checker uses a predefined list of common typos and does not use AI.</p>\n </div>\n );\n};"],"names":["commonTypos","typoRegex","HighlightedText","React","text","parts","useMemo","part","i","CodeSpellChecker","code","setCode","useState","jsxs","jsx","BeakerIcon","e"],"mappings":"gTAGA,MAAMA,EAAc,CAChB,UAAW,WAAY,WAAY,aAAc,cACjD,SAAU,UAAW,UAAW,UAAW,WAAY,WACvD,UAAW,WAAY,WAAY,YAAa,aAAc,WAC9D,SAAU,SAAU,QAAS,QAAS,OAAQ,QAAS,SACvD,SAAU,QAAS,SAAU,OAAQ,SAAU,QAAS,UACxD,aAAc,MAAO,UAAW,SAAU,UAAW,QAAS,SAC9D,SAAU,YAAa,SAAU,UAAW,WAAY,SACxD,UAAW,WAAY,UAAW,SAAU,OAAQ,SACpD,WAAY,UAAW,SAAU,SAAU,SAAU,UACrD,SAAU,UAAW,WAAY,OAAQ,SAAU,SACnD,UAAW,SAAU,UAAW,WAAY,OAAQ,QACpD,QAAS,QAAS,MAAO,OAAQ,WAAY,QAAS,SAC1D,EAEMC,EAAY,IAAI,OAAO,OAAOD,EAAY,KAAK,GAAG,CAAC,OAAQ,IAAI,EAE/DE,EAA8CC,EAAM,KAAK,CAAC,CAAE,KAAAC,KAAW,CACzE,MAAMC,EAAQC,EAAAA,QAAQ,IACXF,EAAK,MAAMH,CAAS,EAAE,IAAI,CAACM,EAAMC,IAChCP,EAAU,KAAKM,CAAI,QACX,OAAA,CAAa,UAAU,+CAA+C,MAAO,gBAAkB,YAArFC,CAA0F,EAEzGD,CACV,EACF,CAACH,CAAI,CAAC,EAET,yBAAU,SAAAC,CAAA,CAAM,CACpB,CAAC,EAEYI,EAA6B,IAAM,CAC5C,KAAM,CAACC,EAAMC,CAAO,EAAIC,EAAAA,SAAS;AAAA;AAAA;AAAA;AAAA,EAA8I,EAE/K,OACIC,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,6BACV,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAW,EACZD,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,oBAAA,CAAkB,CAAA,EAC7C,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,+DAAA,CAA6D,CAAA,EACzG,EACAD,EAAAA,KAAC,MAAA,CAAI,UAAU,oGACX,SAAA,CAAAC,EAAAA,IAAC,WAAA,CACG,MAAOJ,EACP,SAAWM,GAAML,EAAQK,EAAE,OAAO,KAAK,EACvC,UAAU,oGACV,WAAW,OAAA,CAAA,EAEfF,EAAAA,IAAC,MAAA,CAAI,UAAU,6EAA6E,cAAY,OACpG,SAAAA,EAAAA,IAACZ,EAAA,CAAgB,KAAMQ,CAAA,CAAM,CAAA,CACjC,CAAA,EACJ,EACCI,EAAAA,IAAC,IAAA,CAAE,UAAU,+CAA+C,SAAA,0EAAA,CAAwE,CAAA,EACzI,CAER"}
assets/ColorPaletteGenerator-Cvsu53-R.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r,j as e}from"./react-DKy9e2uO.js";import{Z as u}from"./react-colorful-4Kqy2sC7.js";import{V as b,S as h,L as c}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 A=()=>{const[s,i]=r.useState("#0047AB"),[d,m]=r.useState(["#0047AB","#3366CC","#6688D1","#99AADD","#CCD3E8","#F0F2F5"]),[a,o]=r.useState(!1),[l,n]=r.useState(""),x=r.useCallback(async()=>{o(!0),n("");try{const t=await b(s);m(t.colors)}catch(t){const f=t instanceof Error?t.message:"An unknown error occurred.";n(`Failed to generate palette: ${f}`)}finally{o(!1)}},[s]),p=t=>{navigator.clipboard.writeText(t)};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 text-center",children:[e.jsxs("h1",{className:"text-3xl font-bold flex items-center justify-center",children:[e.jsx(h,{}),e.jsx("span",{className:"ml-3",children:"AI Color Palette Generator"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Pick a base color and let Gemini design a beautiful palette for you."})]}),e.jsxs("div",{className:"flex-grow flex flex-col md:flex-row items-center justify-center gap-8",children:[e.jsxs("div",{className:"flex flex-col items-center gap-4",children:[e.jsx(u,{color:s,onChange:i,className:"!w-64 !h-64"}),e.jsx("div",{className:"p-2 bg-surface rounded-md font-mono text-lg border border-border",style:{color:s},children:s}),e.jsx("button",{onClick:x,disabled:a,className:"btn-primary w-full flex items-center justify-center px-6 py-3",children:a?e.jsx(c,{}):"Generate Palette"}),l&&e.jsx("p",{className:"text-red-500 text-sm mt-2",children:l})]}),e.jsxs("div",{className:"flex flex-col gap-2 w-full max-w-sm",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"Generated Palette:"}),a?e.jsx("div",{className:"flex items-center justify-center h-48",children:e.jsx(c,{})}):d.map(t=>e.jsxs("div",{className:"group flex items-center justify-between p-4 rounded-md shadow-md border border-border",style:{backgroundColor:t},children:[e.jsx("span",{className:"font-mono font-bold text-black/70 mix-blend-overlay",children:t}),e.jsx("button",{onClick:()=>p(t),className:"opacity-0 group-hover:opacity-100 transition-opacity bg-white/30 hover:bg-white/50 px-3 py-1 rounded text-xs text-black font-semibold backdrop-blur-sm",children:"Copy"})]},t))]})]})]})};export{A as ColorPaletteGenerator};
2
+ //# sourceMappingURL=ColorPaletteGenerator-Cvsu53-R.js.map
assets/ColorPaletteGenerator-Cvsu53-R.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"ColorPaletteGenerator-Cvsu53-R.js","sources":["../../components/features/ColorPaletteGenerator.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { HexColorPicker } from 'react-colorful';\nimport { generateColorPalette } from '../../services/index.ts';\nimport { SparklesIcon } from '../icons.tsx';\nimport { LoadingSpinner } from '../shared/index.tsx';\n\nexport const ColorPaletteGenerator: React.FC = () => {\n const [baseColor, setBaseColor] = useState(\"#0047AB\");\n const [palette, setPalette] = useState<string[]>(['#0047AB', '#3366CC', '#6688D1', '#99AADD', '#CCD3E8', '#F0F2F5']);\n const [isLoading, setIsLoading] = useState<boolean>(false);\n const [error, setError] = useState<string>('');\n\n const handleGenerate = useCallback(async () => {\n setIsLoading(true);\n setError('');\n try {\n const result = await generateColorPalette(baseColor);\n setPalette(result.colors);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'An unknown error occurred.';\n setError(`Failed to generate palette: ${errorMessage}`);\n } finally {\n setIsLoading(false);\n }\n }, [baseColor]);\n\n const handleCopy = (color: string) => {\n navigator.clipboard.writeText(color);\n };\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6 text-center\">\n <h1 className=\"text-3xl font-bold flex items-center justify-center\">\n <SparklesIcon />\n <span className=\"ml-3\">AI Color Palette Generator</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Pick a base color and let Gemini design a beautiful palette for you.</p>\n </header>\n <div className=\"flex-grow flex flex-col md:flex-row items-center justify-center gap-8\">\n <div className=\"flex flex-col items-center gap-4\">\n <HexColorPicker color={baseColor} onChange={setBaseColor} className=\"!w-64 !h-64\"/>\n <div className=\"p-2 bg-surface rounded-md font-mono text-lg border border-border\" style={{color: baseColor}}>{baseColor}</div>\n <button\n onClick={handleGenerate}\n disabled={isLoading}\n className=\"btn-primary w-full flex items-center justify-center px-6 py-3\"\n >\n {isLoading ? <LoadingSpinner /> : 'Generate Palette'}\n </button>\n {error && <p className=\"text-red-500 text-sm mt-2\">{error}</p>}\n </div>\n <div className=\"flex flex-col gap-2 w-full max-w-sm\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">Generated Palette:</label>\n {isLoading ? (\n <div className=\"flex items-center justify-center h-48\"><LoadingSpinner /></div>\n ) : (\n palette.map((color) => (\n <div key={color} className=\"group flex items-center justify-between p-4 rounded-md shadow-md border border-border\" style={{ backgroundColor: color }}>\n <span className=\"font-mono font-bold text-black/70 mix-blend-overlay\">{color}</span>\n <button\n onClick={() => handleCopy(color)}\n className=\"opacity-0 group-hover:opacity-100 transition-opacity bg-white/30 hover:bg-white/50 px-3 py-1 rounded text-xs text-black font-semibold backdrop-blur-sm\">\n Copy\n </button>\n </div>\n ))\n )}\n </div>\n </div>\n </div>\n );\n};"],"names":["ColorPaletteGenerator","baseColor","setBaseColor","useState","palette","setPalette","isLoading","setIsLoading","error","setError","handleGenerate","useCallback","result","generateColorPalette","err","errorMessage","handleCopy","color","jsxs","jsx","SparklesIcon","HexColorPicker","LoadingSpinner"],"mappings":"mWAMO,MAAMA,EAAkC,IAAM,CACjD,KAAM,CAACC,EAAWC,CAAY,EAAIC,EAAAA,SAAS,SAAS,EAC9C,CAACC,EAASC,CAAU,EAAIF,EAAAA,SAAmB,CAAC,UAAW,UAAW,UAAW,UAAW,UAAW,SAAS,CAAC,EAC7G,CAACG,EAAWC,CAAY,EAAIJ,EAAAA,SAAkB,EAAK,EACnD,CAACK,EAAOC,CAAQ,EAAIN,EAAAA,SAAiB,EAAE,EAEvCO,EAAiBC,EAAAA,YAAY,SAAY,CAC3CJ,EAAa,EAAI,EACjBE,EAAS,EAAE,EACX,GAAI,CACA,MAAMG,EAAS,MAAMC,EAAqBZ,CAAS,EACnDI,EAAWO,EAAO,MAAM,CAC5B,OAASE,EAAK,CACV,MAAMC,EAAeD,aAAe,MAAQA,EAAI,QAAU,6BAC1DL,EAAS,+BAA+BM,CAAY,EAAE,CAC1D,QAAA,CACIR,EAAa,EAAK,CACtB,CACJ,EAAG,CAACN,CAAS,CAAC,EAERe,EAAcC,GAAkB,CAClC,UAAU,UAAU,UAAUA,CAAK,CACvC,EAEA,OACIC,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,mBACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,sDACV,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAa,EACdD,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,4BAAA,CAA0B,CAAA,EACrD,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,sEAAA,CAAoE,CAAA,EAChH,EACAD,EAAAA,KAAC,MAAA,CAAI,UAAU,wEACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,mCACV,SAAA,CAAAC,MAACE,GAAe,MAAOpB,EAAW,SAAUC,EAAc,UAAU,cAAa,EACjFiB,EAAAA,IAAC,OAAI,UAAU,mEAAmE,MAAO,CAAC,MAAOlB,CAAA,EAAa,SAAAA,CAAA,CAAU,EACvHkB,EAAAA,IAAC,SAAA,CACC,QAAST,EACT,SAAUJ,EACV,UAAU,gEAET,SAAAA,EAAYa,EAAAA,IAACG,EAAA,CAAA,CAAe,EAAK,kBAAA,CAAA,EAErCd,GAASW,EAAAA,IAAC,IAAA,CAAE,UAAU,4BAA6B,SAAAX,CAAA,CAAM,CAAA,EAC9D,EACAU,EAAAA,KAAC,MAAA,CAAI,UAAU,sCACX,SAAA,CAAAC,EAAAA,IAAC,QAAA,CAAM,UAAU,+CAA+C,SAAA,qBAAkB,EACjFb,QACK,MAAA,CAAI,UAAU,wCAAwC,SAAAa,MAACG,EAAA,CAAA,CAAe,EAAE,EAE1ElB,EAAQ,IAAKa,UACR,MAAA,CAAgB,UAAU,wFAAwF,MAAO,CAAE,gBAAiBA,CAAA,EACzI,SAAA,CAAAE,EAAAA,IAAC,OAAA,CAAK,UAAU,sDAAuD,SAAAF,EAAM,EAC7EE,EAAAA,IAAC,SAAA,CACG,QAAS,IAAMH,EAAWC,CAAK,EAC/B,UAAU,yJAAyJ,SAAA,MAAA,CAAA,CAEvK,CAAA,EANMA,CAOV,CACH,CAAA,CAAA,CAET,CAAA,CAAA,CACJ,CAAA,EACJ,CAER"}
assets/CronJobBuilder-DxMd1_TG.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as t,j as e}from"./react-DKy9e2uO.js";import{x as C,y as N,L as S,S as k}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 c=({label:o,value:n,onChange:i,options:l})=>e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-text-secondary",children:o}),e.jsxs("select",{value:n,onChange:a=>i(a.target.value),className:"w-full mt-1 px-3 py-2 rounded-md bg-surface border border-border",children:[e.jsx("option",{value:"*",children:"* (every)"}),l.map(a=>e.jsx("option",{value:a,children:a},a))]})]}),$=({initialPrompt:o})=>{const[n,i]=t.useState("0"),[l,a]=t.useState("17"),[d,p]=t.useState("*"),[x,h]=t.useState("*"),[m,g]=t.useState("1-5"),[b,y]=t.useState(o||"every weekday at 5pm"),[f,j]=t.useState(!1),v=t.useMemo(()=>`${n} ${l} ${d} ${x} ${m}`,[n,l,d,x,m]),u=t.useCallback(async r=>{if(r){j(!0);try{const s=await C(r);i(s.minute),a(s.hour),p(s.dayOfMonth),h(s.month),g(s.dayOfWeek)}catch(s){console.error(s)}finally{j(!1)}}},[]);return t.useEffect(()=>{o&&(y(o),u(o))},[o,u]),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(N,{}),e.jsx("span",{className:"ml-3",children:"AI Cron Job Builder"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Visually construct a cron expression or describe it in plain English."})]}),e.jsxs("div",{className:"flex gap-2 mb-6",children:[e.jsx("input",{type:"text",value:b,onChange:r=>y(r.target.value),placeholder:"Describe a schedule...",className:"flex-grow px-3 py-1.5 rounded-md bg-surface border border-border text-sm"}),e.jsxs("button",{onClick:()=>u(b),disabled:f,className:"btn-primary px-4 py-1.5 flex items-center gap-2",children:[f?e.jsx(S,{}):e.jsx(k,{})," AI Generate"]})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-5 gap-4 mb-6",children:[e.jsx(c,{label:"Minute",value:n,onChange:i,options:Array.from({length:60},(r,s)=>s)}),e.jsx(c,{label:"Hour",value:l,onChange:a,options:Array.from({length:24},(r,s)=>s)}),e.jsx(c,{label:"Day (Month)",value:d,onChange:p,options:Array.from({length:31},(r,s)=>s+1)}),e.jsx(c,{label:"Month",value:x,onChange:h,options:Array.from({length:12},(r,s)=>s+1)}),e.jsx(c,{label:"Day (Week)",value:m,onChange:g,options:Array.from({length:7},(r,s)=>s)})]}),e.jsxs("div",{className:"bg-surface p-4 rounded-lg text-center border border-border",children:[e.jsx("p",{className:"text-text-secondary text-sm",children:"Generated Expression"}),e.jsx("p",{className:"font-mono text-primary text-2xl mt-1",children:v}),e.jsx("button",{onClick:()=>navigator.clipboard.writeText(v),className:"mt-4 px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-md text-xs",children:"Copy"})]})]})};export{$ as CronJobBuilder};
2
+ //# sourceMappingURL=CronJobBuilder-DxMd1_TG.js.map
assets/CronJobBuilder-DxMd1_TG.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CronJobBuilder-DxMd1_TG.js","sources":["../../components/features/CronJobBuilder.tsx"],"sourcesContent":["import React, { useState, useMemo, useCallback, useEffect } from 'react';\nimport { CommandLineIcon, SparklesIcon } from '../icons.tsx';\nimport { generateCronFromDescription, CronParts } from '../../services/index.ts';\nimport { LoadingSpinner } from '../shared/index.tsx';\n\nconst CronPartSelector: React.FC<{ label: string, value: string, onChange: (value: string) => void, options: (string|number)[] }> = ({ label, value, onChange, options }) => {\n return (\n <div>\n <label className=\"block text-sm font-medium text-text-secondary\">{label}</label>\n <select value={value} onChange={e => onChange(e.target.value)} className=\"w-full mt-1 px-3 py-2 rounded-md bg-surface border border-border\">\n <option value=\"*\">* (every)</option>\n {options.map(o => <option key={o} value={o}>{o}</option>)}\n </select>\n </div>\n );\n};\n\nexport const CronJobBuilder: React.FC<{ initialPrompt?: string }> = ({ initialPrompt }) => {\n const [minute, setMinute] = useState('0');\n const [hour, setHour] = useState('17');\n const [dayOfMonth, setDayOfMonth] = useState('*');\n const [month, setMonth] = useState('*');\n const [dayOfWeek, setDayOfWeek] = useState('1-5');\n const [aiPrompt, setAiPrompt] = useState(initialPrompt || 'every weekday at 5pm');\n const [isLoading, setIsLoading] = useState(false);\n \n const cronExpression = useMemo(() => {\n return `${minute} ${hour} ${dayOfMonth} ${month} ${dayOfWeek}`;\n }, [minute, hour, dayOfMonth, month, dayOfWeek]);\n\n const handleAiGenerate = useCallback(async (p: string) => {\n if (!p) return;\n setIsLoading(true);\n try {\n const result: CronParts = await generateCronFromDescription(p);\n setMinute(result.minute);\n setHour(result.hour);\n setDayOfMonth(result.dayOfMonth);\n setMonth(result.month);\n setDayOfWeek(result.dayOfWeek);\n } catch (e) {\n console.error(e);\n } finally {\n setIsLoading(false);\n }\n }, []);\n\n useEffect(() => {\n if (initialPrompt) {\n setAiPrompt(initialPrompt);\n handleAiGenerate(initialPrompt);\n }\n }, [initialPrompt, handleAiGenerate]);\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <CommandLineIcon />\n <span className=\"ml-3\">AI Cron Job Builder</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Visually construct a cron expression or describe it in plain English.</p>\n </header>\n <div className=\"flex gap-2 mb-6\">\n <input type=\"text\" value={aiPrompt} onChange={e => setAiPrompt(e.target.value)} placeholder=\"Describe a schedule...\" className=\"flex-grow px-3 py-1.5 rounded-md bg-surface border border-border text-sm\"/>\n <button onClick={() => handleAiGenerate(aiPrompt)} disabled={isLoading} className=\"btn-primary px-4 py-1.5 flex items-center gap-2\">\n {isLoading ? <LoadingSpinner /> : <SparklesIcon />} AI Generate\n </button>\n </div>\n <div className=\"grid grid-cols-2 md:grid-cols-5 gap-4 mb-6\">\n <CronPartSelector label=\"Minute\" value={minute} onChange={setMinute} options={Array.from({length: 60}, (_, i) => i)} />\n <CronPartSelector label=\"Hour\" value={hour} onChange={setHour} options={Array.from({length: 24}, (_, i) => i)} />\n <CronPartSelector label=\"Day (Month)\" value={dayOfMonth} onChange={setDayOfMonth} options={Array.from({length: 31}, (_, i) => i + 1)} />\n <CronPartSelector label=\"Month\" value={month} onChange={setMonth} options={Array.from({length: 12}, (_, i) => i + 1)} />\n <CronPartSelector label=\"Day (Week)\" value={dayOfWeek} onChange={setDayOfWeek} options={Array.from({length: 7}, (_, i) => i)} />\n </div>\n <div className=\"bg-surface p-4 rounded-lg text-center border border-border\">\n <p className=\"text-text-secondary text-sm\">Generated Expression</p>\n <p className=\"font-mono text-primary text-2xl mt-1\">{cronExpression}</p>\n <button onClick={() => navigator.clipboard.writeText(cronExpression)} className=\"mt-4 px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-md text-xs\">Copy</button>\n </div>\n </div>\n );\n};"],"names":["CronPartSelector","label","value","onChange","options","jsx","jsxs","e","o","CronJobBuilder","initialPrompt","minute","setMinute","useState","hour","setHour","dayOfMonth","setDayOfMonth","month","setMonth","dayOfWeek","setDayOfWeek","aiPrompt","setAiPrompt","isLoading","setIsLoading","cronExpression","useMemo","handleAiGenerate","useCallback","p","result","generateCronFromDescription","useEffect","CommandLineIcon","LoadingSpinner","SparklesIcon","_","i"],"mappings":"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"}
assets/CssGridEditor-Tggo3uo4.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import{r as n,j as e}from"./react-DKy9e2uO.js";import{i as y,A as f,j}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 r={rows:3,cols:4,rowGap:1,colGap:1},F=()=>{const[a,c]=n.useState(r.rows),[t,i]=n.useState(r.cols),[l,m]=n.useState(r.rowGap),[o,x]=n.useState(r.colGap),g={display:"grid",gridTemplateColumns:`repeat(${t}, 1fr)`,gridTemplateRows:`repeat(${a}, 1fr)`,gap:`${l}rem ${o}rem`,height:"100%",width:"100%"},d=n.useMemo(()=>`.grid-container {
2
+ display: grid;
3
+ grid-template-columns: repeat(${t}, 1fr);
4
+ grid-template-rows: repeat(${a}, 1fr);
5
+ gap: ${l}rem ${o}rem;
6
+ }`,[a,t,l,o]),u=()=>{navigator.clipboard.writeText(d)},h=()=>{j(d,"grid.css","text/css")},b=()=>{c(r.rows),i(r.cols),m(r.rowGap),x(r.colGap)};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:"CSS Grid Visual Editor"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Configure your grid layout and copy the generated CSS."})]}),e.jsxs("div",{className:"flex-grow grid grid-cols-1 lg:grid-cols-3 gap-6 min-h-0",children:[e.jsxs("div",{className:"lg:col-span-1 flex flex-col gap-4 bg-surface border border-border p-6 rounded-lg overflow-y-auto",children:[e.jsxs("div",{className:"flex justify-between items-center",children:[e.jsx("h3",{className:"text-xl font-bold",children:"Controls"}),e.jsx("button",{onClick:b,className:"text-xs px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-md",children:"Reset"})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsxs("label",{htmlFor:"rows",className:"block text-sm font-medium text-text-secondary",children:["Rows (",a,")"]}),e.jsx("input",{id:"rows",type:"range",min:"1",max:"12",value:a,onChange:s=>c(Number(s.target.value)),className:"w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"})]}),e.jsxs("div",{children:[e.jsxs("label",{htmlFor:"cols",className:"block text-sm font-medium text-text-secondary",children:["Columns (",t,")"]}),e.jsx("input",{id:"cols",type:"range",min:"1",max:"12",value:t,onChange:s=>i(Number(s.target.value)),className:"w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"})]}),e.jsxs("div",{children:[e.jsxs("label",{htmlFor:"rowGap",className:"block text-sm font-medium text-text-secondary",children:["Row Gap (",l,"rem)"]}),e.jsx("input",{id:"rowGap",type:"range",min:"0",max:"8",step:"0.25",value:l,onChange:s=>m(Number(s.target.value)),className:"w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"})]}),e.jsxs("div",{children:[e.jsxs("label",{htmlFor:"colGap",className:"block text-sm font-medium text-text-secondary",children:["Column Gap (",o,"rem)"]}),e.jsx("input",{id:"colGap",type:"range",min:"0",max:"8",step:"0.25",value:o,onChange:s=>x(Number(s.target.value)),className:"w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer"})]})]}),e.jsxs("div",{className:"flex-grow mt-4 flex flex-col min-h-[150px]",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 CSS"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{onClick:u,className:"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md text-xs",children:"Copy"}),e.jsxs("button",{onClick:h,className:"flex items-center gap-1 px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md text-xs",children:[e.jsx(f,{className:"w-4 h-4"})," Download"]})]})]}),e.jsx("div",{className:"relative flex-grow",children:e.jsx("pre",{className:"bg-background p-4 rounded-md text-primary text-sm overflow-auto h-full w-full absolute",children:d})})]})]}),e.jsx("div",{className:"lg:col-span-2 bg-background rounded-lg p-4 border-2 border-dashed border-border",children:e.jsx("div",{style:g,children:Array.from({length:a*t}).map((s,p)=>e.jsx("div",{className:"bg-primary/10 rounded-lg border-2 border-dashed border-primary/50 flex items-center justify-center text-primary",children:e.jsx("span",{className:"text-xs opacity-70",children:p+1})},p))})})]})]})};export{F as CssGridEditor};
7
+ //# sourceMappingURL=CssGridEditor-Tggo3uo4.js.map
assets/CssGridEditor-Tggo3uo4.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CssGridEditor-Tggo3uo4.js","sources":["../../components/features/CssGridEditor.tsx"],"sourcesContent":["import React, { useState, useMemo } from 'react';\nimport { CodeBracketSquareIcon, ArrowDownTrayIcon } from '../icons.tsx';\nimport { downloadFile } from '../../services/index.ts';\n\nconst initialSettings = { rows: 3, cols: 4, rowGap: 1, colGap: 1 };\n\nexport const CssGridEditor: React.FC = () => {\n const [rows, setRows] = useState(initialSettings.rows);\n const [cols, setCols] = useState(initialSettings.cols);\n const [rowGap, setRowGap] = useState(initialSettings.rowGap);\n const [colGap, setColGap] = useState(initialSettings.colGap);\n\n const gridStyle = {\n display: 'grid',\n gridTemplateColumns: `repeat(${cols}, 1fr)`,\n gridTemplateRows: `repeat(${rows}, 1fr)`,\n gap: `${rowGap}rem ${colGap}rem`,\n height: '100%',\n width: '100%'\n };\n\n const cssCode = useMemo(() => {\n return `.grid-container {\n display: grid;\n grid-template-columns: repeat(${cols}, 1fr);\n grid-template-rows: repeat(${rows}, 1fr);\n gap: ${rowGap}rem ${colGap}rem;\n}`;\n }, [rows, cols, rowGap, colGap]);\n \n const handleCopy = () => {\n navigator.clipboard.writeText(cssCode);\n };\n \n const handleDownload = () => {\n downloadFile(cssCode, 'grid.css', 'text/css');\n };\n\n const handleReset = () => {\n setRows(initialSettings.rows);\n setCols(initialSettings.cols);\n setRowGap(initialSettings.rowGap);\n setColGap(initialSettings.colGap);\n };\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <CodeBracketSquareIcon />\n <span className=\"ml-3\">CSS Grid Visual Editor</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Configure your grid layout and copy the generated CSS.</p>\n </header>\n <div className=\"flex-grow grid grid-cols-1 lg:grid-cols-3 gap-6 min-h-0\">\n <div className=\"lg:col-span-1 flex flex-col gap-4 bg-surface border border-border p-6 rounded-lg overflow-y-auto\">\n <div className=\"flex justify-between items-center\">\n <h3 className=\"text-xl font-bold\">Controls</h3>\n <button onClick={handleReset} className=\"text-xs px-3 py-1 bg-gray-100 hover:bg-gray-200 rounded-md\">Reset</button>\n </div>\n <div className=\"space-y-4\">\n <div>\n <label htmlFor=\"rows\" className=\"block text-sm font-medium text-text-secondary\">Rows ({rows})</label>\n <input id=\"rows\" type=\"range\" min=\"1\" max=\"12\" value={rows} onChange={e => setRows(Number(e.target.value))} className=\"w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer\" />\n </div>\n <div>\n <label htmlFor=\"cols\" className=\"block text-sm font-medium text-text-secondary\">Columns ({cols})</label>\n <input id=\"cols\" type=\"range\" min=\"1\" max=\"12\" value={cols} onChange={e => setCols(Number(e.target.value))} className=\"w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer\" />\n </div>\n <div>\n <label htmlFor=\"rowGap\" className=\"block text-sm font-medium text-text-secondary\">Row Gap ({rowGap}rem)</label>\n <input id=\"rowGap\" type=\"range\" min=\"0\" max=\"8\" step=\"0.25\" value={rowGap} onChange={e => setRowGap(Number(e.target.value))} className=\"w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer\" />\n </div>\n <div>\n <label htmlFor=\"colGap\" className=\"block text-sm font-medium text-text-secondary\">Column Gap ({colGap}rem)</label>\n <input id=\"colGap\" type=\"range\" min=\"0\" max=\"8\" step=\"0.25\" value={colGap} onChange={e => setColGap(Number(e.target.value))} className=\"w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer\" />\n </div>\n </div>\n <div className=\"flex-grow mt-4 flex flex-col min-h-[150px]\">\n <div className=\"flex justify-between items-center mb-2\">\n <label className=\"text-sm font-medium text-text-secondary\">Generated CSS</label>\n <div className=\"flex gap-2\">\n <button onClick={handleCopy} className=\"px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md text-xs\">Copy</button>\n <button onClick={handleDownload} className=\"flex items-center gap-1 px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md text-xs\"><ArrowDownTrayIcon className=\"w-4 h-4\"/> Download</button>\n </div>\n </div>\n <div className=\"relative flex-grow\">\n <pre className=\"bg-background p-4 rounded-md text-primary text-sm overflow-auto h-full w-full absolute\">{cssCode}</pre>\n </div>\n </div>\n </div>\n <div className=\"lg:col-span-2 bg-background rounded-lg p-4 border-2 border-dashed border-border\">\n <div style={gridStyle}>\n {Array.from({ length: rows * cols }).map((_, i) => (\n <div key={i} className=\"bg-primary/10 rounded-lg border-2 border-dashed border-primary/50 flex items-center justify-center text-primary\">\n <span className=\"text-xs opacity-70\">{i + 1}</span>\n </div>\n ))}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["initialSettings","CssGridEditor","rows","setRows","useState","cols","setCols","rowGap","setRowGap","colGap","setColGap","gridStyle","cssCode","useMemo","handleCopy","handleDownload","downloadFile","handleReset","jsxs","jsx","CodeBracketSquareIcon","e","ArrowDownTrayIcon","_","i"],"mappings":"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"}
assets/DigitalWhiteboard-mqmKu9Bh.js ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ import{r as c,j as t}from"./react-DKy9e2uO.js";import{u as v,m as k,n as S,S as C,L as z,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 d=["bg-yellow-400","bg-green-400","bg-blue-400","bg-pink-400","bg-purple-400","bg-orange-400"],D=["text-yellow-900","text-green-900","text-blue-900","text-pink-900","text-purple-900","text-orange-900"],W=()=>{const[s,m]=v("devcore_whiteboard_notes",[]),[a,g]=c.useState(null),[n,p]=c.useState(!1),[u,l]=c.useState(""),h=c.useCallback(async()=>{if(s.length!==0){p(!0),l("");try{const e=s.map(i=>`- ${i.text}`).join(`
2
+ `),r=k(e);let o="";for await(const i of r)o+=i,l(o)}catch(e){console.error(e),l("Sorry, an error occurred while summarizing.")}finally{p(!1)}}},[s]),y=()=>{const e={id:Date.now(),text:"New idea...",x:50,y:50,color:d[s.length%d.length]};m([...s,e])},j=(e,r)=>{r.stopPropagation(),m(s.filter(o=>o.id!==e))},x=(e,r)=>{m(s.map(o=>o.id===e?{...o,...r}:o))},N=(e,r)=>{const o=e.target;if(o.tagName==="TEXTAREA"||o.dataset.role==="button")return;const b=e.currentTarget.getBoundingClientRect();g({id:r,offsetX:e.clientX-b.left,offsetY:e.clientY-b.top})},w=e=>{if(!a)return;const r=e.currentTarget.getBoundingClientRect();x(a.id,{x:e.clientX-a.offsetX-r.left,y:e.clientY-a.offsetY-r.top})},f=()=>g(null);return t.jsxs("div",{className:"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary",children:[t.jsxs("header",{className:"mb-6 flex justify-between items-center",children:[t.jsxs("div",{children:[t.jsxs("h1",{className:"text-3xl font-bold flex items-center",children:[t.jsx(S,{}),t.jsx("span",{className:"ml-3",children:"Digital Whiteboard"})]}),t.jsx("p",{className:"text-text-secondary mt-1",children:"Organize your ideas with interactive sticky notes and AI summaries."})]}),t.jsxs("div",{className:"flex gap-2",children:[t.jsxs("button",{onClick:h,disabled:n||s.length===0,className:"btn-primary flex items-center gap-2 px-4 py-2",children:[t.jsx(C,{})," ",n?"Summarizing...":"AI Summarize"]}),t.jsx("button",{onClick:y,className:"btn-primary px-6 py-2",children:"Add Note"})]})]}),t.jsx("div",{className:"relative flex-grow bg-background border-2 border-dashed border-border rounded-lg overflow-hidden",onMouseMove:w,onMouseUp:f,onMouseLeave:f,children:s.map(e=>t.jsxs("div",{className:`group absolute w-56 h-56 p-2 flex flex-col shadow-lg cursor-grab active:cursor-grabbing rounded-md transition-transform duration-100 border border-black/40 ${e.color} ${D[d.indexOf(e.color)]}`,style:{top:e.y,left:e.x,transform:(a==null?void 0:a.id)===e.id?"scale(1.05)":"scale(1)"},onMouseDown:r=>N(r,e.id),children:[t.jsx("button",{"data-role":"button",onClick:r=>j(e.id,r),className:"absolute -top-2 -right-2 w-6 h-6 rounded-full bg-gray-700 text-white font-bold text-xs flex items-center justify-center opacity-0 group-hover:opacity-100 hover:bg-red-500 transition-all",children:"×"}),t.jsx("textarea",{value:e.text,onChange:r=>x(e.id,{text:r.target.value}),className:"w-full h-full bg-transparent resize-none focus:outline-none font-medium p-1"}),t.jsx("div",{"data-role":"button",className:"flex-shrink-0 flex justify-center gap-1 p-1 opacity-0 group-hover:opacity-100 transition-opacity",children:d.map((r,o)=>t.jsx("button",{onClick:()=>x(e.id,{color:r}),className:`w-4 h-4 rounded-full ${r} border border-black/20 ${e.color===r?"ring-2 ring-offset-1 ring-black/50":""}`},r))})]},e.id))}),(n||u)&&t.jsx("div",{className:"fixed inset-0 bg-gray-900/80 backdrop-blur-sm z-50 flex items-center justify-center",onClick:()=>l(""),children:t.jsxs("div",{className:"w-full max-w-2xl bg-surface border border-border rounded-lg shadow-2xl p-6",onClick:e=>e.stopPropagation(),children:[t.jsx("h2",{className:"text-xl font-bold mb-4",children:"AI Summary of Notes"}),n&&!u?t.jsx(z,{}):t.jsx(M,{content:u})]})})]})};export{W as DigitalWhiteboard};
3
+ //# sourceMappingURL=DigitalWhiteboard-mqmKu9Bh.js.map
assets/DigitalWhiteboard-mqmKu9Bh.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"DigitalWhiteboard-mqmKu9Bh.js","sources":["../../components/features/DigitalWhiteboard.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { SparklesIcon, DigitalWhiteboardIcon } from '../icons.tsx';\nimport { useLocalStorage } from '../../hooks/useLocalStorage.ts';\nimport { summarizeNotesStream } from '../../services/index.ts';\nimport { LoadingSpinner } from '../shared/index.tsx';\nimport { MarkdownRenderer } from '../shared/index.tsx';\n\ninterface Note {\n id: number;\n text: string;\n x: number;\n y: number;\n color: string;\n}\n\nconst colors = ['bg-yellow-400', 'bg-green-400', 'bg-blue-400', 'bg-pink-400', 'bg-purple-400', 'bg-orange-400'];\nconst textColors = ['text-yellow-900', 'text-green-900', 'text-blue-900', 'text-pink-900', 'text-purple-900', 'text-orange-900'];\n\nexport const DigitalWhiteboard: React.FC = () => {\n const [notes, setNotes] = useLocalStorage<Note[]>('devcore_whiteboard_notes', []);\n const [dragging, setDragging] = useState<{ id: number; offsetX: number; offsetY: number } | null>(null);\n const [isSummarizing, setIsSummarizing] = useState(false);\n const [summary, setSummary] = useState('');\n\n const handleSummarize = useCallback(async () => {\n if (notes.length === 0) return;\n setIsSummarizing(true);\n setSummary('');\n try {\n const allNotesText = notes.map((n: Note) => `- ${n.text}`).join('\\n');\n const stream = summarizeNotesStream(allNotesText);\n let fullResponse = '';\n for await (const chunk of stream) {\n fullResponse += chunk;\n setSummary(fullResponse);\n }\n } catch (error) {\n console.error(error);\n setSummary('Sorry, an error occurred while summarizing.');\n } finally {\n setIsSummarizing(false);\n }\n }, [notes]);\n\n const addNote = () => {\n const newNote: Note = {\n id: Date.now(),\n text: 'New idea...',\n x: 50,\n y: 50,\n color: colors[notes.length % colors.length],\n };\n setNotes([...notes, newNote]);\n };\n \n const deleteNote = (id: number, e: React.MouseEvent) => {\n e.stopPropagation();\n setNotes(notes.filter((n) => n.id !== id));\n };\n\n const updateNote = (id: number, updates: Partial<Note>) => {\n setNotes(notes.map((n) => n.id === id ? { ...n, ...updates } : n));\n };\n\n const onMouseDown = (e: React.MouseEvent<HTMLDivElement>, id: number) => {\n const target = e.target as HTMLElement;\n if (target.tagName === 'TEXTAREA' || target.dataset.role === 'button') return;\n \n const noteElement = e.currentTarget;\n const rect = noteElement.getBoundingClientRect();\n setDragging({ id, offsetX: e.clientX - rect.left, offsetY: e.clientY - rect.top });\n };\n\n const onMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!dragging) return;\n const boardRect = e.currentTarget.getBoundingClientRect();\n updateNote(dragging.id, {\n x: e.clientX - dragging.offsetX - boardRect.left,\n y: e.clientY - dragging.offsetY - boardRect.top\n });\n };\n\n const onMouseUp = () => setDragging(null);\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6 flex justify-between items-center\">\n <div>\n <h1 className=\"text-3xl font-bold flex items-center\"><DigitalWhiteboardIcon /><span className=\"ml-3\">Digital Whiteboard</span></h1>\n <p className=\"text-text-secondary mt-1\">Organize your ideas with interactive sticky notes and AI summaries.</p>\n </div>\n <div className=\"flex gap-2\">\n <button onClick={handleSummarize} disabled={isSummarizing || notes.length === 0} className=\"btn-primary flex items-center gap-2 px-4 py-2\">\n <SparklesIcon/> {isSummarizing ? 'Summarizing...' : 'AI Summarize'}\n </button>\n <button onClick={addNote} className=\"btn-primary px-6 py-2\">Add Note</button>\n </div>\n </header>\n <div\n className=\"relative flex-grow bg-background border-2 border-dashed border-border rounded-lg overflow-hidden\"\n onMouseMove={onMouseMove} onMouseUp={onMouseUp} onMouseLeave={onMouseUp}\n >\n {notes.map((note) => (\n <div\n key={note.id}\n className={`group absolute w-56 h-56 p-2 flex flex-col shadow-lg cursor-grab active:cursor-grabbing rounded-md transition-transform duration-100 border border-black/40 ${note.color} ${textColors[colors.indexOf(note.color)]}`}\n style={{ top: note.y, left: note.x, transform: dragging?.id === note.id ? 'scale(1.05)' : 'scale(1)' }}\n onMouseDown={e => onMouseDown(e, note.id)}\n >\n <button data-role=\"button\" onClick={(e) => deleteNote(note.id, e)} className=\"absolute -top-2 -right-2 w-6 h-6 rounded-full bg-gray-700 text-white font-bold text-xs flex items-center justify-center opacity-0 group-hover:opacity-100 hover:bg-red-500 transition-all\">&times;</button>\n <textarea\n value={note.text}\n onChange={(e) => updateNote(note.id, { text: e.target.value })}\n className=\"w-full h-full bg-transparent resize-none focus:outline-none font-medium p-1\"\n />\n <div data-role=\"button\" className=\"flex-shrink-0 flex justify-center gap-1 p-1 opacity-0 group-hover:opacity-100 transition-opacity\">\n {colors.map((c, i) => <button key={c} onClick={() => updateNote(note.id, { color: c })} className={`w-4 h-4 rounded-full ${c} border border-black/20 ${note.color === c ? 'ring-2 ring-offset-1 ring-black/50' : ''}`}/>)}\n </div>\n </div>\n ))}\n </div>\n {(isSummarizing || summary) && (\n <div className=\"fixed inset-0 bg-gray-900/80 backdrop-blur-sm z-50 flex items-center justify-center\" onClick={() => setSummary('')}>\n <div className=\"w-full max-w-2xl bg-surface border border-border rounded-lg shadow-2xl p-6\" onClick={e => e.stopPropagation()}>\n <h2 className=\"text-xl font-bold mb-4\">AI Summary of Notes</h2>\n {isSummarizing && !summary ? <LoadingSpinner /> : <MarkdownRenderer content={summary} />}\n </div>\n </div>\n )}\n </div>\n );\n};"],"names":["colors","textColors","DigitalWhiteboard","notes","setNotes","useLocalStorage","dragging","setDragging","useState","isSummarizing","setIsSummarizing","summary","setSummary","handleSummarize","useCallback","allNotesText","n","stream","summarizeNotesStream","fullResponse","chunk","error","addNote","newNote","deleteNote","id","e","updateNote","updates","onMouseDown","target","rect","onMouseMove","boardRect","onMouseUp","jsxs","jsx","DigitalWhiteboardIcon","SparklesIcon","note","c","i","LoadingSpinner","MarkdownRenderer"],"mappings":"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"}
assets/JsonTreeNavigator-wiByc32v.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as p,j as e}from"./react-DKy9e2uO.js";import{F as f}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 u=({data:s,nodeKey:l,isRoot:n=!1})=>{const[r,c]=p.useState(n),i=typeof s=="object"&&s!==null,o=()=>c(!r);if(!i)return e.jsxs("div",{className:"ml-4 pl-4 border-l border-border",children:[e.jsxs("span",{className:"text-purple-700",children:[l,": "]}),e.jsx("span",{className:typeof s=="string"?"text-green-700":"text-orange-700",children:typeof s=="string"?`"${s}"`:String(s)})]});const x=Object.entries(s),a=Array.isArray(s)?"[]":"{}";return e.jsxs("div",{className:`ml-4 ${n?"":"pl-4 border-l border-border"}`,children:[e.jsxs("button",{onClick:o,className:"flex items-center cursor-pointer hover:bg-gray-100 rounded px-1",children:[e.jsx("span",{className:`transform transition-transform ${r?"rotate-90":"rotate-0"}`,children:"▶"}),e.jsxs("span",{className:"ml-1 text-purple-700",children:[l,":"]}),e.jsx("span",{className:"ml-2 text-text-secondary",children:a[0]}),!r&&e.jsxs("span",{className:"text-text-secondary",children:["...",a[1]]})]}),r&&e.jsxs("div",{children:[x.map(([d,t])=>e.jsx(u,{nodeKey:d,data:t},d)),e.jsx("div",{className:"text-text-secondary ml-4",children:a[1]})]})]})},S=({initialData:s})=>{const l=`{
2
+ "id": "devcore-001",
3
+ "active": true,
4
+ "features": [
5
+ "ai-explainer",
6
+ "api-tester"
7
+ ],
8
+ "config": {
9
+ "theme": "dark",
10
+ "version": 1
11
+ }
12
+ }`,[n,r]=p.useState(s?JSON.stringify(s,null,2):l),[c,i]=p.useState(()=>{try{return JSON.parse(n)}catch{return null}}),[o,x]=p.useState(""),a=t=>{try{const m=JSON.parse(t);i(m),x("")}catch(m){m instanceof Error&&x(m.message),i(null)}},d=t=>{r(t.target.value),a(t.target.value)};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(f,{}),e.jsx("span",{className:"ml-3",children:"JSON Tree Navigator"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Paste your JSON data to visualize it as a collapsible tree."})]}),e.jsxs("div",{className:"flex-grow flex flex-col gap-4 min-h-0",children:[e.jsxs("div",{className:"flex flex-col h-2/5 min-h-[200px]",children:[e.jsx("label",{htmlFor:"json-input",className:"text-sm font-medium text-text-secondary mb-2",children:"JSON Input"}),e.jsx("textarea",{id:"json-input",value:n,onChange:d,className:`flex-grow p-4 bg-surface border ${o?"border-red-500":"border-border"} rounded-md resize-y font-mono text-sm focus:ring-2 focus:ring-primary focus:outline-none`}),o&&e.jsx("p",{className:"text-red-500 text-xs mt-1",children:o})]}),e.jsxs("div",{className:"flex flex-col flex-grow min-h-0",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"Tree View"}),e.jsx("div",{className:"flex-grow p-4 bg-surface border border-border rounded-md overflow-y-auto font-mono text-sm",children:c?e.jsx(u,{data:c,nodeKey:"root",isRoot:!0}):e.jsx("div",{className:"text-text-secondary",children:"Enter valid JSON to view"})})]})]})]})};export{S as JsonTreeNavigator};
13
+ //# sourceMappingURL=JsonTreeNavigator-wiByc32v.js.map
assets/JsonTreeNavigator-wiByc32v.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"JsonTreeNavigator-wiByc32v.js","sources":["../../components/features/JsonTreeNavigator.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { FileCodeIcon } from '../icons.tsx';\n\ninterface JsonNodeProps {\n data: any;\n nodeKey: string;\n isRoot?: boolean;\n}\n\nconst JsonNode: React.FC<JsonNodeProps> = ({ data, nodeKey, isRoot = false }) => {\n const [isOpen, setIsOpen] = useState(isRoot);\n const isObject = typeof data === 'object' && data !== null;\n\n const toggleOpen = () => setIsOpen(!isOpen);\n\n if (!isObject) {\n return (\n <div className=\"ml-4 pl-4 border-l border-border\">\n <span className=\"text-purple-700\">{nodeKey}: </span>\n <span className={typeof data === 'string' ? 'text-green-700' : 'text-orange-700'}>\n {typeof data === 'string' ? `\"${data}\"` : String(data)}\n </span>\n </div>\n );\n }\n\n const entries = Object.entries(data);\n const bracket = Array.isArray(data) ? '[]' : '{}';\n\n return (\n <div className={`ml-4 ${!isRoot ? 'pl-4 border-l border-border' : ''}`}>\n <button onClick={toggleOpen} className=\"flex items-center cursor-pointer hover:bg-gray-100 rounded px-1\">\n <span className={`transform transition-transform ${isOpen ? 'rotate-90' : 'rotate-0'}`}>▶</span>\n <span className=\"ml-1 text-purple-700\">{nodeKey}:</span>\n <span className=\"ml-2 text-text-secondary\">{bracket[0]}</span>\n {!isOpen && <span className=\"text-text-secondary\">...{bracket[1]}</span>}\n </button>\n {isOpen && (\n <div>\n {entries.map(([key, value]) => (\n <JsonNode key={key} nodeKey={key} data={value} />\n ))}\n <div className=\"text-text-secondary ml-4\">{bracket[1]}</div>\n </div>\n )}\n </div>\n );\n};\n\nexport const JsonTreeNavigator: React.FC<{ initialData?: object }> = ({ initialData }) => {\n const defaultJson = '{\\n \"id\": \"devcore-001\",\\n \"active\": true,\\n \"features\": [\\n \"ai-explainer\",\\n \"api-tester\"\\n ],\\n \"config\": {\\n \"theme\": \"dark\",\\n \"version\": 1\\n }\\n}';\n const [jsonInput, setJsonInput] = useState(initialData ? JSON.stringify(initialData, null, 2) : defaultJson);\n const [parsedData, setParsedData] = useState<any>(() => {\n try {\n return JSON.parse(jsonInput);\n } catch {\n return null;\n }\n });\n const [error, setError] = useState('');\n\n const parseJson = (input: string) => {\n try {\n const parsed = JSON.parse(input);\n setParsedData(parsed);\n setError('');\n } catch (e) {\n if (e instanceof Error) setError(e.message);\n setParsedData(null);\n }\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setJsonInput(e.target.value);\n parseJson(e.target.value);\n }\n \n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\">\n <FileCodeIcon />\n <span className=\"ml-3\">JSON Tree Navigator</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Paste your JSON data to visualize it as a collapsible tree.</p>\n </header>\n <div className=\"flex-grow flex flex-col gap-4 min-h-0\">\n <div className=\"flex flex-col h-2/5 min-h-[200px]\">\n <label htmlFor=\"json-input\" className=\"text-sm font-medium text-text-secondary mb-2\">JSON Input</label>\n <textarea\n id=\"json-input\"\n value={jsonInput}\n onChange={handleInputChange}\n className={`flex-grow p-4 bg-surface border ${error ? 'border-red-500' : 'border-border'} rounded-md resize-y font-mono text-sm focus:ring-2 focus:ring-primary focus:outline-none`}\n />\n {error && <p className=\"text-red-500 text-xs mt-1\">{error}</p>}\n </div>\n <div className=\"flex flex-col flex-grow min-h-0\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">Tree View</label>\n <div className=\"flex-grow p-4 bg-surface border border-border rounded-md overflow-y-auto font-mono text-sm\">\n {parsedData ? <JsonNode data={parsedData} nodeKey=\"root\" isRoot /> : <div className=\"text-text-secondary\">Enter valid JSON to view</div>}\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["JsonNode","data","nodeKey","isRoot","isOpen","setIsOpen","useState","isObject","toggleOpen","jsxs","entries","bracket","jsx","key","value","JsonTreeNavigator","initialData","defaultJson","jsonInput","setJsonInput","parsedData","setParsedData","error","setError","parseJson","input","parsed","e","handleInputChange","FileCodeIcon"],"mappings":"ySASA,MAAMA,EAAoC,CAAC,CAAE,KAAAC,EAAM,QAAAC,EAAS,OAAAC,EAAS,MAAY,CAC7E,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAASH,CAAM,EACrCI,EAAW,OAAON,GAAS,UAAYA,IAAS,KAEhDO,EAAa,IAAMH,EAAU,CAACD,CAAM,EAE1C,GAAI,CAACG,EACD,OACIE,EAAAA,KAAC,MAAA,CAAI,UAAU,mCACX,SAAA,CAAAA,EAAAA,KAAC,OAAA,CAAK,UAAU,kBAAmB,SAAA,CAAAP,EAAQ,IAAA,EAAE,QAC5C,OAAA,CAAK,UAAW,OAAOD,GAAS,SAAW,iBAAmB,kBAC1D,SAAA,OAAOA,GAAS,SAAW,IAAIA,CAAI,IAAM,OAAOA,CAAI,CAAA,CACzD,CAAA,EACJ,EAIR,MAAMS,EAAU,OAAO,QAAQT,CAAI,EAC7BU,EAAU,MAAM,QAAQV,CAAI,EAAI,KAAO,KAE7C,OACIQ,OAAC,OAAI,UAAW,QAASN,EAAyC,GAAhC,6BAAkC,GAChE,SAAA,CAAAM,EAAAA,KAAC,SAAA,CAAO,QAASD,EAAY,UAAU,kEACnC,SAAA,CAAAI,EAAAA,IAAC,QAAK,UAAW,kCAAkCR,EAAS,YAAc,UAAU,GAAI,SAAA,GAAA,CAAC,EACzFK,EAAAA,KAAC,OAAA,CAAK,UAAU,uBAAwB,SAAA,CAAAP,EAAQ,GAAA,EAAC,QAChD,OAAA,CAAK,UAAU,2BAA4B,SAAAS,EAAQ,CAAC,EAAE,EACtD,CAACP,GAAUK,EAAAA,KAAC,OAAA,CAAK,UAAU,sBAAsB,SAAA,CAAA,MAAIE,EAAQ,CAAC,CAAA,CAAA,CAAE,CAAA,EACrE,EACCP,UACI,MAAA,CACI,SAAA,CAAAM,EAAQ,IAAI,CAAC,CAACG,EAAKC,CAAK,IACrBF,EAAAA,IAACZ,EAAA,CAAmB,QAASa,EAAK,KAAMC,CAAA,EAAzBD,CAAgC,CAClD,QACA,MAAA,CAAI,UAAU,2BAA4B,SAAAF,EAAQ,CAAC,CAAA,CAAE,CAAA,CAAA,CAC1D,CAAA,EAER,CAER,EAEaI,EAAwD,CAAC,CAAE,YAAAC,KAAkB,CACtF,MAAMC,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GACd,CAACC,EAAWC,CAAY,EAAIb,EAAAA,SAASU,EAAc,KAAK,UAAUA,EAAa,KAAM,CAAC,EAAIC,CAAW,EACrG,CAACG,EAAYC,CAAa,EAAIf,EAAAA,SAAc,IAAM,CACpD,GAAI,CACA,OAAO,KAAK,MAAMY,CAAS,CAC/B,MAAQ,CACJ,OAAO,IACX,CACJ,CAAC,EACK,CAACI,EAAOC,CAAQ,EAAIjB,EAAAA,SAAS,EAAE,EAE/BkB,EAAaC,GAAkB,CACjC,GAAI,CACA,MAAMC,EAAS,KAAK,MAAMD,CAAK,EAC/BJ,EAAcK,CAAM,EACpBH,EAAS,EAAE,CACf,OAASI,EAAG,CACJA,aAAa,OAAOJ,EAASI,EAAE,OAAO,EAC1CN,EAAc,IAAI,CACtB,CACJ,EAEMO,EAAqBD,GAA8C,CACrER,EAAaQ,EAAE,OAAO,KAAK,EAC3BH,EAAUG,EAAE,OAAO,KAAK,CAC5B,EAEA,OACIlB,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,uCACV,SAAA,CAAAG,EAAAA,IAACiB,EAAA,EAAa,EACdjB,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,qBAAA,CAAmB,CAAA,EAC9C,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,6DAAA,CAA2D,CAAA,EACvG,EACAH,EAAAA,KAAC,MAAA,CAAI,UAAU,wCACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,oCACX,SAAA,CAAAG,MAAC,QAAA,CAAM,QAAQ,aAAa,UAAU,+CAA+C,SAAA,aAAU,EAC/FA,EAAAA,IAAC,WAAA,CACG,GAAG,aACH,MAAOM,EACP,SAAUU,EACV,UAAW,mCAAmCN,EAAQ,iBAAmB,eAAe,2FAAA,CAAA,EAE3FA,GAASV,EAAAA,IAAC,IAAA,CAAE,UAAU,4BAA6B,SAAAU,CAAA,CAAM,CAAA,EAC9D,EACCb,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACZ,SAAA,CAAAG,EAAAA,IAAC,QAAA,CAAM,UAAU,+CAA+C,SAAA,YAAS,QACxE,MAAA,CAAI,UAAU,6FACV,SAAAQ,EAAaR,MAACZ,GAAS,KAAMoB,EAAY,QAAQ,OAAO,OAAM,GAAC,EAAKR,MAAC,OAAI,UAAU,sBAAsB,oCAAwB,CAAA,CACtI,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,EACJ,CAER"}
assets/LogicFlowBuilder-iHo46zDC.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as x,j as e,R as M}from"./react-DKy9e2uO.js";import{l as D,W as g}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 L=new Map(g.map(s=>[s.id,s])),S=({feature:s,onDragStart:l})=>e.jsxs("div",{draggable:!0,onDragStart:m=>l(m,s.id),className:"p-3 rounded-md bg-gray-50 border border-border flex items-center gap-3 cursor-grab hover:bg-gray-100 transition-colors",children:[e.jsx("div",{className:"text-primary flex-shrink-0",children:s.icon}),e.jsxs("div",{children:[e.jsx("h4",{className:"font-bold text-sm text-text-primary",children:s.name}),e.jsx("p",{className:"text-xs text-text-secondary",children:s.category})]})]}),P=({node:s,feature:l,onMouseDown:m,onLinkStart:h,onLinkEnd:d})=>e.jsxs("div",{className:"absolute w-52 bg-surface rounded-lg shadow-md border-2 border-border cursor-grab active:cursor-grabbing flex flex-col",style:{left:s.x,top:s.y,transform:"translate(-50%, -50%)"},onMouseDown:i=>m(i,s.id),onMouseUp:i=>d(i,s.id),children:[e.jsxs("div",{className:"p-2 flex items-center gap-2 border-b border-border",children:[e.jsx("div",{className:"w-5 h-5 text-primary",children:l.icon}),e.jsx("span",{className:"text-sm font-semibold truncate text-text-primary",children:l.name})]}),e.jsxs("div",{className:"relative p-3 text-xs text-text-secondary min-h-[40px] flex items-center justify-center",children:["Workflow Node",e.jsx("div",{onMouseDown:i=>h(i,s.id),className:"absolute right-[-9px] top-1/2 -translate-y-1/2 w-4 h-4 bg-primary rounded-full border-2 border-surface cursor-crosshair hover:scale-125 transition-transform",title:"Drag to connect"})]})]}),R=M.memo(()=>e.jsxs("svg",{width:"100%",height:"100%",className:"absolute inset-0",children:[e.jsxs("defs",{children:[e.jsx("pattern",{id:"smallGrid",width:"10",height:"10",patternUnits:"userSpaceOnUse",children:e.jsx("path",{d:"M 10 0 L 0 0 0 10",fill:"none",stroke:"rgba(0, 0, 0, 0.05)",strokeWidth:"0.5"})}),e.jsxs("pattern",{id:"grid",width:"50",height:"50",patternUnits:"userSpaceOnUse",children:[e.jsx("rect",{width:"50",height:"50",fill:"url(#smallGrid)"}),e.jsx("path",{d:"M 50 0 L 0 0 0 50",fill:"none",stroke:"rgba(0, 0, 0, 0.1)",strokeWidth:"1"})]})]}),e.jsx("rect",{width:"100%",height:"100%",fill:"url(#grid)"})]})),G=()=>{const[s,l]=x.useState([]),[m,h]=x.useState([]),[d,i]=x.useState(null),[n,p]=x.useState(null),c=x.useRef(null),b=(t,r)=>{t.dataTransfer.setData("application/json",JSON.stringify({featureId:r}))},j=t=>{if(t.preventDefault(),!c.current)return;const{featureId:r}=JSON.parse(t.dataTransfer.getData("application/json")),o=c.current.getBoundingClientRect(),a={id:Date.now(),featureId:r,x:t.clientX-o.left,y:t.clientY-o.top};l(k=>[...k,a])},y=(t,r)=>{const o=s.find(a=>a.id===r);!o||t.target.title==="Drag to connect"||i({id:r,offsetX:t.clientX-o.x,offsetY:t.clientY-o.y})},v=t=>{if(d&&c.current&&l(s.map(r=>r.id===d.id?{...r,x:t.clientX-d.offsetX,y:t.clientY-d.offsetY}:r)),n&&c.current){const r=c.current.getBoundingClientRect();p({...n,toPos:{x:t.clientX-r.left,y:t.clientY-r.top}})}},f=()=>{i(null),p(null)},N=(t,r)=>{t.stopPropagation();const o=s.find(a=>a.id===r);o&&p({from:r,fromPos:{x:o.x,y:o.y},toPos:{x:o.x,y:o.y}})},w=(t,r)=>{t.stopPropagation(),n&&n.from!==r&&h(o=>[...o,{from:n.from,to:r}]),p(null)},u=x.useMemo(()=>new Map(s.map(t=>[t.id,{x:t.x,y:t.y}])),[s]);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(D,{}),e.jsx("span",{className:"ml-3",children:"Logic Flow Builder"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Visually build application logic flows and development pipelines."})]}),e.jsxs("div",{className:"flex-grow flex gap-6 min-h-0",children:[e.jsxs("aside",{className:"w-72 flex-shrink-0 bg-surface border border-border p-4 rounded-lg flex flex-col",children:[e.jsx("h3",{className:"font-bold mb-3 text-lg",children:"Features"}),e.jsx("div",{className:"flex-grow overflow-y-auto space-y-3 pr-2",children:g.map(t=>e.jsx(S,{feature:t,onDragStart:b},t.id))})]}),e.jsxs("main",{ref:c,className:"flex-grow relative bg-background border-2 border-dashed border-border rounded-lg overflow-hidden",onDrop:j,onDragOver:t=>t.preventDefault(),onMouseMove:v,onMouseUp:f,onMouseLeave:f,children:[e.jsx(R,{}),e.jsxs("svg",{width:"100%",height:"100%",className:"absolute inset-0 pointer-events-none",children:[m.map((t,r)=>{const o=u.get(t.from),a=u.get(t.to);return!o||!a?null:e.jsx("line",{x1:o.x,y1:o.y,x2:a.x,y2:a.y,stroke:"var(--color-primary)",strokeWidth:"2",markerEnd:"url(#arrow)"},r)}),n&&e.jsx("line",{x1:n.fromPos.x,y1:n.fromPos.y,x2:n.toPos.x,y2:n.toPos.y,stroke:"var(--color-primary)",strokeWidth:"2",strokeDasharray:"5,5"}),e.jsx("defs",{children:e.jsx("marker",{id:"arrow",viewBox:"0 0 10 10",refX:"8",refY:"5",markerWidth:"6",markerHeight:"6",orient:"auto-start-reverse",children:e.jsx("path",{d:"M 0 0 L 10 5 L 0 10 z",fill:"var(--color-primary)"})})})]}),s.map(t=>{const r=L.get(t.featureId);return r?e.jsx(P,{node:t,feature:r,onMouseDown:y,onLinkStart:N,onLinkEnd:w},t.id):null})]})]})]})};export{G as LogicFlowBuilder};
2
+ //# sourceMappingURL=LogicFlowBuilder-iHo46zDC.js.map
assets/LogicFlowBuilder-iHo46zDC.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"LogicFlowBuilder-iHo46zDC.js","sources":["../../components/features/LogicFlowBuilder.tsx"],"sourcesContent":["import React, { useState, useRef, useMemo, useCallback } from 'react';\nimport { ALL_FEATURES } from '../features/index.ts';\nimport type { Feature } from '../../types.ts';\nimport { MapIcon } from '../icons.tsx';\n\ninterface Node {\n id: number;\n featureId: string;\n x: number;\n y: number;\n}\n\ninterface Link {\n from: number;\n to: number;\n}\n\nconst featuresMap = new Map(ALL_FEATURES.map(f => [f.id, f]));\n\nconst FeaturePaletteItem: React.FC<{ feature: Feature, onDragStart: (e: React.DragEvent, featureId: string) => void }> = ({ feature, onDragStart }) => (\n <div\n draggable\n onDragStart={e => onDragStart(e, feature.id)}\n className=\"p-3 rounded-md bg-gray-50 border border-border flex items-center gap-3 cursor-grab hover:bg-gray-100 transition-colors\"\n >\n <div className=\"text-primary flex-shrink-0\">{feature.icon}</div>\n <div>\n <h4 className=\"font-bold text-sm text-text-primary\">{feature.name}</h4>\n <p className=\"text-xs text-text-secondary\">{feature.category}</p>\n </div>\n </div>\n);\n\nconst NodeComponent: React.FC<{\n node: Node;\n feature: Feature;\n onMouseDown: (e: React.MouseEvent, id: number) => void;\n onLinkStart: (e: React.MouseEvent, id: number) => void;\n onLinkEnd: (e: React.MouseEvent, id: number) => void;\n}> = ({ node, feature, onMouseDown, onLinkStart, onLinkEnd }) => (\n <div\n className=\"absolute w-52 bg-surface rounded-lg shadow-md border-2 border-border cursor-grab active:cursor-grabbing flex flex-col\"\n style={{ left: node.x, top: node.y, transform: 'translate(-50%, -50%)' }}\n onMouseDown={e => onMouseDown(e, node.id)}\n onMouseUp={e => onLinkEnd(e, node.id)}\n >\n <div className=\"p-2 flex items-center gap-2 border-b border-border\">\n <div className=\"w-5 h-5 text-primary\">{feature.icon}</div>\n <span className=\"text-sm font-semibold truncate text-text-primary\">{feature.name}</span>\n </div>\n <div className=\"relative p-3 text-xs text-text-secondary min-h-[40px] flex items-center justify-center\">\n Workflow Node\n <div\n onMouseDown={e => onLinkStart(e, node.id)}\n className=\"absolute right-[-9px] top-1/2 -translate-y-1/2 w-4 h-4 bg-primary rounded-full border-2 border-surface cursor-crosshair hover:scale-125 transition-transform\"\n title=\"Drag to connect\"\n />\n </div>\n </div>\n);\n\nconst SVGGrid: React.FC = React.memo(() => (\n <svg width=\"100%\" height=\"100%\" className=\"absolute inset-0\">\n <defs>\n <pattern id=\"smallGrid\" width=\"10\" height=\"10\" patternUnits=\"userSpaceOnUse\">\n <path d=\"M 10 0 L 0 0 0 10\" fill=\"none\" stroke=\"rgba(0, 0, 0, 0.05)\" strokeWidth=\"0.5\"/>\n </pattern>\n <pattern id=\"grid\" width=\"50\" height=\"50\" patternUnits=\"userSpaceOnUse\">\n <rect width=\"50\" height=\"50\" fill=\"url(#smallGrid)\"/>\n <path d=\"M 50 0 L 0 0 0 50\" fill=\"none\" stroke=\"rgba(0, 0, 0, 0.1)\" strokeWidth=\"1\"/>\n </pattern>\n </defs>\n <rect width=\"100%\" height=\"100%\" fill=\"url(#grid)\" />\n </svg>\n));\n\nexport const LogicFlowBuilder: React.FC = () => {\n const [nodes, setNodes] = useState<Node[]>([]);\n const [links, setLinks] = useState<Link[]>([]);\n const [draggingNode, setDraggingNode] = useState<{ id: number; offsetX: number; offsetY: number } | null>(null);\n const [linking, setLinking] = useState<{ from: number; fromPos: { x: number; y: number }; toPos: { x: number; y: number } } | null>(null);\n const canvasRef = useRef<HTMLDivElement>(null);\n\n const handleDragStart = (e: React.DragEvent, featureId: string) => {\n e.dataTransfer.setData('application/json', JSON.stringify({ featureId }));\n };\n\n const handleDrop = (e: React.DragEvent) => {\n e.preventDefault();\n if (!canvasRef.current) return;\n const { featureId } = JSON.parse(e.dataTransfer.getData('application/json'));\n const canvasRect = canvasRef.current.getBoundingClientRect();\n const newNode: Node = {\n id: Date.now(),\n featureId,\n x: e.clientX - canvasRect.left,\n y: e.clientY - canvasRect.top,\n };\n setNodes(prev => [...prev, newNode]);\n };\n\n const handleNodeMouseDown = (e: React.MouseEvent, id: number) => {\n const node = nodes.find(n => n.id === id);\n if (!node || (e.target as HTMLElement).title === 'Drag to connect') return;\n setDraggingNode({ id, offsetX: e.clientX - node.x, offsetY: e.clientY - node.y });\n };\n\n const handleCanvasMouseMove = (e: React.MouseEvent) => {\n if (draggingNode && canvasRef.current) {\n setNodes(nodes.map(n => n.id === draggingNode.id ? { ...n, x: e.clientX - draggingNode.offsetX, y: e.clientY - draggingNode.offsetY } : n));\n }\n if (linking && canvasRef.current) {\n const canvasRect = canvasRef.current.getBoundingClientRect();\n setLinking({ ...linking, toPos: { x: e.clientX - canvasRect.left, y: e.clientY - canvasRect.top } });\n }\n };\n\n const handleCanvasMouseUp = () => {\n setDraggingNode(null);\n setLinking(null);\n };\n\n const handleLinkStart = (e: React.MouseEvent, id: number) => {\n e.stopPropagation();\n const fromNode = nodes.find(n => n.id === id);\n if (!fromNode) return;\n setLinking({ from: id, fromPos: { x: fromNode.x, y: fromNode.y }, toPos: { x: fromNode.x, y: fromNode.y } });\n };\n\n const handleLinkEnd = (e: React.MouseEvent, id: number) => {\n e.stopPropagation();\n if (linking && linking.from !== id) {\n setLinks(prev => [...prev, { from: linking.from, to: id }]);\n }\n setLinking(null);\n };\n\n const nodePositions = useMemo(() => new Map(nodes.map(n => [n.id, { x: n.x, y: n.y }])), [nodes]);\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\"><MapIcon /><span className=\"ml-3\">Logic Flow Builder</span></h1>\n <p className=\"text-text-secondary mt-1\">Visually build application logic flows and development pipelines.</p>\n </header>\n <div className=\"flex-grow flex gap-6 min-h-0\">\n <aside className=\"w-72 flex-shrink-0 bg-surface border border-border p-4 rounded-lg flex flex-col\">\n <h3 className=\"font-bold mb-3 text-lg\">Features</h3>\n <div className=\"flex-grow overflow-y-auto space-y-3 pr-2\">\n {ALL_FEATURES.map(feature => <FeaturePaletteItem key={feature.id} feature={feature} onDragStart={handleDragStart} />)}\n </div>\n </aside>\n <main\n ref={canvasRef}\n className=\"flex-grow relative bg-background border-2 border-dashed border-border rounded-lg overflow-hidden\"\n onDrop={handleDrop}\n onDragOver={e => e.preventDefault()}\n onMouseMove={handleCanvasMouseMove}\n onMouseUp={handleCanvasMouseUp}\n onMouseLeave={handleCanvasMouseUp}\n >\n <SVGGrid />\n <svg width=\"100%\" height=\"100%\" className=\"absolute inset-0 pointer-events-none\">\n {links.map((link, i) => {\n const fromNode = nodePositions.get(link.from);\n const toNode = nodePositions.get(link.to);\n if (!fromNode || !toNode) return null;\n return <line key={i} x1={fromNode.x} y1={fromNode.y} x2={toNode.x} y2={toNode.y} stroke=\"var(--color-primary)\" strokeWidth=\"2\" markerEnd=\"url(#arrow)\" />;\n })}\n {linking && <line x1={linking.fromPos.x} y1={linking.fromPos.y} x2={linking.toPos.x} y2={linking.toPos.y} stroke=\"var(--color-primary)\" strokeWidth=\"2\" strokeDasharray=\"5,5\" />}\n <defs><marker id=\"arrow\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"6\" markerHeight=\"6\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--color-primary)\" /></marker></defs>\n </svg>\n {nodes.map(node => {\n const feature = featuresMap.get(node.featureId);\n return feature ? <NodeComponent key={node.id} node={node} feature={feature} onMouseDown={handleNodeMouseDown} onLinkStart={handleLinkStart} onLinkEnd={handleLinkEnd} /> : null;\n })}\n </main>\n </div>\n </div>\n );\n};"],"names":["featuresMap","ALL_FEATURES","f","FeaturePaletteItem","feature","onDragStart","jsxs","e","jsx","NodeComponent","node","onMouseDown","onLinkStart","onLinkEnd","SVGGrid","React","LogicFlowBuilder","nodes","setNodes","useState","links","setLinks","draggingNode","setDraggingNode","linking","setLinking","canvasRef","useRef","handleDragStart","featureId","handleDrop","canvasRect","newNode","prev","handleNodeMouseDown","id","n","handleCanvasMouseMove","handleCanvasMouseUp","handleLinkStart","fromNode","handleLinkEnd","nodePositions","useMemo","MapIcon","link","i","toNode"],"mappings":"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"}
assets/MarkdownSlides-JjWHLefE.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as t,j as e}from"./react-DKy9e2uO.js";import{m as p}from"./marked-CesSW9Du.js";import{P as g}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"./jszip-s56H2EZ-.js";const b=`# Slide 1: Welcome
2
+
3
+ This is a slide deck generated from Markdown.
4
+
5
+ - Use standard markdown syntax
6
+ - Like lists, headers, and **bold** text.
7
+
8
+ ---
9
+
10
+ # Slide 2: Features
11
+
12
+ Navigate using the buttons below.
13
+
14
+ \`\`\`javascript
15
+ console.log("Code blocks work too!");
16
+ \`\`\`
17
+
18
+ ---
19
+
20
+ # Slide 3: The End
21
+
22
+ Easy to create and present.
23
+ `,C=()=>{const[n,m]=t.useState(b),[l,c]=t.useState(0),[u,x]=t.useState(""),a=t.useRef(null),r=t.useMemo(()=>n.split(/^-{3,}\s*$/m),[n]);t.useEffect(()=>{(async()=>{const o=r[l]||"",h=await p.parse(o);x(h)})()},[r,l]);const d=t.useCallback(()=>c(s=>Math.min(s+1,r.length-1)),[r.length]),i=t.useCallback(()=>c(s=>Math.max(s-1,0)),[]),f=()=>{var s;(s=a.current)==null||s.requestFullscreen()};return t.useEffect(()=>{const s=o=>{document.fullscreenElement===a.current&&((o.key==="ArrowRight"||o.key===" ")&&d(),o.key==="ArrowLeft"&&i())};return document.addEventListener("keydown",s),()=>document.removeEventListener("keydown",s)},[d,i]),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(g,{}),e.jsx("span",{className:"ml-3",children:"Markdown to Slides"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Write markdown, present it as a slideshow. Use '---' to separate slides."})]}),e.jsxs("div",{className:"flex-grow grid grid-cols-1 lg:grid-cols-2 gap-6 h-full overflow-hidden",children:[e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsx("label",{htmlFor:"md-input",className:"text-sm font-medium text-text-secondary mb-2",children:"Markdown Editor"}),e.jsx("textarea",{id:"md-input",value:n,onChange:s=>m(s.target.value),className:"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm focus:ring-2 focus:ring-primary focus:outline-none"})]}),e.jsxs("div",{ref:a,className:"flex flex-col h-full bg-surface fullscreen:bg-background border border-border rounded-md",children:[e.jsx("div",{className:"flex-shrink-0 flex justify-end items-center p-2 border-b border-border",children:e.jsx("button",{onClick:f,className:"px-3 py-1 bg-gray-100 rounded-md text-xs hover:bg-gray-200",children:"Fullscreen"})}),e.jsxs("div",{className:"relative flex-grow flex flex-col justify-center items-center p-8 overflow-y-auto",children:[e.jsx("div",{className:"prose prose-lg max-w-none w-full",dangerouslySetInnerHTML:{__html:u}}),e.jsx("button",{onClick:i,disabled:l===0,className:"absolute left-4 top-1/2 -translate-y-1/2 p-2 bg-gray-200/50 rounded-full disabled:opacity-30 hover:bg-gray-300/50",children:"◀"}),e.jsx("button",{onClick:d,disabled:l===r.length-1,className:"absolute right-4 top-1/2 -translate-y-1/2 p-2 bg-gray-200/50 rounded-full disabled:opacity-30 hover:bg-gray-300/50",children:"▶"}),e.jsxs("div",{className:"absolute bottom-4 right-4 text-xs bg-black/50 px-2 py-1 rounded-md text-white",children:[l+1," / ",r.length]})]})]})]})]})};export{C as MarkdownSlides};
24
+ //# sourceMappingURL=MarkdownSlides-JjWHLefE.js.map
assets/MarkdownSlides-JjWHLefE.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"MarkdownSlides-JjWHLefE.js","sources":["../../components/features/MarkdownSlides.tsx"],"sourcesContent":["import React, { useState, useMemo, useEffect, useRef, useCallback } from 'react';\nimport { marked } from 'marked';\nimport { PhotoIcon } from '../icons.tsx';\n\nconst exampleMarkdown = `# Slide 1: Welcome\n\nThis is a slide deck generated from Markdown.\n\n- Use standard markdown syntax\n- Like lists, headers, and **bold** text.\n\n---\n\n# Slide 2: Features\n\nNavigate using the buttons below.\n\n\\`\\`\\`javascript\nconsole.log(\"Code blocks work too!\");\n\\`\\`\\`\n\n---\n\n# Slide 3: The End\n\nEasy to create and present.\n`;\n\nexport const MarkdownSlides: React.FC = () => {\n const [markdown, setMarkdown] = useState(exampleMarkdown);\n const [currentSlide, setCurrentSlide] = useState(0);\n const [slideHtml, setSlideHtml] = useState<string | TrustedHTML>('');\n const presentationRef = useRef<HTMLDivElement>(null);\n\n const slides = useMemo(() => markdown.split(/^-{3,}\\s*$/m), [markdown]);\n\n useEffect(() => {\n const parse = async () => {\n const currentSlideContent = slides[currentSlide] || '';\n const html = await marked.parse(currentSlideContent);\n setSlideHtml(html);\n };\n parse();\n }, [slides, currentSlide]);\n\n const goToNext = useCallback(() => setCurrentSlide(s => Math.min(s + 1, slides.length - 1)), [slides.length]);\n const goToPrev = useCallback(() => setCurrentSlide(s => Math.max(s - 1, 0)), []);\n\n const handleFullscreen = () => {\n presentationRef.current?.requestFullscreen();\n };\n \n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (document.fullscreenElement === presentationRef.current) {\n if (e.key === 'ArrowRight' || e.key === ' ') goToNext();\n if (e.key === 'ArrowLeft') goToPrev();\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [goToNext, goToPrev]);\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\">\n <h1 className=\"text-3xl font-bold flex items-center\"><PhotoIcon /><span className=\"ml-3\">Markdown to Slides</span></h1>\n <p className=\"text-text-secondary mt-1\">Write markdown, present it as a slideshow. Use '---' to separate slides.</p>\n </header>\n <div className=\"flex-grow grid grid-cols-1 lg:grid-cols-2 gap-6 h-full overflow-hidden\">\n <div className=\"flex flex-col h-full\">\n <label htmlFor=\"md-input\" className=\"text-sm font-medium text-text-secondary mb-2\">Markdown Editor</label>\n <textarea id=\"md-input\" value={markdown} onChange={e => setMarkdown(e.target.value)} className=\"flex-grow p-4 bg-surface border border-border rounded-md resize-none font-mono text-sm focus:ring-2 focus:ring-primary focus:outline-none\"/>\n </div>\n <div ref={presentationRef} className=\"flex flex-col h-full bg-surface fullscreen:bg-background border border-border rounded-md\">\n <div className=\"flex-shrink-0 flex justify-end items-center p-2 border-b border-border\">\n <button onClick={handleFullscreen} className=\"px-3 py-1 bg-gray-100 rounded-md text-xs hover:bg-gray-200\">Fullscreen</button>\n </div>\n <div className=\"relative flex-grow flex flex-col justify-center items-center p-8 overflow-y-auto\">\n <div className=\"prose prose-lg max-w-none w-full\" dangerouslySetInnerHTML={{ __html: slideHtml }} />\n <button onClick={goToPrev} disabled={currentSlide === 0} className=\"absolute left-4 top-1/2 -translate-y-1/2 p-2 bg-gray-200/50 rounded-full disabled:opacity-30 hover:bg-gray-300/50\">◀</button>\n <button onClick={goToNext} disabled={currentSlide === slides.length - 1} className=\"absolute right-4 top-1/2 -translate-y-1/2 p-2 bg-gray-200/50 rounded-full disabled:opacity-30 hover:bg-gray-300/50\">▶</button>\n <div className=\"absolute bottom-4 right-4 text-xs bg-black/50 px-2 py-1 rounded-md text-white\">\n {currentSlide + 1} / {slides.length}\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n};"],"names":["exampleMarkdown","MarkdownSlides","markdown","setMarkdown","useState","currentSlide","setCurrentSlide","slideHtml","setSlideHtml","presentationRef","useRef","slides","useMemo","useEffect","currentSlideContent","html","marked","goToNext","useCallback","goToPrev","handleFullscreen","_a","handleKeyDown","e","jsxs","jsx","PhotoIcon"],"mappings":"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"}
assets/MetaTagEditor-uPETDQxa.js ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as o,j as e}from"./react-DKy9e2uO.js";import{i}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 n=({meta:t})=>e.jsxs("div",{className:"w-full max-w-md mx-auto bg-surface border border-border rounded-2xl overflow-hidden shadow-lg",children:[e.jsx("div",{className:"h-52 bg-gray-100 flex items-center justify-center",children:t.image?e.jsx("img",{src:t.image,alt:"Preview",className:"w-full h-full object-cover",onError:a=>a.currentTarget.style.display="none"}):e.jsx("span",{className:"text-text-secondary",children:"Image Preview"})}),e.jsxs("div",{className:"p-4",children:[e.jsx("p",{className:"text-xs text-text-secondary truncate",children:new URL(t.url||"https://example.com").hostname}),e.jsx("h3",{className:"font-bold text-text-primary truncate mt-1",children:t.title||"Your Title Here"}),e.jsx("p",{className:"text-sm text-text-secondary mt-1 line-clamp-2",children:t.description||"A concise description of your content will appear here."})]})]}),j=()=>{const[t,a]=o.useState({title:"DevCore AI Toolkit",description:"The ultimate toolkit for modern developers, powered by Gemini.",image:"https://storage.googleapis.com/maker-studio-project-images-prod/programming_power_on_a_laptop_3a8f0bb1_39a9_4c2b_81f0_a74551480f2c.png",url:"https://devcore.example.com"}),r=s=>{a({...t,[s.target.name]:s.target.value})},l=o.useMemo(()=>`<!-- Primary Meta Tags -->
2
+ <title>${t.title}</title>
3
+ <meta name="title" content="${t.title}" />
4
+ <meta name="description" content="${t.description}" />
5
+ <!-- Open Graph / Facebook -->
6
+ <meta property="og:type" content="website" />
7
+ <meta property="og:url" content="${t.url}" />
8
+ <meta property="og:title" content="${t.title}" />
9
+ <meta property="og:description" content="${t.description}" />
10
+ <meta property="og:image" content="${t.image}" />
11
+ <!-- Twitter -->
12
+ <meta property="twitter:card" content="summary_large_image" />
13
+ <meta property="twitter:url" content="${t.url}" />
14
+ <meta property="twitter:title" content="${t.title}" />
15
+ <meta property="twitter:description" content="${t.description}" />
16
+ <meta property="twitter:image" content="${t.image}" />`,[t]);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(i,{}),e.jsx("span",{className:"ml-3",children:"Meta Tag Editor"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Generate SEO & social media meta tags with a live preview."})]}),e.jsxs("div",{className:"flex-grow grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-6 min-h-0",children:[e.jsxs("div",{className:"xl:col-span-1 flex flex-col gap-4 bg-surface border border-border p-6 rounded-lg overflow-y-auto",children:[e.jsx("h3",{className:"text-xl font-bold",children:"Metadata"}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm",children:"Title"}),e.jsx("input",{type:"text",name:"title",value:t.title,onChange:r,className:"w-full mt-1 p-2 rounded bg-background border border-border"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm",children:"Description"}),e.jsx("input",{type:"text",name:"description",value:t.description,onChange:r,className:"w-full mt-1 p-2 rounded bg-background border border-border"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm",children:"Canonical URL"}),e.jsx("input",{type:"text",name:"url",value:t.url,onChange:r,className:"w-full mt-1 p-2 rounded bg-background border border-border"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm",children:"Social Image URL"}),e.jsx("input",{type:"text",name:"image",value:t.image,onChange:r,className:"w-full mt-1 p-2 rounded bg-background border border-border"})]})]}),e.jsxs("div",{className:"xl:col-span-1 flex flex-col",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"Generated HTML"}),e.jsxs("div",{className:"relative flex-grow",children:[e.jsx("pre",{className:"w-full h-full bg-background p-4 rounded-md text-primary text-sm overflow-auto",children:l}),e.jsx("button",{onClick:()=>navigator.clipboard.writeText(l),className:"absolute top-2 right-2 px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md text-xs",children:"Copy"})]})]}),e.jsxs("div",{className:"hidden xl:flex flex-col items-center justify-center",children:[e.jsx("label",{className:"text-sm font-medium text-text-secondary mb-2",children:"Live Preview"}),e.jsx(n,{meta:t})]})]})]})};export{j as MetaTagEditor};
17
+ //# sourceMappingURL=MetaTagEditor-uPETDQxa.js.map
assets/MetaTagEditor-uPETDQxa.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"MetaTagEditor-uPETDQxa.js","sources":["../../components/features/MetaTagEditor.tsx"],"sourcesContent":["import React, { useState, useMemo } from 'react';\nimport { CodeBracketSquareIcon } from '../icons.tsx';\n\ninterface MetaData {\n title: string;\n description: string;\n image: string;\n url: string;\n}\n\nconst SocialCardPreview: React.FC<{ meta: MetaData }> = ({ meta }) => (\n <div className=\"w-full max-w-md mx-auto bg-surface border border-border rounded-2xl overflow-hidden shadow-lg\">\n <div className=\"h-52 bg-gray-100 flex items-center justify-center\">\n {meta.image ? <img src={meta.image} alt=\"Preview\" className=\"w-full h-full object-cover\" onError={(e) => e.currentTarget.style.display='none'}/> : <span className=\"text-text-secondary\">Image Preview</span>}\n </div>\n <div className=\"p-4\">\n <p className=\"text-xs text-text-secondary truncate\">{new URL(meta.url || 'https://example.com').hostname}</p>\n <h3 className=\"font-bold text-text-primary truncate mt-1\">{meta.title || 'Your Title Here'}</h3>\n <p className=\"text-sm text-text-secondary mt-1 line-clamp-2\">{meta.description || 'A concise description of your content will appear here.'}</p>\n </div>\n </div>\n);\n\nexport const MetaTagEditor: React.FC = () => {\n const [meta, setMeta] = useState<MetaData>({\n title: 'DevCore AI Toolkit', description: 'The ultimate toolkit for modern developers, powered by Gemini.',\n image: 'https://storage.googleapis.com/maker-studio-project-images-prod/programming_power_on_a_laptop_3a8f0bb1_39a9_4c2b_81f0_a74551480f2c.png',\n url: 'https://devcore.example.com'\n });\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n setMeta({ ...meta, [e.target.name]: e.target.value });\n };\n\n const generatedHtml = useMemo(() => {\n return `<!-- Primary Meta Tags -->\n<title>${meta.title}</title>\n<meta name=\"title\" content=\"${meta.title}\" />\n<meta name=\"description\" content=\"${meta.description}\" />\n<!-- Open Graph / Facebook -->\n<meta property=\"og:type\" content=\"website\" />\n<meta property=\"og:url\" content=\"${meta.url}\" />\n<meta property=\"og:title\" content=\"${meta.title}\" />\n<meta property=\"og:description\" content=\"${meta.description}\" />\n<meta property=\"og:image\" content=\"${meta.image}\" />\n<!-- Twitter -->\n<meta property=\"twitter:card\" content=\"summary_large_image\" />\n<meta property=\"twitter:url\" content=\"${meta.url}\" />\n<meta property=\"twitter:title\" content=\"${meta.title}\" />\n<meta property=\"twitter:description\" content=\"${meta.description}\" />\n<meta property=\"twitter:image\" content=\"${meta.image}\" />`;\n }, [meta]);\n \n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\"><h1 className=\"text-3xl font-bold flex items-center\"><CodeBracketSquareIcon /><span className=\"ml-3\">Meta Tag Editor</span></h1><p className=\"text-text-secondary mt-1\">Generate SEO & social media meta tags with a live preview.</p></header>\n <div className=\"flex-grow grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-3 gap-6 min-h-0\">\n <div className=\"xl:col-span-1 flex flex-col gap-4 bg-surface border border-border p-6 rounded-lg overflow-y-auto\">\n <h3 className=\"text-xl font-bold\">Metadata</h3>\n <div><label className=\"block text-sm\">Title</label><input type=\"text\" name=\"title\" value={meta.title} onChange={handleChange} className=\"w-full mt-1 p-2 rounded bg-background border border-border\"/></div>\n <div><label className=\"block text-sm\">Description</label><input type=\"text\" name=\"description\" value={meta.description} onChange={handleChange} className=\"w-full mt-1 p-2 rounded bg-background border border-border\"/></div>\n <div><label className=\"block text-sm\">Canonical URL</label><input type=\"text\" name=\"url\" value={meta.url} onChange={handleChange} className=\"w-full mt-1 p-2 rounded bg-background border border-border\"/></div>\n <div><label className=\"block text-sm\">Social Image URL</label><input type=\"text\" name=\"image\" value={meta.image} onChange={handleChange} className=\"w-full mt-1 p-2 rounded bg-background border border-border\"/></div>\n </div>\n <div className=\"xl:col-span-1 flex flex-col\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">Generated HTML</label>\n <div className=\"relative flex-grow\"><pre className=\"w-full h-full bg-background p-4 rounded-md text-primary text-sm overflow-auto\">{generatedHtml}</pre><button onClick={() => navigator.clipboard.writeText(generatedHtml)} className=\"absolute top-2 right-2 px-2 py-1 bg-gray-100 hover:bg-gray-200 rounded-md text-xs\">Copy</button></div>\n </div>\n <div className=\"hidden xl:flex flex-col items-center justify-center\">\n <label className=\"text-sm font-medium text-text-secondary mb-2\">Live Preview</label>\n <SocialCardPreview meta={meta} />\n </div>\n </div>\n </div>\n );\n};"],"names":["SocialCardPreview","meta","jsxs","jsx","e","MetaTagEditor","setMeta","useState","handleChange","generatedHtml","useMemo","CodeBracketSquareIcon"],"mappings":"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"}
assets/NetworkVisualizer-Cx-AAdTT.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as l,j as e}from"./react-DKy9e2uO.js";import{N as g}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 d=({title:a,value:m})=>e.jsxs("div",{className:"bg-surface border border-border p-3 rounded-lg text-center",children:[e.jsx("p",{className:"text-xs text-text-secondary",children:a}),e.jsx("p",{className:"text-xl font-bold text-text-primary",children:m})]}),F=()=>{const[a,m]=l.useState([]),[i,h]=l.useState("duration"),[c,p]=l.useState("desc");l.useEffect(()=>{const t=performance.getEntriesByType("resource");m(t)},[]);const f=l.useMemo(()=>[...a].sort((t,r)=>{const s=t[i],o=r[i];return s<o?c==="asc"?-1:1:s>o?c==="asc"?1:-1:0}),[a,i,c]),{totalSize:j,totalDuration:x,maxDuration:b}=l.useMemo(()=>{const t=a.reduce((s,o)=>s+o.transferSize,0),r=Math.max(...a.map(s=>s.startTime+s.duration),0);return{totalSize:t,totalDuration:r,maxDuration:Math.max(...a.map(s=>s.duration),0)}},[a]),N=t=>{p(i===t&&c==="desc"?"asc":"desc"),h(t)},u=t=>{if(t===0)return"0 B";const r=1024,s=["B","KB","MB"],o=Math.floor(Math.log(t)/Math.log(r));return parseFloat((t/Math.pow(r,o)).toFixed(1))+" "+s[o]},n=({skey:t,label:r,className:s})=>e.jsxs("th",{onClick:()=>N(t),className:`p-2 text-left cursor-pointer hover:bg-gray-100 ${s}`,children:[r," ",i===t&&(c==="asc"?"▲":"▼")]});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(g,{}),e.jsx("span",{className:"ml-3",children:"Network Visualizer"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Inspect network resources with a summary and waterfall chart."})]}),e.jsxs("div",{className:"grid grid-cols-2 md:grid-cols-4 gap-4 mb-4",children:[e.jsx(d,{title:"Total Requests",value:a.length}),e.jsx(d,{title:"Total Transferred",value:u(j)}),e.jsx(d,{title:"Finish Time",value:`${x.toFixed(0)}ms`}),e.jsx(d,{title:"Longest Request",value:`${b.toFixed(0)}ms`})]}),e.jsx("div",{className:"flex-grow overflow-auto bg-surface rounded-lg border border-border",children:e.jsxs("table",{className:"w-full text-sm text-left table-fixed",children:[e.jsx("thead",{className:"sticky top-0 bg-surface z-10",children:e.jsxs("tr",{className:"border-b border-border",children:[e.jsx(n,{skey:"name",label:"Name",className:"w-2/5"}),e.jsx(n,{skey:"initiatorType",label:"Type",className:"w-1/5"}),e.jsx(n,{skey:"transferSize",label:"Size",className:"w-1/5"}),e.jsx(n,{skey:"duration",label:"Time / Waterfall",className:"w-1/5"})]})}),e.jsx("tbody",{children:f.map((t,r)=>e.jsxs("tr",{className:"border-b border-border hover:bg-gray-50",children:[e.jsx("td",{className:"p-2 text-primary truncate",title:t.name,children:t.name.split("/").pop()}),e.jsx("td",{className:"p-2",children:t.initiatorType}),e.jsx("td",{className:"p-2",children:u(t.transferSize)}),e.jsx("td",{className:"p-2",children:e.jsxs("div",{className:"flex items-center",children:[e.jsxs("span",{className:"w-12",children:[t.duration.toFixed(0),"ms"]}),e.jsx("div",{className:"flex-grow h-4 bg-gray-200 rounded overflow-hidden",children:e.jsx("div",{className:"h-4 bg-primary rounded",style:{marginLeft:`${t.startTime/x*100}%`,width:`${t.duration/x*100}%`},title:`Start: ${t.startTime.toFixed(0)}ms`})})]})})]},r))})]})})]})};export{F as NetworkVisualizer};
2
+ //# sourceMappingURL=NetworkVisualizer-Cx-AAdTT.js.map
assets/NetworkVisualizer-Cx-AAdTT.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"NetworkVisualizer-Cx-AAdTT.js","sources":["../../components/features/NetworkVisualizer.tsx"],"sourcesContent":["import React, { useState, useEffect, useMemo } from 'react';\nimport { ChartBarIcon } from '../icons.tsx';\n\ntype SortKey = 'name' | 'initiatorType' | 'transferSize' | 'duration';\ntype SortDirection = 'asc' | 'desc';\n\nconst SummaryCard: React.FC<{ title: string, value: string | number }> = ({ title, value }) => (\n <div className=\"bg-surface border border-border p-3 rounded-lg text-center\">\n <p className=\"text-xs text-text-secondary\">{title}</p>\n <p className=\"text-xl font-bold text-text-primary\">{value}</p>\n </div>\n);\n\nexport const NetworkVisualizer: React.FC = () => {\n const [requests, setRequests] = useState<PerformanceResourceTiming[]>([]);\n const [sortKey, setSortKey] = useState<SortKey>('duration');\n const [sortDirection, setSortDirection] = useState<SortDirection>('desc');\n\n useEffect(() => {\n const entries = performance.getEntriesByType(\"resource\") as PerformanceResourceTiming[];\n setRequests(entries);\n }, []);\n \n const sortedRequests = useMemo(() => {\n return [...requests].sort((a, b) => {\n const valA = a[sortKey];\n const valB = b[sortKey];\n if (valA < valB) return sortDirection === 'asc' ? -1 : 1;\n if (valA > valB) return sortDirection === 'asc' ? 1 : -1;\n return 0;\n });\n }, [requests, sortKey, sortDirection]);\n\n const { totalSize, totalDuration, maxDuration } = useMemo(() => {\n const totalSize = requests.reduce((acc, req) => acc + req.transferSize, 0);\n const maxFinish = Math.max(...requests.map(r => r.startTime + r.duration), 0);\n return { totalSize, totalDuration: maxFinish, maxDuration: Math.max(...requests.map(r => r.duration), 0) };\n }, [requests]);\n\n const handleSort = (key: SortKey) => {\n setSortDirection(sortKey === key && sortDirection === 'desc' ? 'asc' : 'desc');\n setSortKey(key);\n };\n \n const formatBytes = (bytes: number) => {\n if (bytes === 0) return '0 B';\n const k = 1024; const sizes = ['B', 'KB', 'MB'];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];\n };\n\n const SortableHeader: React.FC<{ skey: SortKey, label: string; className?: string }> = ({ skey, label, className }) => (\n <th onClick={() => handleSort(skey)} className={`p-2 text-left cursor-pointer hover:bg-gray-100 ${className}`}>\n {label} {sortKey === skey && (sortDirection === 'asc' ? '▲' : '▼')}\n </th>\n );\n\n return (\n <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n <header className=\"mb-6\"><h1 className=\"text-3xl font-bold flex items-center\"><ChartBarIcon /><span className=\"ml-3\">Network Visualizer</span></h1><p className=\"text-text-secondary mt-1\">Inspect network resources with a summary and waterfall chart.</p></header>\n <div className=\"grid grid-cols-2 md:grid-cols-4 gap-4 mb-4\">\n <SummaryCard title=\"Total Requests\" value={requests.length} />\n <SummaryCard title=\"Total Transferred\" value={formatBytes(totalSize)} />\n <SummaryCard title=\"Finish Time\" value={`${totalDuration.toFixed(0)}ms`} />\n <SummaryCard title=\"Longest Request\" value={`${maxDuration.toFixed(0)}ms`} />\n </div>\n <div className=\"flex-grow overflow-auto bg-surface rounded-lg border border-border\">\n <table className=\"w-full text-sm text-left table-fixed\">\n <thead className=\"sticky top-0 bg-surface z-10\"><tr className=\"border-b border-border\">\n <SortableHeader skey=\"name\" label=\"Name\" className=\"w-2/5\"/>\n <SortableHeader skey=\"initiatorType\" label=\"Type\" className=\"w-1/5\" />\n <SortableHeader skey=\"transferSize\" label=\"Size\" className=\"w-1/5\"/>\n <SortableHeader skey=\"duration\" label=\"Time / Waterfall\" className=\"w-1/5\"/>\n </tr></thead>\n <tbody>{sortedRequests.map((req, i) => (<tr key={i} className=\"border-b border-border hover:bg-gray-50\">\n <td className=\"p-2 text-primary truncate\" title={req.name}>{req.name.split('/').pop()}</td>\n <td className=\"p-2\">{req.initiatorType}</td>\n <td className=\"p-2\">{formatBytes(req.transferSize)}</td>\n <td className=\"p-2\"><div className=\"flex items-center\">\n <span className=\"w-12\">{req.duration.toFixed(0)}ms</span>\n <div className=\"flex-grow h-4 bg-gray-200 rounded overflow-hidden\">\n <div className=\"h-4 bg-primary rounded\" style={{ marginLeft: `${(req.startTime / totalDuration) * 100}%`, width: `${(req.duration / totalDuration) * 100}%` }} title={`Start: ${req.startTime.toFixed(0)}ms`}></div>\n </div>\n </div></td>\n </tr>))}</tbody>\n </table>\n </div>\n </div>\n );\n};"],"names":["SummaryCard","title","value","jsxs","jsx","NetworkVisualizer","requests","setRequests","useState","sortKey","setSortKey","sortDirection","setSortDirection","useEffect","entries","sortedRequests","useMemo","a","b","valA","valB","totalSize","totalDuration","maxDuration","acc","req","maxFinish","r","handleSort","key","formatBytes","bytes","k","sizes","i","SortableHeader","skey","label","className","ChartBarIcon"],"mappings":"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"}