PageSourceSearch

https://www.hamienet.com/assets/ExplorePage-Dvljs4Ju.js

js hamienet.com collected 2026-10-02 04:59:48 UTC 11,285 bytes, 232 lines download raw bytes

1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js";
2import { T as TrackRow } from "./TrackRow-CdYYo5vh.js";
3import { a as api } from "./index-w5lXls15.js";
4import { A as AdSlot } from "./AdSlot-BEBlpA_I.js";
5import { u as useTranslation } from "./vendor-i18n-BC7ZMXWQ.js";
6import { bO as Library, de as Flame, cH as Tag, bi as Sparkles } from "./vendor-D0P4XgNj.js";
7import "./main-aQ5jZgYp.js";
8import "./vendor-react-three-BCww3P1x.js";
9import "./utils-CEVb7nN1.js";
10import "./synth-Fr-K52Ox.js";
11import "./wasm-synth-adapter-DpNGIIyM.js";
12import "./vendor-spessasynth-DH8n6o_V.js";
13import "./vendor-audio-D-wTggbx.js";
14import "./Waveform-BgnMyg5E.js";
15import "./vendor-framer-B-4FZk1Z.js";
16import "./labTools-HX5HYAPB.js";
17import "./UserAvatar-BQN4jlY-.js";
18const CategoryCard = ({ icon: Icon, label, color, gradient, href }) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
19  "a",
20  {
21    href,
22    className: "group relative flex flex-col items-center justify-center p-4 bg-white dark:bg-zinc-900 rounded-2xl transition-all h-24 flex-1 min-w-[140px] border border-zinc-200 dark:border-zinc-800 shadow-sm hover:shadow-2xl hover:shadow-indigo-500/10 hover:-translate-y-1 active:scale-95 overflow-hidden flex",
23    children: [
24      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `absolute top-0 right-0 w-16 h-16 opacity-10 group-hover:opacity-20 transition-opacity bg-gradient-to-br ${gradient} rounded-full -mr-6 -mt-6 blur-xl group-hover:scale-150 duration-700` }),
25      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `p-2.5 rounded-xl mb-2 bg-zinc-50 dark:bg-zinc-800 shadow-inner group-hover:scale-110 group-hover:rotate-3 transition-all duration-300`, children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { size: 20, className: `${color}` }) }),
26      /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-black text-[10px] uppercase tracking-wider text-zinc-500 group-hover:text-zinc-900 dark:group-hover:text-white transition-colors text-center line-clamp-1", children: label })
27    ]
28  }
29);
30const TAG_GRADIENTS = [
31  "from-pink-400 to-rose-600",
32  "from-purple-400 to-indigo-600",
33  "from-blue-400 to-indigo-700",
34  "from-emerald-400 to-teal-600",
35  "from-amber-400 to-amber-700",
36  "from-red-400 to-orange-600",
37  "from-indigo-400 to-purple-600",
38  "from-teal-400 to-cyan-600",
39  "from-fuchsia-400 to-purple-600",
40  "from-violet-400 to-indigo-600"
41];
42const TAG_COLORS = [
43  "text-pink-500",
44  "text-purple-500",
45  "text-blue-500",
46  "text-emerald-500",
47  "text-amber-500",
48  "text-red-500",
49  "text-indigo-500",
50  "text-teal-500",
51  "text-fuchsia-500",
52  "text-violet-500"
53];
54const LazyTrackRow = ({
55  cat,
56  currentLang,
57  onSelectTrack,
58  onToggleWatchLater,
59  watchLaterSet,
60  onAddToQueue,
61  onAddToPlaylist,
62  onCategorySelect,
63  t
64}) => {
65  var _a;
66  const [tracks, setTracks] = reactExports.useState([]);
67  const [loading, setLoading] = reactExports.useState(false);
68  const [hasLoaded, setHasLoaded] = reactExports.useState(false);
69  const containerRef = reactExports.useRef(null);
70  reactExports.useEffect(() => {
71    const observer = new IntersectionObserver(
72      (entries) => {
73        if (entries[0].isIntersecting && !hasLoaded && !loading) {
74          setLoading(true);
75          const sort = cat.key === "trending" ? "popular" : "recent";
76          api.getTracks("", cat.key, sort, 20).then((data) => {
77            setTracks(data);
78            setHasLoaded(true);
79          }).catch((e) => {
80            console.error(`Failed to fetch ${cat.key}`, e);
81          }).finally(() => {
82            setLoading(false);
83          });
84        }
85      },
86      { rootMargin: "200px 0px" }
87    );
88    if (containerRef.current) {
89      observer.observe(containerRef.current);
90    }
91    return () => {
92      observer.disconnect();
93    };
94  }, [cat.key, hasLoaded, loading]);
95  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { ref: containerRef, className: "min-h-[100px]", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
96    TrackRow,
97    {
98      title: ((_a = cat.translations) == null ? void 0 : _a[currentLang]) || t(`categories.${cat.key}`, cat.label),
99      tracks,
100      loading,
101      onSelectTrack,
102      onToggleWatchLater,
103      watchLaterSet,
104      onAddToQueue,
105      onAddToPlaylist,
106      onSeeAll: () => onCategorySelect(cat.key),
107      seeAllHref: `/${cat.key}`
108    }
109  ) });
110};
111const ExplorePage = ({ tracks, onSelectTrack, onToggleWatchLater, watchLaterSet, onCategorySelect, onAddToQueue, onAddToPlaylist, onTagSelect }) => {
112  const { t, i18n } = useTranslation();
113  const [categories, setCategories] = reactExports.useState([]);
114  const [randomTags, setRandomTags] = reactExports.useState([]);
115  reactExports.useEffect(() => {
116    const init = async () => {
117      try {
118        const cats = await api.getCategories(0, 100);
119        const filtered = cats.filter((c) => c.key !== "all");
120        if (!filtered.find((c) => c.key === "trending")) {
121          filtered.unshift({ key: "trending", label: "Trending" });
122        }
123        setCategories(filtered);
124        try {
125          const allTags = await api.getTags();
126          const top50 = allTags.slice(0, 50);
127          const shuffled = [...top50].sort(() => 0.5 - Math.random());
128          const selectedTags = shuffled.slice(0, 10);
129          setRandomTags(selectedTags);
130        } catch (tagErr) {
131          console.error("Failed to load tags for ExplorePage", tagErr);
132        }
133      } catch (e) {
134        console.error("Failed to load categories", e);
135      }
136    };
137    init();
138  }, []);
139  const currentLang = i18n.language;
140  const topRowItems = reactExports.useMemo(() => {
141    var _a;
142    const items = [];
143    items.push({
144      key: "collections",
145      label: t("categories.collections", "Collections"),
146      icon: Library,
147      color: "text-indigo-500",
148      gradient: "from-indigo-500 to-purple-600",
149      href: "/collections"
150    });
151    const trendingCat = categories.find((c) => c.key === "trending");
152    items.push({
153      key: "trending",
154      label: ((_a = trendingCat == null ? void 0 : trendingCat.translations) == null ? void 0 : _a[currentLang]) || t("categories.trending", (trendingCat == null ? void 0 : trendingCat.label) || "Trending"),
155      icon: Flame,
156      color: "text-orange-500",
157      gradient: "from-orange-500 to-red-600",
158      href: "/trending"
159    });
160    randomTags.forEach((tag, idx) => {
161      var _a2;
162      const gradient = TAG_GRADIENTS[idx % TAG_GRADIENTS.length];
163      const color = TAG_COLORS[idx % TAG_COLORS.length];
164      items.push({
165        key: `tag-${tag.id}`,
166        label: ((_a2 = tag.translations) == null ? void 0 : _a2[currentLang]) || tag.name,
167        icon: Tag,
168        color,
169        gradient,
170        href: `/tag?name=${encodeURIComponent(tag.name)}`
171      });
172    });
173    return items;
174  }, [categories, randomTags, currentLang, t]);
175  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6 md:p-10 max-w-[2000px] mx-auto animate-in fade-in duration-700 bg-zinc-50 dark:bg-[#0a0a0a] min-h-full", children: [
176    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col md:flex-row md:items-end justify-between gap-6 mb-12", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
177      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-indigo-500 font-black text-xs uppercase tracking-tighter mb-2", children: [
178        /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { size: 14 }),
179        "Discover New Sound"
180      ] }),
181      /* @__PURE__ */ jsxRuntimeExports.jsx("h1", { className: "text-4xl md:text-5xl font-black tracking-tight text-zinc-900 dark:text-white flex items-center gap-4", children: t("nav.explore", "Explore") })
182    ] }) }),
183    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex gap-4 overflow-x-auto pb-4 scrollbar-hide -mx-4 px-4 sm:mx-0 sm:px-0 sm:grid sm:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 2xl:grid-cols-11 mb-10", children: topRowItems.map((item, i) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "shrink-0 w-40 sm:w-auto animate-in fade-in slide-in-from-bottom-4", style: { animationDelay: `${i * 50}ms` }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
184      CategoryCard,
185      {
186        icon: item.icon,
187        label: item.label,
188        color: item.color,
189        gradient: item.gradient,
190        href: item.href
191      }
192    ) }, item.key)) }),
193    /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mb-12 relative overflow-hidden rounded-3xl bg-gradient-to-r from-indigo-950 via-purple-950 to-zinc-950 border border-indigo-500/20 shadow-xl p-8 flex flex-col md:flex-row md:items-center justify-between gap-6 animate-in fade-in slide-in-from-bottom-6", children: [
194      /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative z-10", children: [
195        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-indigo-400 font-bold text-xs uppercase tracking-wider mb-2", children: [
196          /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { size: 14, className: "animate-pulse text-indigo-400" }),
197          "Curated Showcases"
198        ] }),
199        /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-2xl md:text-3xl font-black text-white mb-2 tracking-tight", children: "Themed MIDI Collections" }),
200        /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-zinc-400 text-sm max-w-xl leading-relaxed", children: "Explore dedicated showcases curated for music lovers. Dive into Broadway musicals, movie soundtracks, and classical masterpieces." })
201      ] }),
202      /* @__PURE__ */ jsxRuntimeExports.jsx(
203        "a",
204        {
205          href: "/collections",
206          className: "relative z-10 shrink-0 self-start md:self-auto px-6 py-3 bg-indigo-600 hover:bg-indigo-500 text-white font-bold text-sm rounded-xl transition-all shadow-lg hover:shadow-xl active:scale-95 border border-indigo-400/20",
207          children: "Browse Collections"
208        }
209      ),
210      /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-0 right-0 w-96 h-96 opacity-20 bg-gradient-to-br from-indigo-500 to-purple-600 rounded-full -mr-20 -mt-20 blur-3xl pointer-events-none" })
211    ] }),
212    /* @__PURE__ */ jsxRuntimeExports.jsx(AdSlot, { type: "exploreList" }),
213    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "space-y-4", children: categories.map((cat, i) => /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "animate-in fade-in slide-in-from-bottom-8", style: { animationDelay: `${i * 100}ms` }, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
214      LazyTrackRow,
215      {
216        cat,
217        currentLang,
218        onSelectTrack,
219        onToggleWatchLater,
220        watchLaterSet,
221        onAddToQueue,
222        onAddToPlaylist,
223        onCategorySelect,
224        t
225      }
226    ) }, `row-${cat.key}`)) }),
227    /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-20 py-10 border-t border-zinc-200 dark:border-zinc-800 text-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-zinc-500 text-sm font-medium", children: t("explore.moreComing", "More genres and curated collections are added daily.") }) })
228  ] });
229};
230export {
231  ExplorePage as default
232};

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.