1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js"; 2import { a as api } from "./index-w5lXls15.js"; 3import { L as ListPage } from "./ListPage-T07W6I80.js"; 4import { bI as Hash, bg as Music, bA as Eye } from "./vendor-D0P4XgNj.js"; 5import "./vendor-i18n-BC7ZMXWQ.js"; 6import "./main-aQ5jZgYp.js"; 7import "./vendor-react-three-BCww3P1x.js"; 8import "./utils-CEVb7nN1.js"; 9import "./synth-Fr-K52Ox.js"; 10import "./wasm-synth-adapter-DpNGIIyM.js"; 11import "./vendor-spessasynth-DH8n6o_V.js"; 12import "./vendor-audio-D-wTggbx.js"; 13import "./Waveform-BgnMyg5E.js"; 14import "./vendor-framer-B-4FZk1Z.js"; 15import "./labTools-HX5HYAPB.js"; 16import "./UserAvatar-BQN4jlY-.js"; 17import "./AdSlot-BEBlpA_I.js"; 18const TagPage = ({ tagName, tracks: initialTracks, onSelectTrack, onToggleWatchLater, watchLaterSet, onNavigate }) => { 19 const [lyrics, setLyrics] = reactExports.useState([]); 20 const [loadingLyrics, setLoadingLyrics] = reactExports.useState(false); 21 const [tracks, setTracks] = reactExports.useState([]); 22 const [loadingTracks, setLoadingTracks] = reactExports.useState(false); 23 reactExports.useEffect(() => { 24 if (tagName) { 25 setLoadingLyrics(true); 26 api.searchLyrics(tagName, 1, 30).then((res) => { 27 setLyrics(res.results); 28 }).catch((err) => console.error("[Tag Lyrics Load Fail]", err)).finally(() => setLoadingLyrics(false)); 29 setLoadingTracks(true); 30 const fetchTracksForTag = async () => { 31 try { 32 const allTags = await api.getTags(); 33 const matchedTag = allTags.find( 34 (t) => t.name.toLowerCase() === tagName.toLowerCase() || t.slug === tagName.toLowerCase() 35 ); 36 const slug = matchedTag ? matchedTag.slug : tagName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/(^-|-$)/g, ""); 37 const res = await api.getTracks("", slug, "recent", 100); 38 setTracks(res); 39 } catch (err) { 40 console.error("[Tag Tracks Load Fail]", err); 41 setTracks([]); 42 } finally { 43 setLoadingTracks(false); 44 } 45 }; 46 fetchTracksForTag(); 47 } else { 48 setTracks([]); 49 } 50 }, [tagName]); 51 return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "max-w-6xl mx-auto px-4 py-2", children: [ 52 loadingTracks ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col items-center justify-center py-20", children: [
53 /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-10 h-10 border-4 border-indigo-500 border-t-transparent rounded-full animate-spin mb-4" }), 54 /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "text-zinc-500 text-sm font-medium", children: [ 55 "Loading tracks for #", 56 tagName, 57 "..." 58 ] }) 59 ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx( 60 ListPage, 61 { 62 icon: Hash, 63 title: `#${tagName}`, 64 tracks, 65 onSelectTrack, 66 onToggleWatchLater, 67 watchLaterSet 68 } 69 ), 70 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-12 mb-8 p-6 bg-zinc-50 dark:bg-zinc-900/30 border border-zinc-200 dark:border-zinc-800 rounded-2xl", children: [ 71 /* @__PURE__ */ jsxRuntimeExports.jsxs("h2", { className: "text-xl font-bold text-zinc-900 dark:text-white mb-6 flex items-center gap-2", children: [ 72 /* @__PURE__ */ jsxRuntimeExports.jsx(Music, { size: 20, className: "text-indigo-500" }), 73 "Matching Lyrics" 74 ] }), 75 loadingLyrics ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex justify-center py-8", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "w-6 h-6 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }) }) : lyrics.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-3", children: lyrics.map((lyric) => /* @__PURE__ */ jsxRuntimeExports.jsxs( 76 "div", 77 { 78 onClick: () => onNavigate && onNavigate("lyrics", lyric.id), 79 className: "p-4 bg-white dark:bg-zinc-950 border border-zinc-200 dark:border-zinc-800/80 hover:border-indigo-500 rounded-xl cursor-pointer transition flex items-center justify-between shadow-sm hover:shadow", 80 children: [
81 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "truncate pr-4", children: [ 82 /* @__PURE__ */ jsxRuntimeExports.jsx("h4", { className: "font-bold text-zinc-800 dark:text-zinc-200 truncate text-sm", children: lyric.title }), 83 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-zinc-400 mt-1 truncate", children: [ 84 lyric.artist && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-indigo-400 font-semibold", children: lyric.artist }), 85 lyric.album && /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { children: [ 86 "⢠", 87 lyric.album 88 ] }) 89 ] }) 90 ] }), 91 /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 text-xs text-zinc-400 shrink-0", children: [ 92 /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, { size: 12 }), 93 /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: lyric.views }) 94 ] }) 95 ] 96 }, 97 lyric.id 98 )) }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-center py-8 text-zinc-400 text-sm", children: "No lyrics sheets found with this tag." }) 99 ] }) 100 ] }); 101}; 102export { 103 TagPage as default 104};
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.