CoolFace
Apppublic

admin08077/Githubgemini

sourceHugging Faceotherupdated 10mo agoView on Hugging Face
0likes
SvgPathEditor-BK1SMCC-.js.map1 linesDownload Raw Back to assets
1{"version":3,"file":"SvgPathEditor-BK1SMCC-.js","sources":["../../components/features/SvgPathEditor.tsx"],"sourcesContent":["import React, { useState, useRef } from 'react';\nimport { CodeBracketSquareIcon, ArrowDownTrayIcon } from '../icons.tsx';\nimport { downloadFile } from '../../services/fileUtils.ts';\n\nconst initialPath = \"M 20 80 Q 100 20 180 80 T 340 80\";\n\nconst parsePath = (d: string) => {\n    const commands = d.match(/[a-df-z][^a-df-z]*/ig) || [];\n    return commands.map((cmdStr, i) => {\n        const command = cmdStr[0];\n        const args = cmdStr.slice(1).trim().split(/[\\s,]+/).map(parseFloat).filter(n => !isNaN(n));\n        const points = [];\n        for (let j = 0; j < args.length; j += 2) {\n            points.push({ x: args[j], y: args[j + 1] });\n        }\n        return { id: i, command, points };\n    });\n};\n\nconst buildPath = (parsed: any[]) => {\n    return parsed.map(cmd => `${cmd.command} ${cmd.points.map((p:any) => `${p.x} ${p.y}`).join(' ')}`).join(' ');\n};\n\nexport const SvgPathEditor: React.FC = () => {\n    const [pathData, setPathData] = useState(initialPath);\n    const svgRef = useRef<SVGSVGElement>(null);\n    const [draggingPoint, setDraggingPoint] = useState<any>(null);\n    const parsedPath = parsePath(pathData);\n\n    const handleMouseDown = (e: React.MouseEvent, cmdIndex: number, pointIndex: number) => {\n        e.stopPropagation();\n        setDraggingPoint({ cmdIndex, pointIndex });\n    };\n\n    const handleMouseMove = (e: React.MouseEvent) => {\n        if (!draggingPoint || !svgRef.current) return;\n        const pt = new DOMPoint(e.clientX, e.clientY);\n        const svgPoint = pt.matrixTransform(svgRef.current.getScreenCTM()?.inverse());\n        \n        const newParsedPath = parsedPath.map((cmd, cIdx) => {\n            if (cIdx === draggingPoint.cmdIndex) {\n                const newPoints = cmd.points.map((p, pIdx) => {\n                    if (pIdx === draggingPoint.pointIndex) {\n                        return { x: Math.round(svgPoint.x), y: Math.round(svgPoint.y) };\n                    }\n                    return p;\n                });\n                return { ...cmd, points: newPoints };\n            }\n            return cmd;\n        });\n        setPathData(buildPath(newParsedPath));\n    };\n    \n    const handleMouseUp = () => setDraggingPoint(null);\n    \n    const handleAddPoint = (e: React.MouseEvent) => {\n        if (!svgRef.current) return;\n        const pt = new DOMPoint(e.clientX, e.clientY);\n        const svgPoint = pt.matrixTransform(svgRef.current.getScreenCTM()?.inverse());\n        const newPathData = `${pathData} L ${Math.round(svgPoint.x)} ${Math.round(svgPoint.y)}`;\n        setPathData(newPathData);\n    };\n\n    const handleDownload = () => {\n        const svgContent = `<svg viewBox=\"0 0 400 160\" xmlns=\"http://www.w3.org/2000/svg\">\n  <path d=\"${pathData}\" stroke=\"black\" fill=\"transparent\" stroke-width=\"2\"/>\n</svg>`;\n        downloadFile(svgContent, 'path.svg', 'image/svg+xml');\n    };\n\n    return (\n        <div className=\"h-full flex flex-col p-4 sm:p-6 lg:p-8 text-text-primary\">\n            <header className=\"mb-6\"><h1 className=\"text-3xl font-bold flex items-center\"><CodeBracketSquareIcon /><span className=\"ml-3\">SVG Path Editor</span></h1><p className=\"text-text-secondary mt-1\">Visually create and manipulate SVG path data by dragging points.</p></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 overflow-y-auto\">\n                    <div className=\"flex justify-between items-center mb-2\">\n                        <label htmlFor=\"path-input\" className=\"text-sm font-medium text-text-secondary\">Path Data (d attribute)</label>\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 SVG\n                        </button>\n                    </div>\n                    <textarea id=\"path-input\" value={pathData} onChange={(e) => setPathData(e.target.value)} className=\"h-24 p-4 bg-surface border border-border rounded-md resize-y font-mono text-sm text-primary\" />\n                     <div className=\"flex-grow mt-4 p-4 bg-surface border-2 border-dashed border-border rounded-md overflow-hidden flex items-center justify-center min-h-[200px]\">\n                        <svg ref={svgRef} viewBox=\"0 0 400 160\" className=\"w-full h-full cursor-crosshair\" onMouseMove={handleMouseMove} onMouseUp={handleMouseUp} onMouseLeave={handleMouseUp} onDoubleClick={handleAddPoint}>\n                           <rect width=\"400\" height=\"160\" fill=\"var(--color-background)\" />\n                            <path d={pathData} stroke=\"var(--color-primary)\" fill=\"transparent\" strokeWidth=\"2\" />\n                            {parsedPath.flatMap((cmd, cmdIndex) => \n                                cmd.points.map((p, pointIndex) => (\n                                    <circle\n                                        key={`${cmd.id}-${pointIndex}`}\n                                        cx={p.x}\n                                        cy={p.y}\n                                        r=\"5\"\n                                        fill={cmd.command.toLowerCase() === 'c' || cmd.command.toLowerCase() === 'q' || cmd.command.toLowerCase() === 's' || cmd.command.toLowerCase() === 't' ? '#fde047' : '#f87171'}\n                                        stroke=\"var(--color-surface)\"\n                                        strokeWidth=\"2\"\n                                        className=\"cursor-move hover:stroke-primary\"\n                                        onMouseDown={(e) => handleMouseDown(e, cmdIndex, pointIndex)}\n                                    />\n                                ))\n                            )}\n                        </svg>\n                    </div>\n                    <p className=\"text-xs text-center text-text-secondary mt-2\">Double-click on the canvas to add a new point.</p>\n                </div>\n                <div className=\"flex flex-col h-full\">\n                    <label className=\"text-sm font-medium text-text-secondary mb-2\">Parsed Commands</label>\n                    <div className=\"flex-grow p-2 bg-background border border-border rounded-md overflow-y-auto font-mono text-xs space-y-2\">\n                        {parsedPath.map(cmd => (\n                            <div key={cmd.id} className=\"p-2 bg-surface rounded\">\n                                <span className=\"font-bold text-amber-600\">{cmd.command}</span>\n                                <span className=\"text-text-secondary\"> {cmd.points.map(p => `(${p.x},${p.y})`).join(' ')}</span>\n                            </div>\n                        ))}\n                    </div>\n                </div>\n            </div>\n        </div>\n    );\n};"],"names":["initialPath","parsePath","d","cmdStr","i","command","args","n","points","j","buildPath","parsed","cmd","p","SvgPathEditor","pathData","setPathData","useState","svgRef","useRef","draggingPoint","setDraggingPoint","parsedPath","handleMouseDown","e","cmdIndex","pointIndex","handleMouseMove","svgPoint","newParsedPath","cIdx","newPoints","pIdx","handleMouseUp","handleAddPoint","newPathData","handleDownload","svgContent","downloadFile","jsxs","jsx","CodeBracketSquareIcon","ArrowDownTrayIcon"],"mappings":"+pFAIA,MAAMA,EAAc,mCAEdC,EAAaC,IACEA,EAAE,MAAM,sBAAsB,GAAK,CAAA,GACpC,IAAI,CAACC,EAAQC,IAAM,CAC/B,MAAMC,EAAUF,EAAO,CAAC,EAClBG,EAAOH,EAAO,MAAM,CAAC,EAAE,KAAA,EAAO,MAAM,QAAQ,EAAE,IAAI,UAAU,EAAE,UAAY,CAAC,MAAMI,CAAC,CAAC,EACnFC,EAAS,CAAA,EACf,QAASC,EAAI,EAAGA,EAAIH,EAAK,OAAQG,GAAK,EAClCD,EAAO,KAAK,CAAE,EAAGF,EAAKG,CAAC,EAAG,EAAGH,EAAKG,EAAI,CAAC,CAAA,CAAG,EAE9C,MAAO,CAAE,GAAIL,EAAG,QAAAC,EAAS,OAAAG,CAAA,CAC7B,CAAC,EAGCE,EAAaC,GACRA,EAAO,IAAIC,GAAO,GAAGA,EAAI,OAAO,IAAIA,EAAI,OAAO,IAAKC,GAAU,GAAGA,EAAE,CAAC,IAAIA,EAAE,CAAC,EAAE,EAAE,KAAK,GAAG,CAAC,EAAE,EAAE,KAAK,GAAG,EAGlGC,GAA0B,IAAM,CACzC,KAAM,CAACC,EAAUC,CAAW,EAAIC,EAAAA,SAASjB,CAAW,EAC9CkB,EAASC,EAAAA,OAAsB,IAAI,EACnC,CAACC,EAAeC,CAAgB,EAAIJ,EAAAA,SAAc,IAAI,EACtDK,EAAarB,EAAUc,CAAQ,EAE/BQ,EAAkB,CAACC,EAAqBC,EAAkBC,IAAuB,CACnFF,EAAE,gBAAA,EACFH,EAAiB,CAAE,SAAAI,EAAU,WAAAC,EAAY,CAC7C,EAEMC,EAAmBH,GAAwB,CAC7C,GAAI,CAACJ,GAAiB,CAACF,EAAO,QAAS,OAEvC,MAAMU,EADK,IAAI,SAASJ,EAAE,QAASA,EAAE,OAAO,EACxB,gBAAgBN,EAAO,QAAQ,aAAA,GAAgB,SAAS,EAEtEW,EAAgBP,EAAW,IAAI,CAACV,EAAKkB,IAAS,CAChD,GAAIA,IAASV,EAAc,SAAU,CACjC,MAAMW,EAAYnB,EAAI,OAAO,IAAI,CAACC,EAAGmB,IAC7BA,IAASZ,EAAc,WAChB,CAAE,EAAG,KAAK,MAAMQ,EAAS,CAAC,EAAG,EAAG,KAAK,MAAMA,EAAS,CAAC,CAAA,EAEzDf,CACV,EACD,MAAO,CAAE,GAAGD,EAAK,OAAQmB,CAAA,CAC7B,CACA,OAAOnB,CACX,CAAC,EACDI,EAAYN,EAAUmB,CAAa,CAAC,CACxC,EAEMI,EAAgB,IAAMZ,EAAiB,IAAI,EAE3Ca,EAAkBV,GAAwB,CAC5C,GAAI,CAACN,EAAO,QAAS,OAErB,MAAMU,EADK,IAAI,SAASJ,EAAE,QAASA,EAAE,OAAO,EACxB,gBAAgBN,EAAO,QAAQ,aAAA,GAAgB,SAAS,EACtEiB,EAAc,GAAGpB,CAAQ,MAAM,KAAK,MAAMa,EAAS,CAAC,CAAC,IAAI,KAAK,MAAMA,EAAS,CAAC,CAAC,GACrFZ,EAAYmB,CAAW,CAC3B,EAEMC,EAAiB,IAAM,CACzB,MAAMC,EAAa;AAAA,aACdtB,CAAQ;AAAA,QAEbuB,EAAaD,EAAY,WAAY,eAAe,CACxD,EAEA,OACIE,EAAAA,KAAC,MAAA,CAAI,UAAU,2DACX,SAAA,CAAAA,EAAAA,KAAC,SAAA,CAAO,UAAU,OAAO,SAAA,CAAAA,EAAAA,KAAC,KAAA,CAAG,UAAU,uCAAuC,SAAA,CAAAC,EAAAA,IAACC,EAAA,EAAsB,EAAED,EAAAA,IAAC,OAAA,CAAK,UAAU,OAAO,SAAA,iBAAA,CAAe,CAAA,EAAO,EAAKA,EAAAA,IAAC,IAAA,CAAE,UAAU,2BAA2B,SAAA,kEAAA,CAAgE,CAAA,EAAI,EACrQD,EAAAA,KAAC,MAAA,CAAI,UAAU,yEACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,uCACX,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,yCACX,SAAA,CAAAC,MAAC,QAAA,CAAM,QAAQ,aAAa,UAAU,0CAA0C,SAAA,0BAAuB,EACtGD,EAAAA,KAAC,SAAA,CAAO,QAASH,EAAgB,UAAU,qFACxC,SAAA,CAAAI,EAAAA,IAACE,EAAA,CAAkB,UAAU,SAAA,CAAS,EAAE,eAAA,CAAA,CAC5C,CAAA,EACJ,EACAF,EAAAA,IAAC,WAAA,CAAS,GAAG,aAAa,MAAOzB,EAAU,SAAWS,GAAMR,EAAYQ,EAAE,OAAO,KAAK,EAAG,UAAU,8FAA8F,QAC/L,MAAA,CAAI,UAAU,+IACZ,SAAAe,EAAAA,KAAC,MAAA,CAAI,IAAKrB,EAAQ,QAAQ,cAAc,UAAU,iCAAiC,YAAaS,EAAiB,UAAWM,EAAe,aAAcA,EAAe,cAAeC,EACpL,SAAA,CAAAM,MAAC,QAAK,MAAM,MAAM,OAAO,MAAM,KAAK,0BAA0B,EAC7DA,EAAAA,IAAC,QAAK,EAAGzB,EAAU,OAAO,uBAAuB,KAAK,cAAc,YAAY,GAAA,CAAI,EACnFO,EAAW,QAAQ,CAACV,EAAKa,IACtBb,EAAI,OAAO,IAAI,CAACC,EAAGa,IACfc,EAAAA,IAAC,SAAA,CAEG,GAAI3B,EAAE,EACN,GAAIA,EAAE,EACN,EAAE,IACF,KAAMD,EAAI,QAAQ,YAAA,IAAkB,KAAOA,EAAI,QAAQ,YAAA,IAAkB,KAAOA,EAAI,QAAQ,gBAAkB,KAAOA,EAAI,QAAQ,YAAA,IAAkB,IAAM,UAAY,UACrK,OAAO,uBACP,YAAY,IACZ,UAAU,mCACV,YAAcY,GAAMD,EAAgBC,EAAGC,EAAUC,CAAU,CAAA,EARtD,GAAGd,EAAI,EAAE,IAAIc,CAAU,EAAA,CAUnC,CAAA,CACL,CAAA,CACJ,CAAA,CACJ,EACAc,EAAAA,IAAC,IAAA,CAAE,UAAU,+CAA+C,SAAA,gDAAA,CAA8C,CAAA,EAC9G,EACAD,EAAAA,KAAC,MAAA,CAAI,UAAU,uBACX,SAAA,CAAAC,EAAAA,IAAC,QAAA,CAAM,UAAU,+CAA+C,SAAA,kBAAe,EAC/EA,EAAAA,IAAC,MAAA,CAAI,UAAU,0GACV,SAAAlB,EAAW,IAAIV,GACZ2B,EAAAA,KAAC,MAAA,CAAiB,UAAU,yBACxB,SAAA,CAAAC,EAAAA,IAAC,OAAA,CAAK,UAAU,2BAA4B,SAAA5B,EAAI,QAAQ,EACxD2B,EAAAA,KAAC,OAAA,CAAK,UAAU,sBAAsB,SAAA,CAAA,IAAE3B,EAAI,OAAO,IAAIC,GAAK,IAAIA,EAAE,CAAC,IAAIA,EAAE,CAAC,GAAG,EAAE,KAAK,GAAG,CAAA,CAAA,CAAE,CAAA,GAFnFD,EAAI,EAGd,CACH,CAAA,CACL,CAAA,CAAA,CACJ,CAAA,CAAA,CACJ,CAAA,EACJ,CAER"}