PageSourceSearch

https://www.hamienet.com/assets/SectionPreviewModal-X73NeEWd.js

js hamienet.com collected 2026-10-02 05:02:48 UTC 10,062 bytes, 200 lines download raw bytes

1import { r as reactExports, j as jsxRuntimeExports } from "./vendor-react-Bay9Y7Lb.js";
2import { n as getOptimizedImageUrl } from "./utils-CEVb7nN1.js";
3import { g as getBilingualTitle } from "./bilingual-CBk-npe4.js";
4import { a as useAdmin } from "./main-aQ5jZgYp.js";
5import { u as useTranslation } from "./vendor-i18n-BC7ZMXWQ.js";
6import { ck as Layers, c_ as ChevronLeft, bF as ChevronRight } from "./vendor-D0P4XgNj.js";
7import { S as SectionContent } from "./SectionContent-dHWQOZ9q.js";
8const NetflixSectionCard = ({ section, onClick, trackCount, className, aspectRatio = "4/5" }) => {
9  const [imageError, setImageError] = reactExports.useState(false);
10  const { i18n } = useTranslation();
11  const { staffModeEnabled } = useAdmin();
12  const { mainTitle: rawMainTitle, subTitle, hoverTooltip, altText, nativeBadge, nativeTitle } = getBilingualTitle(section.title, section.subtitle, i18n.language);
13  const mainTitle = rawMainTitle.replace(/^\d+\.\s*/, "");
14  const resolvedTrackCount = trackCount !== void 0 ? trackCount : section.trackCount;
15  const aspectClass = aspectRatio === "16/9" || aspectRatio === "video" ? "aspect-[16/9]" : "aspect-[4/5]";
16  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
17    "div",
18    {
19      onClick: (e) => {
20        e.preventDefault();
21        e.stopPropagation();
22        onClick();
23      },
24      className: `group relative flex flex-col w-full cursor-pointer shrink-0 transition-transform duration-300 hover:scale-105 hover:z-10 ${className || "min-w-[160px] md:min-w-[200px] max-w-[240px]"}`,
25      children: [
26        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `relative w-full ${aspectClass} rounded-xl overflow-hidden bg-zinc-100 dark:bg-zinc-800 shadow-sm group-hover:shadow-xl transition-shadow duration-300 border border-zinc-200/50 dark:border-zinc-700/50`, children: [
27          section.bannerImage && !imageError ? /* @__PURE__ */ jsxRuntimeExports.jsx(
28            "img",
29            {
30              src: getOptimizedImageUrl(section.bannerImage, "card"),
31              className: "w-full h-full object-cover transition-transform duration-500 group-hover:scale-110",
32              alt: altText || mainTitle,
33              title: hoverTooltip || mainTitle,
34              loading: "lazy",
35              onError: () => setImageError(true)
36            }
37          ) : /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full h-full bg-gradient-to-br from-indigo-500/20 to-purple-500/20 flex flex-col items-center justify-center p-4 text-center", children: [
38            /* @__PURE__ */ jsxRuntimeExports.jsx(Layers, { className: "text-indigo-500/50 mb-2", size: 32 }),
39            /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-bold text-indigo-700/50 dark:text-indigo-300/50 line-clamp-2", children: mainTitle })
40          ] }),
41          nativeBadge && /* @__PURE__ */ jsxRuntimeExports.jsx(
42            "div",
43            {
44              className: "absolute top-2 left-2 bg-black/60 backdrop-blur-md text-white/90 text-[9px] font-black tracking-widest px-1.5 py-0.5 rounded shadow-sm border border-white/10 uppercase select-none",
45              title: `Native Script: ${nativeBadge}`,
46              children: nativeBadge
47            }
48          ),
49          staffModeEnabled && resolvedTrackCount === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-2 right-2 bg-amber-500/90 text-zinc-950 font-black text-[10px] uppercase tracking-wider px-2 py-0.5 rounded-md backdrop-blur-md shadow-md border border-amber-400/40", children: "Unbound (0)" }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-2 right-2 bg-black/60 backdrop-blur-md text-white text-[10px] font-bold px-2 py-1 rounded-md min-w-[40px] text-center", children: resolvedTrackCount !== void 0 ? `${resolvedTrackCount} Tracks` : /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-block w-6 h-2 bg-white/40 animate-pulse rounded" }) })
50        ] }),
51        /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-2 px-1", title: hoverTooltip || mainTitle, children: [
52          /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-bold text-zinc-900 dark:text-zinc-100 truncate group-hover:text-indigo-600 dark:group-hover:text-indigo-400 transition-colors", children: mainTitle }),
53          (subTitle || nativeTitle && nativeTitle !== mainTitle) && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-[11px] font-medium text-zinc-500 dark:text-zinc-400 truncate mt-0.5", title: hoverTooltip || subTitle || void 0, children: subTitle || nativeTitle })
54        ] })
55      ]
56    }
57  );
58};
59function CarouselRow({ children, className = "", hideArrowsOnMobile = true }) {
60  const rowRef = reactExports.useRef(null);
61  const [showLeftArrow, setShowLeftArrow] = reactExports.useState(false);
62  const [showRightArrow, setShowRightArrow] = reactExports.useState(false);
63  const [isDragging, setIsDragging] = reactExports.useState(false);
64  const [startX, setStartX] = reactExports.useState(0);
65  const [scrollLeft, setScrollLeft] = reactExports.useState(0);
66  const handleScroll = () => {
67    if (rowRef.current) {
68      const { scrollLeft: scrollLeft2, scrollWidth, clientWidth } = rowRef.current;
69      setShowLeftArrow(scrollLeft2 > 0);
70      setShowRightArrow(Math.ceil(scrollLeft2 + clientWidth) < scrollWidth);
71    }
72  };
73  reactExports.useEffect(() => {
74    handleScroll();
75    window.addEventListener("resize", handleScroll);
76    return () => window.removeEventListener("resize", handleScroll);
77  }, [children]);
78  reactExports.useEffect(() => {
79    const timer = setTimeout(handleScroll, 100);
80    return () => clearTimeout(timer);
81  }, []);
82  const slide = (direction) => {
83    if (rowRef.current) {
84      const { clientWidth } = rowRef.current;
85      const scrollAmount = direction === "left" ? -(clientWidth * 0.8) : clientWidth * 0.8;
86      rowRef.current.scrollBy({ left: scrollAmount, behavior: "smooth" });
87    }
88  };
89  const handleMouseDown = (e) => {
90    var _a, _b;
91    setIsDragging(true);
92    setStartX(e.pageX - (((_a = rowRef.current) == null ? void 0 : _a.offsetLeft) || 0));
93    setScrollLeft(((_b = rowRef.current) == null ? void 0 : _b.scrollLeft) || 0);
94  };
95  const handleMouseLeave = () => {
96    setIsDragging(false);
97  };
98  const handleMouseUp = () => {
99    setIsDragging(false);
100  };
101  const handleMouseMove = (e) => {
102    if (!isDragging || !rowRef.current) return;
103    e.preventDefault();
104    const x = e.pageX - (rowRef.current.offsetLeft || 0);
105    const walk = (x - startX) * 2;
106    rowRef.current.scrollLeft = scrollLeft - walk;
107  };
108  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: `relative group ${className}`, children: [
109    showLeftArrow && /* @__PURE__ */ jsxRuntimeExports.jsx(
110      "button",
111      {
112        onClick: () => slide("left"),
113        className: `absolute left-0 top-0 bottom-0 z-20 w-12 bg-black/40 hover:bg-black/60 text-white flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity rounded-l-xl ${hideArrowsOnMobile ? "hidden md:flex" : "flex"}`,
114        children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronLeft, { size: 32 })
115      }
116    ),
117    /* @__PURE__ */ jsxRuntimeExports.jsx(
118      "div",
119      {
120        ref: rowRef,
121        onScroll: handleScroll,
122        onMouseDown: handleMouseDown,
123        onMouseLeave: handleMouseLeave,
124        onMouseUp: handleMouseUp,
125        onMouseMove: handleMouseMove,
126        className: `flex items-start gap-4 overflow-x-auto scrollbar-hide pt-1 pb-1.5 ${isDragging ? "cursor-grabbing select-none" : "cursor-grab"} snap-x snap-mandatory md:snap-none`,
127        style: { scrollBehavior: isDragging ? "auto" : "smooth" },
128        children
129      }
130    ),
131    showRightArrow && /* @__P
131URE__ */ jsxRuntimeExports.jsx(
132      "button",
133      {
134        onClick: () => slide("right"),
135        className: `absolute right-0 top-0 bottom-0 z-20 w-12 bg-black/40 hover:bg-black/60 text-white flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity rounded-r-xl ${hideArrowsOnMobile ? "hidden md:flex" : "flex"}`,
136        children: /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronRight, { size: 32 })
137      }
138    )
139  ] });
140}
141const SectionPreviewModal = ({
142  section,
143  activeSlug,
144  onClose,
145  currentUser,
146  onUploadRequested
147}) => {
148  const modalRef = reactExports.useRef(null);
149  reactExports.useEffect(() => {
150    const handleKeyDown = (e) => {
151      if (e.key === "Escape") onClose();
152    };
153    if (section) {
154      window.addEventListener("keydown", handleKeyDown);
155    }
156    return () => window.removeEventListener("keydown", handleKeyDown);
157  }, [section, onClose]);
158  reactExports.useEffect(() => {
159    if (section) {
160      document.body.style.overflow = "hidden";
161    } else {
162      document.body.style.overflow = "auto";
163    }
164    return () => {
165      document.body.style.overflow = "auto";
166    };
167  }, [section]);
168  if (!section) return null;
169  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6 animate-in fade-in duration-200", children: [
170    /* @__PURE__ */ jsxRuntimeExports.jsx(
171      "div",
172      {
173        className: "absolute inset-0 bg-black/60 backdrop-blur-sm",
174        onClick: onClose
175      }
176    ),
177    /* @__PURE__ */ jsxRuntimeExports.jsx(
178      "div",
179      {
180        ref: modalRef,
181        className: "relative w-full max-w-2xl max-h-[90vh] bg-white dark:bg-[#0f0f0f] rounded-2xl shadow-2xl overflow-hidden flex flex-col animate-in zoom-in-95 duration-200",
182        children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "overflow-y-auto custom-scrollbar flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
183          SectionContent,
184          {
185            section,
186            activeSlug,
187            onClose,
188            currentUser,
189            onUploadRequested
190          }
191        ) })
192      }
193    )
194  ] });
195};
196export {
197  CarouselRow as C,
198  NetflixSectionCard as N,
199  SectionPreviewModal as S
200};

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.