admin08077 commited on
Commit
63c17a0
·
verified ·
1 Parent(s): 14a9c72

Upload 107 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/@google-4tyssLU_.js +0 -0
  2. assets/@google-4tyssLU_.js.map +0 -0
  3. assets/AiCodeExplainer-CLIi0ncg.js +12 -0
  4. assets/AiCodeExplainer-CLIi0ncg.js.map +1 -0
  5. assets/AiCodeMigrator-BGFYaT4D.js +8 -0
  6. assets/AiCodeMigrator-BGFYaT4D.js.map +1 -0
  7. assets/AiCodingChallenge-BHuZwn1Z.js +2 -0
  8. assets/AiCodingChallenge-BHuZwn1Z.js.map +1 -0
  9. assets/AiCommitGenerator-DJTJcRjj.js +14 -0
  10. assets/AiCommitGenerator-DJTJcRjj.js.map +1 -0
  11. assets/AiFeatureBuilder-BozWSuGH.js +8 -0
  12. assets/AiFeatureBuilder-BozWSuGH.js.map +1 -0
  13. assets/AiImageGenerator-DtftAreE.js +2 -0
  14. assets/AiImageGenerator-DtftAreE.js.map +1 -0
  15. assets/AiStyleTransfer-bZypLQC9.js +4 -0
  16. assets/AiStyleTransfer-bZypLQC9.js.map +1 -0
  17. assets/AiUnitTestGenerator-CglcTDBa.js +9 -0
  18. assets/AiUnitTestGenerator-CglcTDBa.js.map +1 -0
  19. assets/AsyncCallTreeViewer-CMfYLp-3.js +23 -0
  20. assets/AsyncCallTreeViewer-CMfYLp-3.js.map +1 -0
  21. assets/AudioToCode-D6DCpAJs.js +2 -0
  22. assets/AudioToCode-D6DCpAJs.js.map +1 -0
  23. assets/ChangelogGenerator-BR9dmkLS.js +13 -0
  24. assets/ChangelogGenerator-BR9dmkLS.js.map +1 -0
  25. assets/CodeDiffGhost-CA6PXonq.js +18 -0
  26. assets/CodeDiffGhost-CA6PXonq.js.map +1 -0
  27. assets/CodeFormatter-BxgaA_LP.js +8 -0
  28. assets/CodeFormatter-BxgaA_LP.js.map +1 -0
  29. assets/CodeReviewBot-BnF0W6H3.js +12 -0
  30. assets/CodeReviewBot-BnF0W6H3.js.map +1 -0
  31. assets/CodeSpellChecker-CjNFapKd.js +6 -0
  32. assets/CodeSpellChecker-CjNFapKd.js.map +1 -0
  33. assets/ColorPaletteGenerator-BK2OFSOe.js +2 -0
  34. assets/ColorPaletteGenerator-BK2OFSOe.js.map +1 -0
  35. assets/CronJobBuilder-D6Lnlg8v.js +2 -0
  36. assets/CronJobBuilder-D6Lnlg8v.js.map +1 -0
  37. assets/CssGridEditor-xgIq-lQv.js +7 -0
  38. assets/CssGridEditor-xgIq-lQv.js.map +1 -0
  39. assets/DevNotesStickyPanel-BPakpEvi.js +3 -0
  40. assets/DevNotesStickyPanel-BPakpEvi.js.map +1 -0
  41. assets/FontPairingTool-BQS_3osJ.js +2 -0
  42. assets/FontPairingTool-BQS_3osJ.js.map +1 -0
  43. assets/FontPreviewPicker-u7VEPcYp.js +2 -0
  44. assets/FontPreviewPicker-u7VEPcYp.js.map +1 -0
  45. assets/JsonTreeNavigator-DaOkIsmx.js +13 -0
  46. assets/JsonTreeNavigator-DaOkIsmx.js.map +1 -0
  47. assets/LogicFlowBuilder-rTNUT_Hr.js +2 -0
  48. assets/LogicFlowBuilder-rTNUT_Hr.js.map +1 -0
  49. assets/MarkdownSlides-CVq-A3yp.js +24 -0
  50. assets/MarkdownSlides-CVq-A3yp.js.map +1 -0
assets/@google-4tyssLU_.js ADDED
The diff for this file is too large to render. See raw diff
 
assets/@google-4tyssLU_.js.map ADDED
The diff for this file is too large to render. See raw diff
 
