PageSourceSearch

https://www.hamienet.com/assets/ScoreConverterPage-BOEx74Gz.js

js hamienet.com collected 2026-10-02 05:00:15 UTC 23,119 bytes, 378 lines download raw bytes

1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js";
2import { C as CreditsExhaustedModal } from "./CreditsExhaustedModal-DRhMaBTs.js";
3import { u as useTranslation } from "./vendor-i18n-BC7ZMXWQ.js";
4import { co as FileMusic, ec as CloudUpload, bE as Link, ed as File, bF as ChevronRight, cM as RefreshCw, a_ as CircleCheck, aY as TriangleAlert, d1 as Download, b1 as CircleAlert } from "./vendor-D0P4XgNj.js";
5function ScoreConverterPage({
6  currentUser,
7  onAuthRequested
8}) {
9  var _a, _b, _c, _d, _e, _f;
10  const { t } = useTranslation();
11  const [activeTab, setActiveTab] = reactExports.useState("file");
12  const [file, setFile] = reactExports.useState(null);
13  const [url, setUrl] = reactExports.useState("");
14  const [status, setStatus] = reactExports.useState("idle");
15  const [jobId, setJobId] = reactExports.useState(null);
16  const [progress, setProgress] = reactExports.useState(0);
17  const [result, setResult] = reactExports.useState(null);
18  const [errorMsg, setErrorMsg] = reactExports.useState("");
19  const [isPublishing, setIsPublishing] = reactExports.useState(false);
20  const [showCreditWarning, setShowCreditWarning] = reactExports.useState(false);
21  const [showExhausted, setShowExhausted] = reactExports.useState(false);
22  const [isDragging, setIsDragging] = reactExports.useState(false);
23  const fileInputRef = reactExports.useRef(null);
24  const onDragOver = (e) => {
25    e.preventDefault();
26    setIsDragging(true);
27  };
28  const onDragLeave = (e) => {
29    e.preventDefault();
30    setIsDragging(false);
31  };
32  const onDrop = (e) => {
33    e.preventDefault();
34    setIsDragging(false);
35    if (e.dataTransfer.files && e.dataTransfer.files[0]) {
36      setFile(e.dataTransfer.files[0]);
37    }
38  };
39  reactExports.useEffect(() => {
40    let interval;
41    if (status === "processing" && jobId) {
42      interval = setInterval(async () => {
43        try {
44          const res = await fetch(`/api/score-converter/status/${jobId}`);
45          const data = await res.json();
46          if (data.status === "completed") {
47            setStatus("completed");
48            setResult(data.result);
49            clearInterval(interval);
50          } else if (data.status === "error" || data.status === "failed") {
51            setStatus("error");
52            setErrorMsg(data.error || data.details || "An error occurred during conversion.");
53            clearInterval(interval);
54          } else {
55            setProgress(data.progress || 0);
56          }
57        } catch (e) {
58          setStatus("error");
59          setErrorMsg("Failed to check status.");
60          clearInterval(interval);
61        }
62      }, 2e3);
63    }
64    return () => clearInterval(interval);
65  }, [status, jobId]);
66  const startConversion = () => {
67    if (!currentUser) {
68      onAuthRequested();
69      return;
70    }
71    if (activeTab === "file" && !file || activeTab === "url" && !url.trim()) {
72      return;
73    }
74    setShowCreditWarning(true);
75  };
76  const confirmConversion = async () => {
77    setShowCreditWarning(false);
78    if (((currentUser == null ? void 0 : currentUser.credits) || 0) < 3) {
79      setShowExhausted(true);
80      return;
81    }
82    setStatus("processing");
83    setProgress(0);
84    setErrorMsg("");
85    try {
86      let res;
87      if (activeTab === "file" && file) {
88        const formData = new FormData();
89        formData.append("file", file);
90        res = await fetch("/api/score-converter/convert", {
91          method: "POST",
92          body: formData
93        });
94      } else if (activeTab === "url" && url) {
95        res = await fetch("/api/score-converter/convert-url", {
96          method: "POST",
97          headers: { "Content-Type": "application/json" },
98          body: JSON.stringify({ url })
99        });
100      } else {
101        return;
102      }
103      const data = await res.json();
104      if (data.success && data.jobId) {
105        setJobId(data.jobId);
106      } else {
107        setStatus("error");
108        setErrorMsg(data.error || "Failed to start conversion.");
109      }
110    } catch (e) {
111      setStatus("error");
112      setErrorMsg("Network error while starting conversion.");
113    }
114  };
115  const handlePublish = async () => {
116    if (!jobId || isPublishing) return;
117    setIsPublishing(true);
118    try {
119      const res = await fetch("/api/score-converter/upload-to-site", {
120        method: "POST",
121        headers: { "Content-Type": "application/json" },
122        body: JSON.stringify({ jobId })
123      });
124      const data = await res.json();
125      if (data.success && data.trackUrl) {
126        window.location.href = data.trackUrl;
127      } else {
128        alert(data.error || "Failed to publish.");
129        setIsPublishing(false);
130      }
131    } catch (e) {
132      alert("Error publishing to site.");
133      setIsPublishing(false);
134    }
135  };
136  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-h-screen bg-zinc-50 dark:bg-zinc-950 py-12 px-4 sm:px-6 lg:px-8", children: [
137    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-4xl mx-auto", children: [
138      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center mb-12", children: [
139        /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "inline-flex items-center justify-center w-16 h-16 rounded-full bg-blue-100 dark:bg-blue-900/30 mb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx(FileMusic, { className: "w-8 h-8 text-blue-600 dark:text-blue-400" }) }),
140        /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-4xl font-extrabold text-zinc-900 dark:text-white tracking-tight", children: "Score Format Converter" }),
141        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-4 text-lg text-zinc-600 dark:text-zinc-400 max-w-2xl mx-auto", children: "Transform your digital sheet music files (MXL, MusicXML, MuseScore) into high-quality standard MIDI formats seamlessly." })
142      ] }),
143      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-zinc-900 rounded-2xl shadow-xl border border-zinc-200 dark:border-zinc-800 overflow-hidden", children: [
144        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex border-b border-zinc-200 dark:border-zinc-800", children: [
145          /* @__PURE__ */ jsxRuntimeExports.jsxs(
146            "button",
147            {
148              onClick: () => setActiveTab("file"),
149              className: `flex-1 py-4 px-6 text-sm font-medium flex items-center justify-center gap-2 transition-colors ${activeTab === "file" ? "border-b-2 border-blue-500 text-blue-600 dark:text-blue-400 bg-blue-50/50 dark:bg-blue-900/10" : "text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-300"}`,
150              children: [
151                /* @__PURE__ */ jsxRuntimeExports.jsx(CloudUpload, { className: "w-4 h-4" }),
152                "Upload File"
153              ]
154            }
155          ),
156          /* @__PURE__ */ jsxRuntimeExports.jsxs(
157            "button",
158            {
159              onClick: () => setActiveTab("url"),
160              className: `flex-1 py-4 px-6 text-sm font-medium flex items-center justify-center gap-2 transition-colors ${activeTab === "url" ? "border-b-2 border-blue-500 text-blue-600 dark:text-blue-400 bg-blue-50/50 dark:bg-blue-900/10" : "text-zinc-500 hover:text-zinc-700 dark:text-zinc-400 dark:hover:text-zinc-300"}`,
161              children: [
162                /* @__PURE__ */ jsxRuntimeExports.jsx(Link, { className: "w-4 h-4" }),
163                "Enter URL"
164              ]
165            }
166          )
167        ] }),
168        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-8", children: [
169          status === "idle" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-8", children: [
170            activeTab === "file" ? /* @__PURE__ */ jsxRuntimeExports.jsxs(
171              "div",
172              {
173                onDragOver,
174                onDragLeave,
175                onDrop,
176                className: `border-2 border-dashed rounded-xl p-12 text-center transition-all ${isDragging ? "border-blue-500 bg-blue-50 dark:bg-blue-900/20" : "border-zinc-300 dark:border-zinc-700 hover:border-blue-400 hover:bg-zinc-50 dark:hover:bg-zinc-800/50"}`,
177                children: [
178                  /* @__PURE__ */ jsxRuntimeExports.jsx(
179                    "input",
180                    {
181                      type: "file",
182                      ref: fileInputRef,
183                      className: "hidden",
184                      accept: ".mxl,.xml,.musicxml,.mscz,.mscx,.ly,.ily,.abc,.ptb,.gp,.gp3,.gp4,.gp5,.gp6,.gp7,.gpx,.krn,.ham,.cap,.capx,.ove,.scw",
185                      onChange: (e) => {
186                        if (e.target.files && e.target.files[0]) {
187                          setFile(e.target.files[0]);
188                        }
189                      }
190                    }
191                  ),
192                  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-auto w-16 h-16 mb-4 rounded-full bg-zinc-100 dark:bg-zinc-800 flex items-center justify-center", children: file ? /* @__PURE__ */ jsxRuntimeExports.jsx(File, { className: "w-8 h-8 text-blue-500" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(CloudUpload, { className: "w-8 h-8 text-zinc-400" }) }),
193                  /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-lg font-medium text-zinc-900 dark:text-zinc-100 mb-2", children: file ? file.name : "Drag & drop your score file here" }),
194                  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-zinc-500 dark:text-zinc-400 mb-6", children: file ? `${(file.size / 1024 / 1024).toFixed(2)} MB` : "Supports MusicXML, MuseScore, LilyPond, ABC, Guitar Pro, PowerTab, Humdrum, and Hamie up to 50MB" }),
195                  /* @__PURE__ */ jsxRuntimeExports.jsx(
196                    "button",
197                    {
198                      onClick: () => {
199                        var _a2;
200                        return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
201                      },
202                      className: "px-6 py-2.5 rounded-lg bg-zinc-900 dark:bg-white text-white dark:text-zinc-900 font-medium hover:bg-zinc-800 dark:hover:bg-zinc-100 transition-colors",
203                      children: "Browse Files"
204                    }
205                  )
206                ]
207              }
208            ) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-4", children: [
209              /* @__PURE__ */ jsxRuntimeExports.jsx("label", { className: "block text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Score URL (MuseScore, IMSLP, abcnotation, etc.)" }),
210              /* @__PURE__ */ jsxRuntimeExports.jsx(
211                "input",
212                {
213                  type: "url",
214                  value: url,
215                  onChange: (e) => setUrl(e.target.value),
216                  placeholder: "https://...",
217                  className: "w-full px-4 py-3 rounded-xl border border-zinc-300 dark:border-zinc-700 bg-white dark:bg-zinc-900 text-zinc-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-all"
218                }
219              )
220            ] }),
221            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(
222              "button",
223              {
224                onClick: startConversion,
225                disabled: activeTab === "file" ? !file : !url.trim(),
226                className: "flex items-center gap-2 px-8 py-3.5 bg-blue-600 hover:bg-blue-700 disabled:opacity-50 disabled:hover:bg-blue-600 text-white rounded-xl font-semibold shadow-md shadow-blue-500/20 transition-all",
227                children: [
228                  "Convert Score",
229                  /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { className: "w-5 h-5" })
230                ]
231              }
232            ) })
233          ] }),
234          status === "processing" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "py-12 text-center", children: [
235            /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "w-12 h-12 text-blue-500 mx-auto animate-spin mb-6" }),
236            /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-xl font-bold text-zinc-900 dark:text-white mb-2", children: "Converting your score..." }),
237            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-zinc-500 dark:text-zinc-400 mb-8", children: "This might take a minute depending on the complexity." }),
238            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "max-w-md mx-auto bg-zinc-100 dark:bg-zinc-800 rounded-full h-3 overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
239              "div",
240              {
241                className: "bg-blue-500 h-full rounded-full transition-all duration-500 ease-out",
242                style: { width: `${progress}%` }
243              }
244            ) }),
245            /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mt-3 text-sm font-medium text-blue-600 dark:text-blue-400", children: [
246              progress,
247              "% Complete"
248            ] })
249          ] }),
250          status === "completed" && result && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-8 animate-in fade-in slide-in-from-bottom-4 duration-500", children: [
251            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-center", children: [
252              /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "inline-flex items-center justify-center w-16 h-16 rounded-full bg-green-100 dark:bg-green-900/30 mb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleCheck, { className: "w-8 h-8 text-green-600 dark:text-green-400" }) }),
253              /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-2xl font-bold text-zinc-900 dark:text-white", children: "Conversion Successful!" })
254            ] }),
255            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-zinc-50 dark:bg-zinc-800/50 rounded-xl p-6 border border-zinc-200 dark:border-zinc-700", children: [
256              /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold text-zinc-900 dark:text-white uppercase tracking-wider mb-4", children: "Metadata" }),
257              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
258                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
259                  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "Title" }),
260                  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-medium text-zinc-900 dark:text-white truncate", children: ((_a = result.metadata) == null ? void 0 : _a.title) && result.metadata.title.toLowerCase() !== "unknown" ? result.metadata.title : file ? file.name.replace(/\.[^/.]+$/, "") : "Converted Score" })
261                ] }),
262                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
263                  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "Composer" }),
264                  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-medium text-zinc-900 dark:text-white truncate", children: ((_b = result.metadata) == null ? void 0 : _b.composer) && !["unknown", "unknown artist", "unknown composer"].includes(result.metadata.composer.trim().toLowerCase()) ? result.metadata.composer : "-" })
265                ] }),
266                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
267                  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "Time Signature" }),
268                  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-medium text-zinc-900 dark:text-white", children: ((_c = result.metadata) == null ? void 0 : _c.timeSignature) || ((_d = result.metadata) == null ? void 0 : _d.time_signature) || "-" })
269                ] }),
270                /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
271                  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "Key" }),
272                  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "font-medium text-zinc-900 dark:text-white", children: ((_e = result.metadata) == null ? void 0 : _e.key) || ((_f = result.metadata) == null ? void 0 : _f.key_signature) || "-" })
273                ] })
274              ] })
275            ] }),
276            result.warnings && result.warnings.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-800 rounded-xl p-4 flex gap-3", children: [
277              /* @__PURE__ */ jsxRuntimeExports.jsx(TriangleAlert, { className: "w-5 h-5 text-amber-600 dark:text-amber-500 flex-shrink-0" }),
278              /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
279                /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "text-sm font-semibold text-amber-800 dark:text-amber-400 mb-1", children: "Warnings" }),
280                /* @__PURE__ */ jsxRuntimeExports.jsx("ul", { className: "text-sm text-amber-700 dark:text-amber-500 list-disc list-inside", children: result.warnings.map((w, i) => /* @__PURE__ */ jsxRuntimeExports.jsx("li", { children: w }, i)) })
281              ] })
282            ] }),
283            /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row gap-4 pt-4 border-t border-zinc-200 dark:border-zinc-800", children: [
284              /* @__PURE__ */ jsxRuntimeExports.jsxs(
285                "a",
286                {
287                  href: `/api/score-converter/download/${jobId}`,
288                  download: true,
289                  className: "flex-1 flex items-center justify-center gap-2 px-6 py-3.5 bg-zinc-900 hover:bg-zinc-800 dark:bg-white dark:hover:bg-zinc-100 text-white dark:text-zinc-900 rounded-xl font-semibold transition-colors",
290                  children: [
291                    /* @__PURE__ */ jsxRuntimeExports.jsx(Download, { className: "w-5 h-5" }),
292                    "Download MIDI"
293                  ]
294                }
295              ),
296              /* @__PURE__ */ jsxRuntimeExports.jsx(
297                "button",
298                {
299                  onClick: handlePublish,
300                  disabled: isPublishing,
301                  className: "flex-1 flex items-center justify-center gap-2 px-6 py-3.5 bg-blue-600 hover:bg-blue-700 disabled:opacity-60 text-white rounded-xl font-semibold shadow-md shadow-blue-500/20 transition-all",
302                  children: isPublishing ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
303                    /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "w-5 h-5 animate-spin" }),
304                    "Publishing to HamieNET..."
305                  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
306                    /* @__PURE__ */ jsxRuntimeExports.jsx(CloudUpload, { className: "w-5 h-5" }),
307                    "Publish to HamieNET"
308                  ] })
309                }
310              )
311            ] })
312          ] }),
313          status === "error" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "py-12 text-center animate-in fade-in", children: [
314            /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "inline-flex items-center justify-center w-16 h-16 rounded-full bg-red-100 dark:bg-red-900/30 mb-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "w-8 h-8 text-red-600 dark:text-red-400" }) }),
315            /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-2xl font-bold text-zinc-900 dark:text-white mb-2", children: "Conversion Failed" }),
316            /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-red-600 dark:text-red-400 mb-8 max-w-md mx-auto", children: errorMsg }),
317            /* @__PURE__ */ jsxRuntimeExports.jsx(
318              "button",
319              {
320                onClick: () => {
321                  setStatus("idle");
322                  setProgress(0);
323                },
324                className: "px-8 py-3 bg-zinc-900 hover:bg-zinc-800 dark:bg-white dark:hover:bg-zinc-100 text-white dark:text-zinc-900 rounded-xl font-semibold transition-colors",
325                children: "Try Again"
326              }
327            )
328          ] })
329        ] })
330      ] })
331    ] }),
332    showCreditWarning && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "bg-white dark:bg-zinc-900 rounded-2xl max-w-md w-full p-6 shadow-2xl animate-in zoom-in-95 duration-200", children: [
333      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex justify-between items-start mb-4", children: [
334        /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-xl font-bold text-zinc-900 dark:text-white", children: "Confirm Action" }),
335        /* @__PURE__ */ jsxRuntimeExports.jsx("button", { onClick: () => setShowCreditWarning(false), className: "text-zinc-500 hover:text-zinc-700 dark:hover:text-zinc-300", children: /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "w-6 h-6" }) })
336      ] }),
337      /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-zinc-600 dark:text-zinc-400 mb-6", children: [
338        "Converting a score costs ",
339        /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "text-zinc-900 dark:text-white", children: "3 credits" }),
340        ". You currently have ",
341        /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "text-zinc-900 dark:text-white", children: (currentUser == null ? void 0 : currentUser.credits) || 0 }),
342        " credits remaining."
343      ] }),
344      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-3 justify-end", children: [
345        /* @__PURE__ */ jsxRuntimeExports.jsx(
346          "button",
347          {
348            onClick: () => setShowCreditWarning(false),
349            className: "px-5 py-2.5 rounded-lg text-sm font-medium text-zinc-700 dark:text-zinc-300 hover:bg-zinc-100 dark:hover:bg-zinc-800 transition-colors",
350            children: "Cancel"
351          }
352        ),
353        /* @__PURE__ */ jsxRuntimeExports.jsx(
354          "button",
355          {
356            onClick: confirmConversion,
357            className: "px-5 py-2.5 rounded-lg text-sm font-medium bg-blue-600 hover:bg-blue-700 text-white shadow-sm transition-colors",
358            children: "Confirm & Convert"
359          }
360        )
361      ] })
362    ] }) }),
363    /* @__PURE__ */ jsxRuntimeExports.jsx(
364      CreditsExhaustedModal,
365      {
366        isOpen: showExhausted,
367        onClose: () => setShowExhausted(false),
368        onSignUp: () => {
369          setShowExhausted(false);
370          onAuthRequested();
371        }
372      }
373    )
374  ] });
375}
376export {
377  ScoreConverterPage as default
378};

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.