PageSourceSearch

https://fishersama.com/assets/SvgPreviewer-9623ffb3.js

js fishersama.com collected 2026-10-02 01:30:25 UTC 17,222 bytes, 330 lines download raw bytes

1import{u as he,r as s,j as t,e as me,S as ue,_ as ve}from"./index-3d88130a.js";import{g as i}from"./styled-components.browser.esm-ef6924ab.js";import we from"./purify.es-c09583cd.js";import{u as be}from"./usePageLoading-43692476.js";const ye=i.div`
2  min-height: 100vh;
3  background: linear-gradient(135deg, #f5f7ff 0%, #ffffff 100%);
4  padding: clamp(5rem, 6vw, 6rem) 2rem 2.5rem;
5  position: relative;
6
7  &::before {
8    content: '';
9    position: absolute;
10    inset: 0;
11    background:
12      linear-gradient(90deg, rgba(99, 102, 241, 0.05) 1px, transparent 1px),
13      linear-gradient(rgba(99, 102, 241, 0.05) 1px, transparent 1px);
14    background-size: 20px 20px;
15    pointer-events: none;
16  }
17`,Pe=i.div`
18  display: flex;
19  gap: 2rem;
20  max-width: 1400px;
21  margin: 0 auto;
22  position: relative;
23  z-index: 1;
24
25  @media (max-width: 1024px) {
26    flex-direction: column;
27  }
28`,q=i.div`
29  flex: 1;
30  min-width: 320px;
31  background: rgba(255, 255, 255, 0.88);
32  border-radius: 20px;
33  padding: clamp(1.25rem, 2vw, 1.75rem);
34  border: 1px solid rgba(255, 255, 255, 0.35);
35  box-shadow: 0 20px 50px rgba(79, 70, 229, 0.12);
36  backdrop-filter: blur(12px);
37  display: flex;
38  flex-direction: column;
39  gap: 1.25rem;
40`,ke=i(q)`
41  position: relative;
42  overflow: hidden;
43`,je=i.header`
44  display: flex;
45  flex-direction: column;
46  gap: 0.75rem;
47`,Se=i.h1`
48  font-size: clamp(1.75rem, 2.4vw, 2.3rem);
49  margin: 0;
50  background: linear-gradient(135deg, #6366F1 0%, #8B5CF6 100%);
51  -webkit-background-clip: text;
52  -webkit-text-fill-color: transparent;
53  font-weight: 800;
54  letter-spacing: -0.02em;
55`,Ce=i.p`
56  margin: 0;
57  color: #475569;
58  line-height: 1.65;
59`,N=i.div`
60  display: flex;
61  flex-direction: column;
62  gap: 0.35rem;
63`,O=i.h2`
64  font-size: 1.15rem;
65  font-weight: 600;
66  color: #111827;
67  margin: 0;
68`,W=i.p`
69  font-size: 0.95rem;
70  color: #64748b;
71  margin: 0;
72  line-height: 1.5;
73`,J=i.div`
74  display: flex;
75  flex-direction: column;
76  gap: 0.5rem;
77`,V=i.label`
78  font-size: 0.92rem;
79  font-weight: 600;
80  color: #475569;
81`,Te=i.div`
82  display: grid;
83  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
84  gap: 0.5rem;
85`,ze=i.button`
86  display: inline-flex;
87  align-items: center;
88  justify-content: center;
89  gap: 0.3rem;
90  padding: 0.5rem 0.75rem;
91  border-radius: 10px;
92  border: 2px solid ${({$selected:e})=>e?"rgba(99, 102, 241, 0.8)":"rgba(148, 163, 184, 0.4)"};
93  background: ${({$selected:e})=>e?"rgba(99, 102, 241, 0.12)":"rgba(248, 250, 252, 0.8)"};
94  color: ${({$selected:e})=>e?"#4338ca":"#475569"};
95  font-size: 0.85rem;
96  font-weight: 600;
97  cursor: pointer;
98  transition: all 0.2s ease;
99
100  &:hover {
101    border-color: rgba(99, 102, 241, 0.8);
102    color: #4338ca;
103    transform: translateY(-1px);
104  }
105
106  &:focus-visible {
107    outline: none;
108    box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.18);
109  }
110`,Re=i(J)`
111  flex: 1;
112`,Le=i.textarea`
113  width: 100%;
114  min-height: 360px;
115  font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace;
116  font-size: 0.95rem;
117  line-height: 1.6;
118  color: #0f172a;
119  border: 1px solid rgba(148, 163, 184, 0.4);
120  border-radius: 14px;
121  padding: 1rem;
122  background: rgba(255, 255, 255, 0.95);
123  resize: vertical;
124  transition: border 0.2s ease, box-shadow 0.2s ease;
125  box-shadow: inset 0 2px 6px rgba(15, 23, 42, 0.04);
126
127  &:focus {
128    border-color: rgba(99, 102, 241, 0.5);
129    box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.15);
130    outline: none;
131  }
132`,Be=i.div`
133  display: flex;
134  flex-wrap: wrap;
135  gap: 0.75rem;
136`,F=i.button`
137  border: none;
138  border-radius: 999px;
139  padding: 0.65rem 1.4rem;
140  font-size: 0.9rem;
141  font-weight: 600;
142  cursor: pointer;
143  transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease;
144  display: inline-flex;
145  align-items: center;
146  gap: 0.4rem;
147  background: ${({variant:e})=>e==="primary"?"linear-gradient(135deg, #6366F1 0%, #8B5CF6 100%)":"rgba(99, 102, 241, 0.08)"};
148  color: ${({variant:e})=>e==="primary"?"#fff":"#4338ca"};
149  box-shadow: ${({variant:e})=>e==="primary"?"0 18px 30px rgba(79, 70, 229, 0.25)":"none"};
150
151  &:disabled {
152    opacity: 0.6;
153    cursor: not-allowed;
154  }
155
156  &:not(:disabled):hover {
157    transform: translateY(-1px);
158    box-shadow: ${({variant:e})=>e==="primary"?"0 20px 36px rgba(79, 70, 229, 0.3)":"0 8px 18px rgba(79, 70, 229, 0.15)"};
159  }
160`,Fe=i.div`
161  display: flex;
162  gap: 0.75rem;
163  flex-wrap: wrap;
164`,K=i.span`
165  padding: 0.35rem 0.85rem;
166  border-radius: 999px;
167  background: rgba(15, 23, 42, 0.05);
168  color: #475569;
169  font-size: 0.8rem;
170  font-weight: 500;
171`,Y=i.div`
172  margin-top: 0.75rem;
173  padding: 0.85rem 1rem;
174  border-radius: 14px;
175  font-size: 0.9rem;
176  background: ${({type:e})=>e==="success"?"rgba(16, 185, 129, 0.12)":"rgba(248, 113, 113, 0.15)"};
177  color: ${({type:e})=>e==="success"?"#047857":"#b91c1c"};
178  border: 1px solid
179    ${({type:e})=>e==="success"?"rgba(16, 185, 129, 0.3)":"rgba(248, 113, 113, 0.3)"};
180`,Me=i.div`
181  flex: 1;
182  border-radius: 18px;
183  border: 1px solid rgba(148, 163, 184, 0.35);
184  padding: 1.5rem;
185  background: #ffffff;
186  min-height: 460px;
187  position: relative;
188  overflow: auto;
189  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.35);
190`,Ee=i.div`
191  width: 100%;
192  min-height: 100%;
193  display: flex;
194  align-items: ${({$centered:e})=>e?"center":"flex-start"};
195  justify-content: ${({$centered:e})=>e?"center":"flex-start"};
196`,$e=i.div`
197  display: inline-flex;
198  align-items: center;
199  justify-content: center;
200  transform-origin: top left;
201  transition: transform 0.15s ease;
202  flex-shrink: 0;
203`,Ae=i.div`
204  display: inline-flex;
205  align-items: center;
206  justify-content: center;
207  flex-direction: column;
208
209  svg {
210    width: auto;
211    height: auto;
212    max-width: none;
213  }
214`,Ge=i.div`
215  text-align: center;
216  color: #94a3b8;
217  font-size: 0.95rem;
218  line-height: 1.6;
219`,De=i.div`
220  display: flex;
221  justify-content: flex-end;
222  margin-bottom: 0.75rem;
223`,Ie=i(F)`
224  position: relative;
225`,Ue=i.div`
226  max-width: 1220px;
227  margin: 3rem auto 0;
228  padding: clamp(1.5rem, 3vw, 2.5rem);
229  background: linear-gradient(135deg, rgba(99, 102, 241, 0.12) 0%, rgba(255, 255, 255, 0.85) 55%, rgba(244, 246, 255, 0.9) 100%);
230  border-radius: 28px;
231  border: 1px solid rgba(99, 102, 241, 0.18);
232  box-shadow: 0 35px 60px rgba(79, 70, 229, 0.18);
233  position: relative;
234  z-index: 1;
235  display: flex;
236  flex-direction: column;
237  gap: 1.75rem;
238`,X=i.section`
239  background: rgba(255, 255, 255, 0.95);
240  border-radius: 20px;
241  padding: clamp(1.5rem, 3vw, 2.25rem);
242  border: 1px solid rgba(148, 163, 184, 0.2);
243  box-shadow: 0 18px 32px rgba(79, 70, 229, 0.12);
244`,_e=i.h2`
245  font-size: 1.6rem;
246  font-weight: 700;
247  color: #1f2937;
248  margin-bottom: 1rem;
249`,He=i.div`
250  display: grid;
251  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
252  gap: 1.25rem;
253`,Ne=i.article`
254  background: rgba(249, 250, 255, 0.92);
255  border: 1px solid rgba(99, 102, 241, 0.15);
256  border-radius: 18px;
257  padding: 1.35rem;
258  box-shadow: 0 16px 28px rgba(99, 102, 241, 0.12);
259  display: flex;
260  flex-direction: column;
261  gap: 0.35rem;
262`,Oe=i.h3`
263  font-size: 1rem;
264  margin: 0;
265  font-weight: 600;
266  color: #1f2937;
267`,We=i.p`
268  font-size: 0.92rem;
269  color: #4b5563;
270  margin: 0;
271  line-height: 1.55;
272`,P=[{id:"gradientBadge",labelKey:"tools.svgPreviewer.examples.gradientBadge",code:`<svg width="320" height="200" viewBox="0 0 320 200" xmlns="http://www.w3.org/2000/svg">
273  <defs>
274    <linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
275      <stop offset="0%" stop-color="#6366F1"/>
276      <stop offset="100%" stop-color="#A855F7"/>
277    </linearGradient>
278    <filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
279      <feDropShadow dx="0" dy="12" stdDeviation="20" flood-color="#000000" flood-opacity="0.2"/>
280    </filter>
281  </defs>
282  <rect width="320" height="200" rx="32" fill="url(#gradient)" filter="url(#shadow)"/>
283  <g transform="translate(32, 42)" fill="white">
284    <text x="0" y="0" font-size="18" fill="rgba(255,255,255,0.8)">AI Toolbox</text>
285    <text x="0" y="36" font-size="32" font-weight="700">SVG Preview</text>
286    <text x="0" y="70" font-size="16" fill="rgba(255,255,255,0.8)">Live rendering · Export ready</text>
287  </g>
288  <circle cx="250" cy="60" r="26" fill="rgba(255,255,255,0.2)" stroke="rgba(255,255,255,0.6)" stroke-width="2"/>
289  <path d="M244 60 L253 69 L266 49" stroke="white" stroke-width="4" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
290</svg>`},{id:"htmlLayout",labelKey:"tools.svgPreviewer.examples.htmlBlock",code:`<div style="width: 320px; padding: 24px; border-radius: 24px; background: #0f172a; color: white; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI';">
291  <h2 style="margin: 0 0 12px; font-size: 1.25rem;">Inline HTML + SVG</h2>
292  <p style="opacity: 0.8; margin: 0 0 16px; line-height: 1.4;">
293    Mix HTML and SVG snippets to prototype UI blocks and badges with gradient fills.
294  </p>
295  <svg width="272" height="80" viewBox="0 0 272 80" xmlns="http://www.w3.org/2000/svg">
296    <defs>
297      <linearGradient id="pill" x1="0%" y1="0%" x2="100%" y2="0%">
298        <stop offset="0%" stop-color="#22d3ee"/>
299        <stop offset="100%" stop-color="#818cf8"/>
300      </linearGradient>
301    </defs>
302    <rect x="0" y="0" width="272" height="80" rx="40" fill="url(#pill)" opacity="0.15"/>
303    <text x="26" y="48" fill="#bae6fd" font-size="24" font-weight="600">export.png</text>
304    <circle cx="216" cy="40" r="20" fill="rgba(255,255,255,0.3)"/>
305    <path d="M208 40 L214 46 L226 34" stroke="white" stroke-width="4" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
306  </svg>
307</div>`},{id:"chart",labelKey:"tools.svgPreviewer.examples.chart",code:`<svg width="360" height="220" viewBox="0 0 360 220" xmlns="http://www.w3.org/2000/svg">
308  <defs>
309    <linearGradient id="line" x1="0%" y1="0%" x2="0%" y2="100%">
310      <stop offset="0%" stop-color="#38bdf8"/>
311      <stop offset="100%" stop-color="#2563eb"/>
312    </linearGradient>
313    <filter id="glow">
314      <feGaussianBlur stdDeviation="4" result="coloredBlur"/>
315      <feMerge>
316        <feMergeNode in="coloredBlur"/>
317        <feMergeNode in="SourceGraphic"/>
318      </feMerge>
319    </filter>
320  </defs>
321  <rect width="360" height="220" rx="28" fill="#0f172a"/>
322  <g transform="translate(32, 32)">
323    <text x="0" y="-8" fill="#94a3b8" font-size="12">SVG Sparkline · last 7 days</text>
324    <polyline points="0,130 40,110 80,120 120,80 160,90 200,40 240,70 280,30"
325      fill="none" stroke="url(#line)" stroke-width="4" stroke-linecap="round" filter="url(#glow)"/>
326    <circle cx="200" cy="40" r="6" fill="#38bdf8"/>
327    <text x="200" y="20" text-anchor="middle" fill="#e0f2fe" font-size="12">+48%</text>
328    <line x1="0" y1="130" x2="280" y2="130" stroke="rgba(148,163,184,0.35)" stroke-dasharray="6 6"/>
329  </g>
330</svg>`}],k="custom",qe=()=>{const{t:e}=he(),Q=be(),[c,j]=s.useState(P[0].code),[M,S]=s.useState(P[0].id),[E,u]=s.useState(""),[$,A]=s.useState(""),[G,D]=s.useState(!1),p=s.useRef(null),v=s.useRef(null),I="svg-previewer-editor",[Z,w]=s.useState(1),[ee,b]=s.useState(!0),U=s.useMemo(()=>{if(!c.trim())return"";try{return we.sanitize(c,{USE_PROFILES:{svg:!0,svgFilters:!0,html:!0},ADD_ATTR:["style","class","viewBox","fill","stroke","stroke-width","stroke-linecap","stroke-linejoin","filterUnits","markerHeight","markerWidth","orient","gradientUnits","clipPathUnits","preserveAspectRatio","xmlns","xmlns:xlink"],ADD_TAGS:["foreignObject","animate","animateMotion","animateTransform","linearGradient","radialGradient","stop","pattern","mask","clipPath","feDropShadow","feGaussianBlur"]})}catch(r){return console.error("Failed to sanitize SVG/HTML snippet",r),""}},[c]),f=!!c.trim(),te=c.length,re=c.split(/\n/).length;s.useEffect(()=>{if(!f){w(1),b(!0);return}const r=()=>{if(!v.current||!p.current)return;const n=v.current,d=p.current,a=window.getComputedStyle(n),C=(parseFloat(a.paddingLeft)||0)+(parseFloat(a.paddingRight)||0),T=(parseFloat(a.paddingTop)||0)+(parseFloat(a.paddingBottom)||0),z=Math.max(0,n.clientWidth-C),R=Math.max(0,n.clientHeight-T),h=d.scrollWidth,g=d.scrollHeight;if(!h||!g){w(1),b(!0);return}const m=z/h,x=R/g,l=Math.min(1,m,x);if(!Number.isFinite(l)||l<=0){w(1),b(!0);return}w(l),b(l===1)},o=typeof ResizeObserver<"u"?new ResizeObserver(r):null;return r(),o==null||o.observe(p.current),o==null||o.observe(v.current),window.addEventListener("resize",r),()=>{o==null||o.disconnect(),window.removeEventListener("resize",r)}},[f,U]);const ie=r=>{if(S(r),r===k)return;const o=P.find(n=>n.id===r);o&&j(o.code)},oe=r=>{M!==k&&S(k),j(r.target.value)},ne=async()=>{if(!(navigator!=null&&navigator.clipboard)){u(e("tools.svgPreviewer.notifications.copyUnavailable"));return}try{await navigator.clipboard.writeText(c),u(e("tools.svgPreviewer.notifications.copied")),setTimeout(()=>u(""),2e3)}catch(r){console.error("Clipboard copy failed",r),u(e("tools.svgPreviewer.notifications.copyFailed"))}},se=()=>{j(""),S(k)},_=r=>{const o=r.toDataURL("image/png"),n=document.createElement("a");n.href=o,n.download=`svg-preview-${Date.now()}.png`,n.click()},ae=async r=>{const o=(await ve(()=>import("./html2canvas.esm-e0a7d97b.js"),[])).default,n=document.createElement("div"),d=r.cloneNode(!0);n.style.position="fixed",n.style.left="-10000px",n.style.top="0",n.style.pointerEvents="none",n.style.background="#ffffff",n.appendChild(d),document.body.appendChild(n);try{const a=await o(d,{backgroundColor:"#ffffff",scale:2,useCORS:!0});_(a)}finally{document.body.removeChild(n)}},le=async r=>{const o=r.cloneNode(!0);o.getAttribute("xmlns")||o.setAttribute("xmlns","http://www.w3.org/2000/svg");const d=new XMLSerializer().serializeToString(o),a=o.getAttribute("viewBox"),[,,C,T]=a?a.split(/\s+/):[],z=o.getAttribute("width"),R=o.getAttribute("height"),h=r.getBoundingClientRect(),g=parseFloat(z)||parseFloat(C)||h.width||800,m=parseFloat(R)||parseFloat(T)||h.height||600,x=window.devicePixelRatio||1,l=document.createElement("canvas");l.width=Math.max(1,Math.round(g*x)),l.height=Math.max(1,Math.round(m*x));const L=l.getContext("2d");L.scale(x,x),await new Promise((ge,xe)=>{const y=new Image,B=URL.createObjectURL(new Blob([d],{type:"image/svg+xml;charset=utf-8"}));y.onload=()=>{L.clearRect(0,0,g,m),L.drawImage(y,0,0,g,m),URL.revokeObjectURL(B),ge()},y.onerror=fe=>{URL.revokeObjectURL(B),xe(fe)},y.src=B}),_(l)},ce=async()=>
330{if(!(!p.current||!f)){D(!0),A("");try{const r=p.current,o=r.querySelectorAll("svg");o.length===1&&r.childElementCount===1&&r.firstElementChild===o[0]?await le(o[0]):await ae(r)}catch(r){console.error("Failed to export preview",r),A(e("tools.svgPreviewer.errors.export"))}finally{D(!1)}}},H=[{title:e("tools.svgPreviewer.tips.sanitize.title"),desc:e("tools.svgPreviewer.tips.sanitize.description")},{title:e("tools.svgPreviewer.tips.gradients.title"),desc:e("tools.svgPreviewer.tips.gradients.description")},{title:e("tools.svgPreviewer.tips.export.title"),desc:e("tools.svgPreviewer.tips.export.description")}],de=e("tools.svgPreviewer.tipsTitle"),pe=H.length>0;return t.jsxs(t.Fragment,{children:[Q&&t.jsx(me,{}),t.jsx(ue,{title:e("tools.svgPreviewer.metaTitle"),description:e("tools.svgPreviewer.metaDescription")}),t.jsxs(ye,{children:[t.jsxs(Pe,{children:[t.jsxs(q,{children:[t.jsxs(N,{children:[t.jsx(O,{children:e("tools.svgPreviewer.editorTitle")}),t.jsx(W,{children:e("tools.svgPreviewer.editorDescription")})]}),t.jsxs(J,{children:[t.jsx(V,{as:"span",children:e("tools.svgPreviewer.selectPreset")}),t.jsx(Te,{role:"group","aria-label":e("tools.svgPreviewer.selectPreset"),children:P.map(r=>{const o=e(r.labelKey),n=M===r.id;return t.jsx(ze,{type:"button","aria-pressed":n,$selected:n,onClick:()=>ie(r.id),children:o},r.id)})})]}),t.jsxs(Re,{children:[t.jsx(V,{htmlFor:I,children:e("tools.svgPreviewer.inputLabel")}),t.jsx(Le,{id:I,value:c,onChange:oe,spellCheck:!1,placeholder:e("tools.svgPreviewer.placeholder")})]}),t.jsxs(Fe,{children:[t.jsx(K,{children:`${re} ${e("tools.svgPreviewer.stats.lines")}`}),t.jsx(K,{children:`${te} ${e("tools.svgPreviewer.stats.chars")}`})]}),t.jsxs(Be,{children:[t.jsx(F,{variant:"secondary",type:"button",onClick:ne,children:e("tools.svgPreviewer.actions.copy")}),t.jsx(F,{type:"button",onClick:se,children:e("tools.svgPreviewer.actions.clear")})]}),E&&t.jsx(Y,{type:"success",children:E})]}),t.jsxs(ke,{"aria-live":"polite",children:[t.jsxs(N,{children:[t.jsx(O,{children:e("tools.svgPreviewer.previewTitle")}),t.jsx(W,{children:e("tools.svgPreviewer.previewDescription")})]}),t.jsx(De,{children:t.jsx(Ie,{variant:"primary",type:"button",disabled:!f||G,onClick:ce,children:e(G?"tools.svgPreviewer.actions.exporting":"tools.svgPreviewer.actions.export")})}),t.jsx(Me,{ref:v,children:f?t.jsx(Ee,{$centered:ee,children:t.jsx($e,{style:{transform:`scale(${Z})`},children:t.jsx(Ae,{ref:p,dangerouslySetInnerHTML:{__html:U}})})}):t.jsx(Ge,{children:e("tools.svgPreviewer.previewPlaceholder")})}),$&&t.jsx(Y,{children:$})]})]}),t.jsxs(Ue,{children:[t.jsx(X,{children:t.jsxs(je,{as:"section",children:[t.jsx(Se,{children:e("tools.svgPreviewer.title")}),t.jsx(Ce,{children:e("tools.svgPreviewer.description")})]})}),pe&&t.jsxs(X,{children:[t.jsx(_e,{children:de}),t.jsx(He,{children:H.map(r=>t.jsxs(Ne,{children:[t.jsx(Oe,{children:r.title}),t.jsx(We,{children:r.desc})]},r.title))})]})]})]})]})};export{qe as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.