assets/AiCodeExplainer-CLIi0ncg.js ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as l,j as e}from"./react-D_B_5QVd.js";import{e as b,C as N,M as v}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.js";const f=({text:r="AI is analyzing..."})=>e.jsxs("div",{className:"flex items-center justify-center space-x-2",children:[e.jsx("div",{className:"w-2 h-2 rounded-full bg-primary animate-pulse",style:{animationDelay:"0s"}}),e.jsx("div",{className:"w-2 h-2 rounded-full bg-primary animate-pulse",style:{animationDelay:"0.2s"}}),e.jsx("div",{className:"w-2 h-2 rounded-full bg-primary animate-pulse",style:{animationDelay:"0.4s"}}),e.jsx("span",{className:"text-text-secondary ml-2",children:r})]}),w=`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
+ };`,C=r=>r.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/(const|let|var|function|return|if|for|=>)/g,'<span class="text-indigo-600">$1</span>').replace(/(\'|")(.*?)(\'|")/g,'<span class="text-emerald-700">$1$2$3</span>').replace(/(\/\/.*)/g,'<span class="text-gray-500">$1</span>').replace(/(\{|\}|\(|\)|\[|\])/g,'<span class="text-gray-600">$1</span>'),M=({initialCode:r})=>{const[i,m]=l.useState(r||w),[a,x]=l.useState(null),[n,p]=l.useState(!1),[o,c]=l.useState(""),[u,h]=l.useState("summary"),d=l.useCallback(async s=>{if(!s.trim()){c("Please enter some code to explain.");return}p(!0),c(""),x(null),h("summary");try{const t=await b(s);x(t)}catch(t){const j=t instanceof Error?t.message:"An unknown error occurred.";c(`Failed to get explanation: ${j}`)}finally{p(!1)}},[]);l.useEffect(()=>{r&&(m(r),d(r))},[r,d]);const y=l.useMemo(()=>C(i),[i]),g=()=>{if(!a)return null;switch(u){case"summary":return e.jsx(v,{content:a.summary});case"lineByLine":return e.jsx("div",{className:"space-y-3",children:a.lineByLine.map((s,t)=>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: ",s.lines]}),e.jsx("p",{className:"text-sm",children:s.explanation})]},t))});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:a.complexity.time})]}),e.jsxs("p",{children:[e.jsx("strong",{children:"Space Complexity:"})," ",e.jsx("span",{className:"font-mono text-amber-600",children:a.complexity.space})]})]});case"suggestions":return e.jsx("ul",{className:"list-disc list-inside space-y-2",children:a.suggestions.map((s,t)=>e.jsx("li",{children:s},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(N,{}),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 gap-4 min-h-0",children:[e.jsxs("div",{className:"flex flex-col h-2/5 min-h-[200px]",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",children:[e.jsx("textarea",{id:"code-input",value:i,onChange:s=>m(s.target.value),placeholder:"Paste your code here...",spellCheck:"false",className:"absolute inset-0 w-full h-full p-4 bg-transparent border border-border rounded-md resize-none font-mono text-sm text-transparent caret-primary focus:ring-2 focus:ring-primary focus:outline-none z-10"}),e.jsx("pre",{"aria-hidden":"true",className:"absolute inset-0 w-full h-full p-4 bg-gray-50 border border-transparent rounded-md font-mono text-sm pointer-events-none z-0 whitespace-pre-wrap",dangerouslySetInnerHTML:{__html:y+`
11
+ `}})]})]}),e.jsx("div",{className:"flex-shrink-0",children:e.jsx("button",{onClick:()=>d(i),disabled:n,className:"btn-primary w-full max-w-xs mx-auto flex items-center justify-center px-6 py-3",children:n?e.jsx(f,{text:"Analyzing..."}):"Analyze Code"})}),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:"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(s=>e.jsx("button",{onClick:()=>h(s),disabled:!a,className:`px-4 py-2 text-sm font-medium capitalize transition-colors ${u===s?"bg-gray-100 text-primary":"text-text-secondary hover:bg-gray-50 disabled:text-gray-300"}`,children:s.replace(/([A-Z])/g," $1")},s))}),e.jsxs("div",{className:"p-4 flex-grow overflow-y-auto",children:[n&&e.jsx("div",{className:"flex items-center justify-center h-full",children:e.jsx(f,{})}),o&&e.jsx("p",{className:"text-red-500",children:o}),a&&!n&&g(),!n&&!a&&!o&&e.jsx("div",{className:"text-text-secondary h-full flex items-center justify-center",children:"The analysis will appear here."})]})]})]})]})]})};export{M as AiCodeExplainer};
12
+ //# sourceMappingURL=AiCodeExplainer-CLIi0ncg.js.map
assets/AiCodeExplainer-CLIi0ncg.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiCodeExplainer-CLIi0ncg.js","sources":["../../components/features/AiCodeExplainer.tsx"],"sourcesContent":["\n\nimport React, { useState, useCallback, useEffect, useMemo } from 'react';\nimport { explainCodeStructured, StructuredExplanation } from '../../services/geminiService.ts';\nimport { CpuChipIcon } from '../icons/InterfaceIcons.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.tsx';\n\nconst LoadingSpinner: React.FC<{text?: string}> = ({ text = 'AI is analyzing...'}) => (\n <div className=\"flex items-center justify-center space-x-2\">\n <div className=\"w-2 h-2 rounded-full bg-primary animate-pulse\" style={{ animationDelay: '0s' }}></div>\n <div className=\"w-2 h-2 rounded-full bg-primary animate-pulse\" style={{ animationDelay: '0.2s' }}></div>\n <div className=\"w-2 h-2 rounded-full bg-primary animate-pulse\" style={{ animationDelay: '0.4s' }}></div>\n <span className=\"text-text-secondary ml-2\">{text}</span>\n </div>\n);\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 return code\n .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')\n .replace(/(const|let|var|function|return|if|for|=>)/g, '<span class=\"text-indigo-600\">$1</span>')\n .replace(/(\\'|\")(.*?)(\\'|\")/g, '<span class=\"text-emerald-700\">$1$2$3</span>')\n .replace(/(\\/\\/.*)/g, '<span class=\"text-gray-500\">$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\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 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\">\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 gap-4 min-h-0\">\n <div className=\"flex flex-col h-2/5 min-h-[200px]\">\n <label htmlFor=\"code-input\" className=\"text-sm font-medium text-text-secondary mb-2\">Your Code</label>\n <div className=\"relative flex-grow\">\n <textarea\n id=\"code-input\"\n value={code}\n onChange={(e) => setCode(e.target.value)}\n placeholder=\"Paste your code here...\"\n spellCheck=\"false\"\n className=\"absolute inset-0 w-full h-full p-4 bg-transparent border border-border rounded-md resize-none font-mono text-sm text-transparent caret-primary focus:ring-2 focus:ring-primary focus:outline-none z-10\"\n />\n <pre \n aria-hidden=\"true\"\n className=\"absolute inset-0 w-full h-full p-4 bg-gray-50 border border-transparent rounded-md font-mono text-sm pointer-events-none z-0 whitespace-pre-wrap\"\n dangerouslySetInnerHTML={{ __html: highlightedCode + '\\n' }} \n />\n </div>\n </div>\n\n <div className=\"flex-shrink-0\">\n <button\n onClick={() => handleExplain(code)}\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 text=\"Analyzing...\"/> : 'Analyze Code'}\n </button>\n </div>\n \n <div className=\"flex flex-col flex-grow min-h-0\">\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-gray-100 text-primary' : 'text-text-secondary hover:bg-gray-50 disabled:text-gray-300'}`}>\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":["LoadingSpinner","text","jsxs","jsx","exampleCode","simpleSyntaxHighlight","code","AiCodeExplainer","initialCode","setCode","useState","explanation","setExplanation","isLoading","setIsLoading","error","setError","activeTab","setActiveTab","handleExplain","useCallback","codeToExplain","result","explainCodeStructured","err","errorMessage","useEffect","highlightedCode","useMemo","renderTabContent","MarkdownRenderer","item","index","CpuChipIcon","e","tab"],"mappings":"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"}
assets/AiCodeMigrator-BGFYaT4D.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import{r as s,j as e}from"./react-D_B_5QVd.js";import{I as L,J as A,L as w,M}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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
+ }`,T=({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{T as AiCodeMigrator};
8
+ //# sourceMappingURL=AiCodeMigrator-BGFYaT4D.js.map
assets/AiCodeMigrator-BGFYaT4D.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiCodeMigrator-BGFYaT4D.js","sources":["../../components/features/AiCodeMigrator.tsx"],"sourcesContent":["\n\nimport React, { useState, useCallback, useEffect } from 'react';\nimport { migrateCodeStream } from '../../services/geminiService.ts';\nimport { ArrowPathIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.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":"wRAQA,MAAMA,EAAY,CAAC,OAAQ,MAAO,aAAc,aAAc,SAAU,KAAM,QAAS,MAAO,UAAW,cAAc,EAEjHC,EAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAQPC,EAAuF,CAAC,CAAE,UAAWC,EAAa,SAAUC,EAAa,OAAQC,KAAgB,CAC1K,KAAM,CAACC,EAAWC,CAAY,EAAIC,EAAAA,SAAiBL,GAAeF,CAAW,EACvE,CAACQ,EAAYC,CAAa,EAAIF,EAAAA,SAAiB,EAAE,EACjD,CAACG,EAAUC,CAAW,EAAIJ,EAAAA,SAASJ,GAAe,MAAM,EACxD,CAACS,EAAQC,CAAS,EAAIN,EAAAA,SAASH,GAAa,KAAK,EACjD,CAACU,EAAWC,CAAY,EAAIR,EAAAA,SAAkB,EAAK,EACnD,CAACS,EAAOC,CAAQ,EAAIV,EAAAA,SAAiB,EAAE,EAEvCW,EAAgBC,EAAAA,YAAY,MAAOC,EAAcC,EAAcC,IAAe,CAChF,GAAI,CAACF,EAAK,OAAQ,CACdH,EAAS,oCAAoC,EAC7C,MACJ,CACAF,EAAa,EAAI,EACjBE,EAAS,EAAE,EACXR,EAAc,EAAE,EAChB,GAAI,CACA,MAAMc,EAASC,EAAkBJ,EAAMC,EAAMC,CAAE,EAC/C,IAAIG,EAAe,GACnB,gBAAiBC,KAASH,EACtBE,GAAgBC,EAChBjB,EAAcgB,CAAY,CAElC,OAASE,EAAK,CACV,MAAMC,EAAeD,aAAe,MAAQA,EAAI,QAAU,6BAC1DV,EAAS,2BAA2BW,CAAY,EAAE,CACtD,QAAA,CACIb,EAAa,EAAK,CACtB,CACJ,EAAG,CAAA,CAAE,EAELc,EAAAA,UAAU,IAAM,CACR3B,GAAeC,GAAeC,IAC9BE,EAAaJ,CAAW,EACxBS,EAAYR,CAAW,EACvBU,EAAUT,CAAS,EACnBc,EAAchB,EAAaC,EAAaC,CAAS,EAEzD,EAAG,CAACF,EAAaC,EAAaC,EAAWc,CAAa,CAAC,EAEvD,MAAMY,EAAiF,CAAC,CAAE,MAAAC,EAAO,SAAAC,CAAA,IAC7FC,EAAAA,IAAC,SAAA,CAAO,MAAAF,EAAc,SAAUG,GAAKF,EAASE,EAAE,OAAO,KAAK,EAAG,UAAU,8DACpE,SAAAnC,EAAU,IAAIoC,GAAQF,EAAAA,IAAC,SAAA,CAAkB,MAAOE,EAAO,SAAAA,CAAA,EAApBA,CAAyB,CAAS,EAC1E,EAGJ,OACIC,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,uCAAuC,SAAA,CAAAH,EAAAA,IAACI,EAAA,EAAc,EAAEJ,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,kBAAA,CAAgB,CAAA,EAAO,EACpHA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,kEAAA,CAAgE,CAAA,EAC5G,EACAG,EAAAA,KAAC,MAAA,CAAI,UAAU,kCACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,0DACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,OACX,SAAA,CAAAH,EAAAA,IAAC,QAAA,CAAM,UAAU,0CAA0C,SAAA,QAAK,EAChEA,EAAAA,IAACH,EAAA,CAAiB,MAAOpB,EAAU,SAAUC,CAAA,CAAa,CAAA,EAC9D,EACAsB,EAAAA,IAAC,WAAA,CACG,MAAO5B,EACP,SAAW6B,GAAM5B,EAAa4B,EAAE,OAAO,KAAK,EAC5C,YAAY,iCACZ,UAAU,wFAAA,CAAA,CACd,EACJ,EACAE,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,OACX,SAAA,CAAAH,EAAAA,IAAC,QAAA,CAAM,UAAU,0CAA0C,SAAA,MAAG,EAC9DA,EAAAA,IAACH,EAAA,CAAiB,MAAOlB,EAAQ,SAAUC,CAAA,CAAW,CAAA,EAC1D,EACAuB,EAAAA,KAAC,MAAA,CAAI,UAAU,8EACX,SAAA,CAAAtB,SAAc,MAAA,CAAI,UAAU,0CAA0C,SAAAmB,MAACK,IAAe,EAAE,EACvFtB,GAASiB,EAAAA,IAAC,IAAA,CAAE,UAAU,mBAAoB,SAAAjB,EAAM,EAChDR,GAAc,CAACM,GAAamB,EAAAA,IAACM,EAAA,CAAiB,QAAS/B,EAAY,EACnE,CAACM,GAAa,CAACN,GAAc,CAACQ,GAASiB,EAAAA,IAAC,MAAA,CAAI,UAAU,8DAA8D,SAAA,iCAAA,CAA+B,CAAA,CAAA,CACxJ,CAAA,CAAA,CACJ,CAAA,EACJ,EACCA,EAAAA,IAAC,SAAA,CACE,QAAS,IAAMf,EAAcb,EAAWK,EAAUE,CAAM,EACxD,SAAUE,EACV,UAAU,sFAET,SAAAA,EAAYmB,EAAAA,IAACK,EAAA,CAAA,CAAe,EAAK,cAAA,CAAA,CACtC,CAAA,CACJ,CAAA,EACJ,CAER"}
assets/AiCodingChallenge-BHuZwn1Z.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as t,j as e}from"./react-D_B_5QVd.js";import{v as f,B as h,L as m,M as u}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.js";const w=()=>{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{w as AiCodingChallenge};
2
+ //# sourceMappingURL=AiCodingChallenge-BHuZwn1Z.js.map
assets/AiCodingChallenge-BHuZwn1Z.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiCodingChallenge-BHuZwn1Z.js","sources":["../../components/features/AiCodingChallenge.tsx"],"sourcesContent":["\n\nimport React, { useState, useCallback, useEffect } from 'react';\nimport { generateCodingChallengeStream } from '../../services/geminiService.ts';\nimport { BeakerIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.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":"6RAQO,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-DJTJcRjj.js ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r,j as e}from"./react-D_B_5QVd.js";import{b,G as y,L as u,A as N}from"./index-BdwitBZy.js";import{d as w}from"./fileUtils-Dvg4vqd5.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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-DJTJcRjj.js.map
assets/AiCommitGenerator-DJTJcRjj.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiCommitGenerator-DJTJcRjj.js","sources":["../../components/features/AiCommitGenerator.tsx"],"sourcesContent":["\n\nimport React, { useState, useCallback, useEffect } from 'react';\nimport { generateCommitMessageStream } from '../../services/geminiService.ts';\nimport { GitBranchIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { downloadFile } from '../../services/fileUtils.ts';\nimport { ArrowDownTrayIcon } from '../icons/InterfaceIcons.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":"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"}
assets/AiFeatureBuilder-BozWSuGH.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import{r,j as e}from"./react-D_B_5QVd.js";import{c as O,g as D,s as I,a as P,b as A,d as $,D as C,B as G,G as B,L as v,f as L,M as N}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.js";const Q=()=>{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 w="";for await(const M of a)w+=M,u(w)}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(C,{}),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(C,{})," 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{Q as AiFeatureBuilder};
8
+ //# sourceMappingURL=AiFeatureBuilder-BozWSuGH.js.map
assets/AiFeatureBuilder-BozWSuGH.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiFeatureBuilder-BozWSuGH.js","sources":["../../components/features/AiFeatureBuilder.tsx"],"sourcesContent":["import React, { useState, useCallback, useEffect } from 'react';\nimport type { GeneratedFile } from '../../types.ts';\nimport { generateFeature, generateUnitTestsStream, generateCommitMessageStream } from '../../services/geminiService.ts';\nimport { saveFile, getAllFiles, clearAllFiles } from '../../services/dbService.ts';\nimport { CpuChipIcon, DocumentTextIcon, BeakerIcon, GitBranchIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.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};\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-DtftAreE.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as o,j as e}from"./react-D_B_5QVd.js";import{O as f,Q as b,L as m,S as j,A as y}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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."],C=()=>{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{C as AiImageGenerator};
2
+ //# sourceMappingURL=AiImageGenerator-DtftAreE.js.map
assets/AiImageGenerator-DtftAreE.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiImageGenerator-DtftAreE.js","sources":["../../components/features/AiImageGenerator.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { generateImage } from '../../services/geminiService.ts';\nimport { ImageGeneratorIcon } from '../icons/CustomFeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { ArrowDownTrayIcon } from '../icons/InterfaceIcons.tsx';\nimport { SparklesIcon } from '../icons/FeatureIcons.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":"oSAOA,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/AiStyleTransfer-bZypLQC9.js ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ import{r as s,j as e}from"./react-D_B_5QVd.js";import{t as y,S as j,L as x,M as b}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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.`,I=()=>{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{I as AiStyleTransfer};
4
+ //# sourceMappingURL=AiStyleTransfer-bZypLQC9.js.map
assets/AiStyleTransfer-bZypLQC9.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiStyleTransfer-bZypLQC9.js","sources":["../../components/features/AiStyleTransfer.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { transferCodeStyleStream } from '../../services/geminiService.ts';\nimport { SparklesIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.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};\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-CglcTDBa.js ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import{r as a,j as e}from"./react-D_B_5QVd.js";import{a as h,B as g,L as m,A as j,M as b}from"./index-BdwitBZy.js";import{d as y}from"./fileUtils-Dvg4vqd5.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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:()=>y(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(j,{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(b,{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-CglcTDBa.js.map
assets/AiUnitTestGenerator-CglcTDBa.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AiUnitTestGenerator-CglcTDBa.js","sources":["../../components/features/AiUnitTestGenerator.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { generateUnitTestsStream } from '../../services/geminiService.ts';\nimport { BeakerIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.tsx';\nimport { downloadFile } from '../../services/fileUtils.ts';\nimport { ArrowDownTrayIcon } from '../icons/InterfaceIcons.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};\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-CMfYLp-3.js ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as d,j as e,R as h}from"./react-D_B_5QVd.js";import{R as u}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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))})]})},S=()=>{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{S as AsyncCallTreeViewer};
23
+ //# sourceMappingURL=AsyncCallTreeViewer-CMfYLp-3.js.map
assets/AsyncCallTreeViewer-CMfYLp-3.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AsyncCallTreeViewer-CMfYLp-3.js","sources":["../../components/features/AsyncCallTreeViewer.tsx"],"sourcesContent":["\n\nimport React, { useState, useMemo } from 'react';\nimport { ChartBarIcon } from '../icons/FeatureIcons.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-D6DCpAJs.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as t,j as e}from"./react-D_B_5QVd.js";import{U as y,V as v,L as h,M as N}from"./index-BdwitBZy.js";import{a as R}from"./fileUtils-Dvg4vqd5.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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 R(s),m=y(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-D6DCpAJs.js.map
assets/AudioToCode-D6DCpAJs.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"AudioToCode-D6DCpAJs.js","sources":["../../components/features/AudioToCode.tsx"],"sourcesContent":["import React, { useState, useRef, useCallback } from 'react';\nimport { transcribeAudioToCodeStream } from '../../services/geminiService.ts';\nimport { MicrophoneIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.tsx';\nimport { blobToBase64 } from '../../services/fileUtils.ts';\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};\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-BR9dmkLS.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as a,j as e}from"./react-D_B_5QVd.js";import{y as u,G as f,L as x,M as p}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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
+ `,L=()=>{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{L as ChangelogGenerator};
13
+ //# sourceMappingURL=ChangelogGenerator-BR9dmkLS.js.map
assets/ChangelogGenerator-BR9dmkLS.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"ChangelogGenerator-BR9dmkLS.js","sources":["../../components/features/ChangelogGenerator.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { generateChangelogFromLogStream } from '../../services/geminiService.ts';\nimport { GitBranchIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.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};\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":"6RAMA,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-CA6PXonq.js ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r,j as e}from"./react-D_B_5QVd.js";import{E as u}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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
+ }`,y=()=>{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{y as CodeDiffGhost};
18
+ //# sourceMappingURL=CodeDiffGhost-CA6PXonq.js.map
assets/CodeDiffGhost-CA6PXonq.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CodeDiffGhost-CA6PXonq.js","sources":["../../components/features/CodeDiffGhost.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport { EyeIcon } from '../icons/FeatureIcons.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};\n"],"names":["initialOldCode","initialNewCode","CodeDiffGhost","oldCode","setOldCode","useState","newCode","setNewCode","typedCode","setTypedCode","isRunning","setIsRunning","intervalRef","useRef","startAnimation","prev","useEffect","jsxs","jsx","EyeIcon","e"],"mappings":"mQAGA,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-BxgaA_LP.js ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import{r,j as e}from"./react-D_B_5QVd.js";import{n as p,l as h,L as i,M as j}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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
+ }`,S=()=>{const[s,x]=r.useState(g),[o,c]=r.useState(""),[a,d]=r.useState(!1),[n,m]=r.useState(""),f=r.useCallback(async()=>{if(!s.trim()){m("Please enter some code to format.");return}d(!0),m(""),c("");try{const t=p(s);let l="";for await(const u of t)l+=u,c(l)}catch(t){const l=t instanceof Error?t.message:"An unknown error occurred.";m(`Failed to format code: ${l}`)}finally{d(!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(i,{})}),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(i,{}):"Format Code"})]})]})};export{S as CodeFormatter};
8
+ //# sourceMappingURL=CodeFormatter-BxgaA_LP.js.map
assets/CodeFormatter-BxgaA_LP.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CodeFormatter-BxgaA_LP.js","sources":["../../components/features/CodeFormatter.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { formatCodeStream } from '../../services/geminiService.ts';\nimport { CodeBracketSquareIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.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};\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":"wRAMA,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-BnF0W6H3.js ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r,j as e}from"./react-D_B_5QVd.js";import{w as h,d as p,L as m,M as j}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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
+ }`,S=()=>{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=h(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(p,{}),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{S as CodeReviewBot};
12
+ //# sourceMappingURL=CodeReviewBot-BnF0W6H3.js.map
assets/CodeReviewBot-BnF0W6H3.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CodeReviewBot-BnF0W6H3.js","sources":["../../components/features/CodeReviewBot.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { reviewCodeStream } from '../../services/geminiService.ts';\nimport { CpuChipIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.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};\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":"wRAMA,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-CjNFapKd.js ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import{r as o,j as e,R as c}from"./react-D_B_5QVd.js";import{B as l}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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})}),y=()=>{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{y as CodeSpellChecker};
6
+ //# sourceMappingURL=CodeSpellChecker-CjNFapKd.js.map
assets/CodeSpellChecker-CjNFapKd.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CodeSpellChecker-CjNFapKd.js","sources":["../../components/features/CodeSpellChecker.tsx"],"sourcesContent":["import React, { useState, useMemo } from 'react';\nimport { BeakerIcon } from '../icons/FeatureIcons.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};\n"],"names":["commonTypos","typoRegex","HighlightedText","React","text","parts","useMemo","part","i","CodeSpellChecker","code","setCode","useState","jsxs","jsx","BeakerIcon","e"],"mappings":"+QAGA,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-BK2OFSOe.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r,j as e}from"./react-D_B_5QVd.js";import{Z as u}from"./react-colorful-yV61q6mf.js";import{W as b,S as h,L as c}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.js";const S=()=>{const[s,i]=r.useState("#0047AB"),[d,m]=r.useState(["#0047AB","#3366CC","#6688D1","#99AADD","#CCD3E8","#F0F2F5"]),[a,l]=r.useState(!1),[o,n]=r.useState(""),x=r.useCallback(async()=>{l(!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{l(!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"}),o&&e.jsx("p",{className:"text-red-500 text-sm mt-2",children:o})]}),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{S as ColorPaletteGenerator};
2
+ //# sourceMappingURL=ColorPaletteGenerator-BK2OFSOe.js.map
assets/ColorPaletteGenerator-BK2OFSOe.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"ColorPaletteGenerator-BK2OFSOe.js","sources":["../../components/features/ColorPaletteGenerator.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { HexColorPicker } from 'react-colorful';\nimport { generateColorPalette } from '../../services/geminiService.ts';\nimport { SparklesIcon } from '../icons/FeatureIcons.tsx';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.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};\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":"kUAMO,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-D6Lnlg8v.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as t,j as e}from"./react-D_B_5QVd.js";import{z as C,H as N,L as S,S as k}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.js";const c=({label:n,value:o,onChange:i,options:l})=>e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-text-secondary",children:n}),e.jsxs("select",{value:o,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:n})=>{const[o,i]=t.useState("0"),[l,a]=t.useState("17"),[d,p]=t.useState("*"),[x,h]=t.useState("*"),[m,g]=t.useState("1-5"),[b,f]=t.useState(n||"every weekday at 5pm"),[y,j]=t.useState(!1),v=t.useMemo(()=>`${o} ${l} ${d} ${x} ${m}`,[o,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(()=>{n&&(f(n),u(n))},[n,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=>f(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:y,className:"btn-primary px-4 py-1.5 flex items-center gap-2",children:[y?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:o,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-D6Lnlg8v.js.map
assets/CronJobBuilder-D6Lnlg8v.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CronJobBuilder-D6Lnlg8v.js","sources":["../../components/features/CronJobBuilder.tsx"],"sourcesContent":["import React, { useState, useMemo, useCallback, useEffect } from 'react';\nimport { CommandLineIcon, SparklesIcon } from '../icons/FeatureIcons.tsx';\nimport { generateCronFromDescription, CronParts } from '../../services/geminiService.ts';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.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};\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-xgIq-lQv.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import{r as n,j as e}from"./react-D_B_5QVd.js";import{l as y,A as f}from"./index-BdwitBZy.js";import{d as j}from"./fileUtils-Dvg4vqd5.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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-xgIq-lQv.js.map
assets/CssGridEditor-xgIq-lQv.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"CssGridEditor-xgIq-lQv.js","sources":["../../components/features/CssGridEditor.tsx"],"sourcesContent":["import React, { useState, useMemo } from 'react';\nimport { CodeBracketSquareIcon } from '../icons/FeatureIcons.tsx';\nimport { downloadFile } from '../../services/fileUtils.ts';\nimport { ArrowDownTrayIcon } from '../icons/InterfaceIcons.tsx';\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};\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/DevNotesStickyPanel-BPakpEvi.js ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ import{r as d,j as t}from"./react-D_B_5QVd.js";import{u as w,q as v,F as S,S as k,L as C,M as z}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.js";const g=["bg-yellow-300 text-yellow-900","bg-green-300 text-green-900","bg-blue-300 text-blue-900","bg-pink-300 text-pink-900","bg-purple-300 text-purple-900"],L=()=>{const[o,l]=w("devcore_notes",[]),[n,u]=d.useState(null),[i,x]=d.useState(!1),[m,c]=d.useState(""),f=d.useCallback(async()=>{if(o.length!==0){x(!0),c("");try{const e=o.map(a=>`- ${a.text}`).join(`
2
+ `),r=v(e);let s="";for await(const a of r)s+=a,c(s)}catch(e){console.error(e),c("Sorry, an error occurred while summarizing.")}finally{x(!1)}}},[o]),b=()=>{const e={id:Date.now(),text:"New note...",x:50+o.length%10*20,y:50+o.length%10*20,color:g[o.length%g.length]};l([...o,e])},h=(e,r)=>{l(o.map(s=>s.id===e?{...s,text:r}:s))},y=(e,r)=>{r.stopPropagation(),l(o.filter(s=>s.id!==e))},N=(e,r)=>{if(e.target.tagName==="TEXTAREA"||e.target.tagName==="BUTTON")return;const a=e.currentTarget.getBoundingClientRect();u({id:r,offsetX:e.clientX-a.left,offsetY:e.clientY-a.top})},j=e=>{if(!n)return;const r=e.currentTarget.getBoundingClientRect();l(o.map(s=>s.id===n.id?{...s,x:e.clientX-n.offsetX-r.left,y:e.clientY-n.offsetY-r.top}:s))},p=()=>u(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:"Dev Notes Sticky Panel"})]}),t.jsx("p",{className:"text-text-secondary mt-1",children:"A place for your thoughts, todos, and random ideas."})]}),t.jsxs("div",{className:"flex gap-2",children:[t.jsxs("button",{onClick:f,disabled:i||o.length===0,className:"btn-primary flex items-center gap-2 px-4 py-2",children:[t.jsx(k,{})," ",i?"Summarizing...":"AI Summarize"]}),t.jsx("button",{onClick:b,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:j,onMouseUp:p,onMouseLeave:p,children:o.map(e=>t.jsxs("div",{className:`group absolute w-48 h-48 p-2 flex flex-col shadow-lg cursor-grab active:cursor-grabbing rounded-md transition-transform duration-100 border border-black/30 ${e.color}`,style:{top:e.y,left:e.x,transform:(n==null?void 0:n.id)===e.id?"scale(1.05)":"scale(1)"},onMouseDown:r=>N(r,e.id),children:[t.jsx("button",{onClick:r=>y(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=>h(e.id,r.target.value),className:"w-full h-full bg-transparent resize-none focus:outline-none font-medium p-1 placeholder:text-inherit/50"})]},e.id))}),(i||m)&&t.jsx("div",{className:"fixed inset-0 bg-gray-900/80 backdrop-blur-sm z-50 flex items-center justify-center",onClick:()=>c(""),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"}),i&&!m?t.jsx(C,{}):t.jsx(z,{content:m})]})})]})};export{L as DevNotesStickyPanel};
3
+ //# sourceMappingURL=DevNotesStickyPanel-BPakpEvi.js.map
assets/DevNotesStickyPanel-BPakpEvi.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"DevNotesStickyPanel-BPakpEvi.js","sources":["../../components/features/DevNotesStickyPanel.tsx"],"sourcesContent":["import React, { useState, useCallback } from 'react';\nimport { FileCodeIcon, SparklesIcon } from '../icons/FeatureIcons.tsx';\nimport { useLocalStorage } from '../../hooks/useLocalStorage.ts';\nimport { summarizeNotesStream } from '../../services/geminiService.ts';\nimport { LoadingSpinner } from '../shared/LoadingSpinner.tsx';\nimport { MarkdownRenderer } from '../shared/MarkdownRenderer.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-300 text-yellow-900', 'bg-green-300 text-green-900', 'bg-blue-300 text-blue-900', 'bg-pink-300 text-pink-900', 'bg-purple-300 text-purple-900'];\n\nexport const DevNotesStickyPanel: React.FC = () => {\n const [notes, setNotes] = useLocalStorage<Note[]>('devcore_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\n const addNote = () => {\n const newNote: Note = {\n id: Date.now(),\n text: 'New note...',\n x: 50 + (notes.length % 10) * 20,\n y: 50 + (notes.length % 10) * 20,\n color: colors[notes.length % colors.length],\n };\n setNotes([...notes, newNote]);\n };\n\n const updateText = (id: number, text: string) => {\n setNotes(notes.map((n: Note) => n.id === id ? { ...n, text } : n));\n };\n \n const deleteNote = (id: number, e: React.MouseEvent) => {\n e.stopPropagation();\n setNotes(notes.filter((n: Note) => n.id !== id));\n };\n\n const onMouseDown = (e: React.MouseEvent<HTMLDivElement>, id: number) => {\n if((e.target as HTMLElement).tagName === 'TEXTAREA' || (e.target as HTMLElement).tagName === 'BUTTON') return;\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 setNotes(\n notes.map((n: Note) =>\n n.id === dragging.id\n ? { ...n, x: e.clientX - dragging.offsetX - boardRect.left, y: e.clientY - dragging.offsetY - boardRect.top }\n : n\n )\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\"><FileCodeIcon /><span className=\"ml-3\">Dev Notes Sticky Panel</span></h1>\n <p className=\"text-text-secondary mt-1\">A place for your thoughts, todos, and random ideas.</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}\n onMouseUp={onMouseUp}\n onMouseLeave={onMouseUp}\n >\n {notes.map((note: Note) => (\n <div\n key={note.id}\n className={`group absolute w-48 h-48 p-2 flex flex-col shadow-lg cursor-grab active:cursor-grabbing rounded-md transition-transform duration-100 border border-black/30 ${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 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) => updateText(note.id, e.target.value)}\n className=\"w-full h-full bg-transparent resize-none focus:outline-none font-medium p-1 placeholder:text-inherit/50\"\n />\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","DevNotesStickyPanel","notes","setNotes","useLocalStorage","dragging","setDragging","useState","isSummarizing","setIsSummarizing","summary","setSummary","handleSummarize","useCallback","allNotesText","n","stream","summarizeNotesStream","fullResponse","chunk","error","addNote","newNote","updateText","id","text","deleteNote","e","onMouseDown","rect","onMouseMove","boardRect","onMouseUp","jsxs","jsx","FileCodeIcon","SparklesIcon","note","LoadingSpinner","MarkdownRenderer"],"mappings":"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"}
assets/FontPairingTool-BQS_3osJ.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as a,j as e}from"./react-D_B_5QVd.js";import{E as m}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.js";const p=["Roboto","Open Sans","Lato","Montserrat","Oswald","Source Sans Pro","Raleway","Poppins","Nunito","Merriweather","Playfair Display","Lora","Noto Sans","Ubuntu","PT Sans","Slabo 27px"],N=()=>{const[t,d]=a.useState("Oswald"),[n,c]=a.useState("Roboto");a.useEffect(()=>{const l=[t,n].filter(Boolean).join("|");if(l){const r="font-pairing-stylesheet";let s=document.getElementById(r);s||(s=document.createElement("link"),s.id=r,s.rel="stylesheet",document.head.appendChild(s)),s.href=`https://fonts.googleapis.com/css?family=${l.replace(/ /g,"+")}:400,700&display=swap`}},[t,n]);const i=({label:l,value:r,onChange:s})=>e.jsxs("div",{children:[e.jsx("label",{className:"block text-sm font-medium text-text-secondary",children:l}),e.jsx("select",{value:r,onChange:o=>s(o.target.value),className:"w-full mt-1 px-3 py-2 rounded-md bg-surface border border-border",children:p.map(o=>e.jsx("option",{value:o,children:o},o))})]});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(m,{}),e.jsx("span",{className:"ml-3",children:"Font Pairing Tool"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Preview Google Font combinations for your projects."})]}),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",children:[e.jsx("h3",{className:"text-xl font-bold",children:"Controls"}),e.jsx(i,{label:"Heading Font",value:t,onChange:d}),e.jsx(i,{label:"Body Font",value:n,onChange:c})]}),e.jsxs("div",{className:"lg:col-span-2 bg-background border border-border rounded-lg p-8 overflow-y-auto",children:[e.jsx("h2",{className:"text-4xl font-bold mb-4",style:{fontFamily:`'${t}', sans-serif`},children:"The Quick Brown Fox Jumps Over the Lazy Dog"}),e.jsx("p",{className:"text-lg",style:{fontFamily:`'${n}', sans-serif`},children:"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat."})]})]})]})};export{N as FontPairingTool};
2
+ //# sourceMappingURL=FontPairingTool-BQS_3osJ.js.map
assets/FontPairingTool-BQS_3osJ.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"FontPairingTool-BQS_3osJ.js","sources":["../../components/features/FontPairingTool.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { EyeIcon } from '../icons/FeatureIcons.tsx';\n\nconst popularFonts = [\n 'Roboto', 'Open Sans', 'Lato', 'Montserrat', 'Oswald', 'Source Sans Pro', 'Raleway', 'Poppins', 'Nunito', 'Merriweather',\n 'Playfair Display', 'Lora', 'Noto Sans', 'Ubuntu', 'PT Sans', 'Slabo 27px'\n];\n\nexport const FontPairingTool: React.FC = () => {\n const [headingFont, setHeadingFont] = useState('Oswald');\n const [bodyFont, setBodyFont] = useState('Roboto');\n\n useEffect(() => {\n const fontsToLoad = [headingFont, bodyFont].filter(Boolean).join('|');\n if (fontsToLoad) {\n const linkId = 'font-pairing-stylesheet';\n let link = document.getElementById(linkId) as HTMLLinkElement;\n if (!link) {\n link = document.createElement('link');\n link.id = linkId;\n link.rel = 'stylesheet';\n document.head.appendChild(link);\n }\n link.href = `https://fonts.googleapis.com/css?family=${fontsToLoad.replace(/ /g, '+')}:400,700&display=swap`;\n }\n }, [headingFont, bodyFont]);\n \n const FontSelector: React.FC<{ label: string, value: string, onChange: (font: string) => void }> = ({ label, value, onChange }) => (\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 {popularFonts.map(font => <option key={font} value={font}>{font}</option>)}\n </select>\n </div>\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 <EyeIcon />\n <span className=\"ml-3\">Font Pairing Tool</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Preview Google Font combinations for your projects.</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\">\n <h3 className=\"text-xl font-bold\">Controls</h3>\n <FontSelector label=\"Heading Font\" value={headingFont} onChange={setHeadingFont} />\n <FontSelector label=\"Body Font\" value={bodyFont} onChange={setBodyFont} />\n </div>\n <div className=\"lg:col-span-2 bg-background border border-border rounded-lg p-8 overflow-y-auto\">\n <h2 className=\"text-4xl font-bold mb-4\" style={{ fontFamily: `'${headingFont}', sans-serif` }}>\n The Quick Brown Fox Jumps Over the Lazy Dog\n </h2>\n <p className=\"text-lg\" style={{ fontFamily: `'${bodyFont}', sans-serif` }}>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat.\n </p>\n </div>\n </div>\n </div>\n );\n};\n"],"names":["popularFonts","FontPairingTool","headingFont","setHeadingFont","useState","bodyFont","setBodyFont","useEffect","fontsToLoad","linkId","link","FontSelector","label","value","onChange","jsx","e","font","jsxs","EyeIcon"],"mappings":"wQAGA,MAAMA,EAAe,CACjB,SAAU,YAAa,OAAQ,aAAc,SAAU,kBAAmB,UAAW,UAAW,SAAU,eAC1G,mBAAoB,OAAQ,YAAa,SAAU,UAAW,YAClE,EAEaC,EAA4B,IAAM,CAC3C,KAAM,CAACC,EAAaC,CAAc,EAAIC,EAAAA,SAAS,QAAQ,EACjD,CAACC,EAAUC,CAAW,EAAIF,EAAAA,SAAS,QAAQ,EAEjDG,EAAAA,UAAU,IAAM,CACZ,MAAMC,EAAc,CAACN,EAAaG,CAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EACpE,GAAIG,EAAa,CACb,MAAMC,EAAS,0BACf,IAAIC,EAAO,SAAS,eAAeD,CAAM,EACpCC,IACDA,EAAO,SAAS,cAAc,MAAM,EACpCA,EAAK,GAAKD,EACVC,EAAK,IAAM,aACX,SAAS,KAAK,YAAYA,CAAI,GAElCA,EAAK,KAAO,2CAA2CF,EAAY,QAAQ,KAAM,GAAG,CAAC,uBACzF,CACJ,EAAG,CAACN,EAAaG,CAAQ,CAAC,EAE1B,MAAMM,EAA6F,CAAC,CAAE,MAAAC,EAAO,MAAAC,EAAO,SAAAC,CAAA,WAC/G,MAAA,CACG,SAAA,CAAAC,EAAAA,IAAC,QAAA,CAAM,UAAU,gDAAiD,SAAAH,EAAM,EACxEG,EAAAA,IAAC,UAAO,MAAAF,EAAc,YAAeC,EAASE,EAAE,OAAO,KAAK,EAAG,UAAU,mEACpE,SAAAhB,EAAa,OAAYe,EAAAA,IAAC,SAAA,CAAkB,MAAOE,EAAO,SAAAA,GAApBA,CAAyB,CAAS,CAAA,CAC7E,CAAA,EACJ,EAGJ,OACIC,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OACd,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,uCACV,SAAA,CAAAH,EAAAA,IAACI,EAAA,EAAQ,EACTJ,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,mBAAA,CAAiB,CAAA,EAC5C,EACAA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,qDAAA,CAAmD,CAAA,EAC/F,EACAG,EAAAA,KAAC,MAAA,CAAI,UAAU,0DACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,mFACX,SAAA,CAAAH,EAAAA,IAAC,KAAA,CAAG,UAAU,oBAAoB,SAAA,WAAQ,QACzCJ,EAAA,CAAa,MAAM,eAAe,MAAOT,EAAa,SAAUC,EAAgB,QAChFQ,EAAA,CAAa,MAAM,YAAY,MAAON,EAAU,SAAUC,CAAA,CAAa,CAAA,EAC5E,EACAY,EAAAA,KAAC,MAAA,CAAI,UAAU,kFACX,SAAA,CAAAH,EAAAA,IAAC,KAAA,CAAG,UAAU,0BAA0B,MAAO,CAAE,WAAY,IAAIb,CAAW,eAAA,EAAmB,SAAA,6CAAA,CAE/F,EACAa,EAAAA,IAAC,IAAA,CAAE,UAAU,UAAU,MAAO,CAAE,WAAY,IAAIV,CAAQ,eAAA,EAAmB,SAAA,sWAAA,CAE3E,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,EACJ,CAER"}
assets/FontPreviewPicker-u7VEPcYp.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as l,j as e}from"./react-D_B_5QVd.js";import{E as d}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.js";const x=["Roboto","Open Sans","Lato","Montserrat","Oswald","Source Sans Pro","Raleway","Poppins","Nunito","Merriweather","Playfair Display","Lora","Noto Sans","Ubuntu","PT Sans","Slabo 27px"],v=()=>{const[s,i]=l.useState("Roboto"),[o,c]=l.useState("The quick brown fox jumps over the lazy dog.");l.useEffect(()=>{if(s){const t="font-preview-stylesheet";let r=document.getElementById(t);r||(r=document.createElement("link"),r.id=t,r.rel="stylesheet",document.head.appendChild(r)),r.href=`https://fonts.googleapis.com/css?family=${s.replace(/ /g,"+")}&display=swap`}},[s]);const a=`@import url('https://fonts.googleapis.com/css?family=${s.replace(/ /g,"+")}&display=swap');`,n=`font-family: '${s}', sans-serif;`;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:"Font Preview & Picker"})]}),e.jsx("p",{className:"text-text-secondary mt-1",children:"Preview Google Fonts and get the CSS import rule."})]}),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",children:[e.jsx("h3",{className:"text-xl font-bold",children:"Controls"}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"font-select",className:"block text-sm font-medium text-text-secondary",children:"Select Font"}),e.jsx("select",{id:"font-select",value:s,onChange:t=>i(t.target.value),className:"w-full mt-1 px-3 py-2 rounded-md bg-surface border border-border",children:x.map(t=>e.jsx("option",{value:t,children:t},t))})]}),e.jsxs("div",{children:[e.jsx("label",{htmlFor:"preview-text",className:"block text-sm font-medium text-text-secondary",children:"Preview Text"}),e.jsx("textarea",{id:"preview-text",value:o,onChange:t=>c(t.target.value),className:"w-full mt-1 p-2 rounded-md bg-surface border border-border h-24 resize-none"})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("label",{className:"block text-sm font-medium text-text-secondary",children:"CSS Rules"}),e.jsxs("div",{className:"relative",children:[e.jsx("pre",{className:"bg-background p-2 rounded-md text-primary text-xs overflow-x-auto",children:a}),e.jsx("button",{onClick:()=>navigator.clipboard.writeText(a),className:"absolute top-1 right-1 px-2 py-0.5 bg-gray-100 hover:bg-gray-200 rounded-md text-xs",children:"Copy"})]}),e.jsxs("div",{className:"relative",children:[e.jsx("pre",{className:"bg-background p-2 rounded-md text-primary text-xs overflow-x-auto",children:n}),e.jsx("button",{onClick:()=>navigator.clipboard.writeText(n),className:"absolute top-1 right-1 px-2 py-0.5 bg-gray-100 hover:bg-gray-200 rounded-md text-xs",children:"Copy"})]})]})]}),e.jsx("div",{className:"lg:col-span-2 bg-background border border-border rounded-lg p-8 flex items-center justify-center",children:e.jsx("p",{className:"text-4xl",style:{fontFamily:`'${s}', sans-serif`},children:o})})]})]})};export{v as FontPreviewPicker};
2
+ //# sourceMappingURL=FontPreviewPicker-u7VEPcYp.js.map
assets/FontPreviewPicker-u7VEPcYp.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"FontPreviewPicker-u7VEPcYp.js","sources":["../../components/features/FontPreviewPicker.tsx"],"sourcesContent":["import React, { useState, useEffect } from 'react';\nimport { EyeIcon } from '../icons/FeatureIcons.tsx';\n\nconst popularFonts = [\n 'Roboto', 'Open Sans', 'Lato', 'Montserrat', 'Oswald', 'Source Sans Pro', 'Raleway', 'Poppins', 'Nunito', 'Merriweather',\n 'Playfair Display', 'Lora', 'Noto Sans', 'Ubuntu', 'PT Sans', 'Slabo 27px'\n];\n\nexport const FontPreviewPicker: React.FC = () => {\n const [selectedFont, setSelectedFont] = useState('Roboto');\n const [previewText, setPreviewText] = useState('The quick brown fox jumps over the lazy dog.');\n\n useEffect(() => {\n if (selectedFont) {\n const linkId = 'font-preview-stylesheet';\n let link = document.getElementById(linkId) as HTMLLinkElement;\n if (!link) {\n link = document.createElement('link');\n link.id = linkId;\n link.rel = 'stylesheet';\n document.head.appendChild(link);\n }\n link.href = `https://fonts.googleapis.com/css?family=${selectedFont.replace(/ /g, '+')}&display=swap`;\n }\n }, [selectedFont]);\n \n const importRule = `@import url('https://fonts.googleapis.com/css?family=${selectedFont.replace(/ /g, '+')}&display=swap');`;\n const cssRule = `font-family: '${selectedFont}', sans-serif;`;\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 <EyeIcon />\n <span className=\"ml-3\">Font Preview & Picker</span>\n </h1>\n <p className=\"text-text-secondary mt-1\">Preview Google Fonts and get the CSS import rule.</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\">\n <h3 className=\"text-xl font-bold\">Controls</h3>\n <div>\n <label htmlFor=\"font-select\" className=\"block text-sm font-medium text-text-secondary\">Select Font</label>\n <select id=\"font-select\" value={selectedFont} onChange={e => setSelectedFont(e.target.value)} className=\"w-full mt-1 px-3 py-2 rounded-md bg-surface border border-border\">\n {popularFonts.map(font => <option key={font} value={font}>{font}</option>)}\n </select>\n </div>\n <div>\n <label htmlFor=\"preview-text\" className=\"block text-sm font-medium text-text-secondary\">Preview Text</label>\n <textarea id=\"preview-text\" value={previewText} onChange={e => setPreviewText(e.target.value)} className=\"w-full mt-1 p-2 rounded-md bg-surface border border-border h-24 resize-none\"></textarea>\n </div>\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium text-text-secondary\">CSS Rules</label>\n <div className=\"relative\"><pre className=\"bg-background p-2 rounded-md text-primary text-xs overflow-x-auto\">{importRule}</pre><button onClick={() => navigator.clipboard.writeText(importRule)} className=\"absolute top-1 right-1 px-2 py-0.5 bg-gray-100 hover:bg-gray-200 rounded-md text-xs\">Copy</button></div>\n <div className=\"relative\"><pre className=\"bg-background p-2 rounded-md text-primary text-xs overflow-x-auto\">{cssRule}</pre><button onClick={() => navigator.clipboard.writeText(cssRule)} className=\"absolute top-1 right-1 px-2 py-0.5 bg-gray-100 hover:bg-gray-200 rounded-md text-xs\">Copy</button></div>\n </div>\n </div>\n <div className=\"lg:col-span-2 bg-background border border-border rounded-lg p-8 flex items-center justify-center\">\n <p className=\"text-4xl\" style={{ fontFamily: `'${selectedFont}', sans-serif` }}>\n {previewText}\n </p>\n </div>\n </div>\n </div>\n );\n};\n"],"names":["popularFonts","FontPreviewPicker","selectedFont","setSelectedFont","useState","previewText","setPreviewText","useEffect","linkId","link","importRule","cssRule","jsxs","jsx","EyeIcon","e","font"],"mappings":"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"}
assets/JsonTreeNavigator-DaOkIsmx.js ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as p,j as e}from"./react-D_B_5QVd.js";import{F as f}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.js";const u=({data:s,nodeKey:l,isRoot:n=!1})=>{const[r,c]=p.useState(n),i=typeof s=="object"&&s!==null,a=()=>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),o=Array.isArray(s)?"[]":"{}";return e.jsxs("div",{className:`ml-4 ${n?"":"pl-4 border-l border-border"}`,children:[e.jsxs("button",{onClick:a,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:o[0]}),!r&&e.jsxs("span",{className:"text-text-secondary",children:["...",o[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:o[1]})]})]})},O=({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}}),[a,x]=p.useState(""),o=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),o(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 ${a?"border-red-500":"border-border"} rounded-md resize-y font-mono text-sm focus:ring-2 focus:ring-primary focus:outline-none`}),a&&e.jsx("p",{className:"text-red-500 text-xs mt-1",children:a})]}),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{O as JsonTreeNavigator};
13
+ //# sourceMappingURL=JsonTreeNavigator-DaOkIsmx.js.map
assets/JsonTreeNavigator-DaOkIsmx.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"JsonTreeNavigator-DaOkIsmx.js","sources":["../../components/features/JsonTreeNavigator.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { FileCodeIcon } from '../icons/FeatureIcons.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};\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":"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"}
assets/LogicFlowBuilder-rTNUT_Hr.js ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ import{r as x,j as e,R as M}from"./react-D_B_5QVd.js";import{o as D,Y as g}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./marked-CesSW9Du.js";import"./idb-Dob3nYDb.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)"})]})),O=()=>{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{O as LogicFlowBuilder};
2
+ //# sourceMappingURL=LogicFlowBuilder-rTNUT_Hr.js.map
assets/LogicFlowBuilder-rTNUT_Hr.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"LogicFlowBuilder-rTNUT_Hr.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/FeatureIcons.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-CVq-A3yp.js ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import{r as t,j as e}from"./react-D_B_5QVd.js";import{m as p}from"./marked-CesSW9Du.js";import{P as g}from"./index-BdwitBZy.js";import"./jszip-C9ownNzX.js";import"./react-dom-EAO2-NBm.js";import"./scheduler-DYLXRpC5.js";import"./@google-4tyssLU_.js";import"./idb-Dob3nYDb.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
+ `,M=()=>{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{M as MarkdownSlides};
24
+ //# sourceMappingURL=MarkdownSlides-CVq-A3yp.js.map
assets/MarkdownSlides-CVq-A3yp.js.map ADDED
@@ -0,0 +1 @@
 
 
1
+ {"version":3,"file":"MarkdownSlides-CVq-A3yp.js","sources":["../../components/features/MarkdownSlides.tsx"],"sourcesContent":["import React, { useState, useMemo, useEffect, useRef, useCallback } from 'react';\nimport { marked } from 'marked';\nimport { PhotoIcon } from '../icons/FeatureIcons.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};\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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"}