@summa-ui/surah-picker 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/core/SurahWheelPicker.tsx","../src/data/quran.ts","../src/labels.ts","../src/core/SurahRangePicker.tsx","../src/core/SurahFieldPicker.tsx","../src/ui/Popup.tsx","../src/icons/icons.tsx"],"sourcesContent":["export {\n SurahWheelPicker,\n type SurahWheelValue,\n type SurahWheelPhysics,\n} from \"./core/SurahWheelPicker\";\nexport {\n SurahRangePicker,\n type SurahRangeValue,\n} from \"./core/SurahRangePicker\";\nexport { SurahFieldPicker } from \"./core/SurahFieldPicker\";\nexport { Popup, type PopupPlacement } from \"./ui/Popup\";\nexport { BookIcon, ChevronDownIcon } from \"./icons/icons\";\nexport {\n defaultLabels,\n resolveLabels,\n type SurahPickerLabels,\n} from \"./labels\";\nexport { SURAH_LIST, getSurah, getAyatCount, type Surah } from \"./data/quran\";\n","import { useEffect, useRef, useState, useCallback } from \"react\";\nimport { SURAH_LIST, getAyatCount } from \"../data/quran\";\nimport { resolveLabels, type SurahPickerLabels } from \"../labels\";\n\nexport interface SurahWheelValue {\n surah: number;\n ayat: number;\n}\n\nexport interface SurahWheelPhysics {\n friction?: number; // peluruhan eksponensial per detik (default 5)\n maxVelocity?: number; // notch per detik (default 80)\n snapMs?: number; // durasi snap ke notch (default 120)\n}\n\ninterface Props {\n value?: SurahWheelValue;\n onChange: (v: SurahWheelValue) => void;\n nameSurah?: string;\n nameAyat?: string;\n physics?: SurahWheelPhysics;\n loop?: boolean; // true = putaran tak berujung (114 -> 1, 1 -> 114)\n chrome?: boolean; // false = roda saja tanpa header badge & hidden input (untuk embed)\n ariaSurahLabel?: string; // default labels.surah\n ariaAyatLabel?: string; // default labels.ayah\n labels?: Partial<SurahPickerLabels>;\n}\n\nfunction pad2(n: number) {\n return String(n).padStart(2, \"0\");\n}\nfunction vibrate() {\n try {\n if (navigator.vibrate) navigator.vibrate(10);\n } catch {}\n}\n\n// chanhdai config with visibleCount 8 for 3 focused\nconst visibleCount = 8;\nconst itemHeight = 36;\nconst halfItemHeight = itemHeight * 0.5;\nconst itemAngle = 360 / visibleCount;\nconst radius = itemHeight / Math.tan((itemAngle * Math.PI) / 180);\nconst containerHeight = Math.round(radius * 2 + itemHeight * 0.25);\nconst quarterCount = visibleCount >> 2;\nconst RESISTANCE = 0.3;\nconst STOP_VELOCITY = 0.5; // notch/detik — di bawah ini dianggap berhenti\nconst WHEEL_SETTLE_MS = 90; // jeda snap setelah tick wheel terakhir\nconst MIN_FLICK_VELOCITY = 2; // lepas di bawah ini = snap langsung, tanpa fling\nconst VIB_THROTTLE_MS = 30; // getar maksimal ~33x/detik saat fling kencang\nconst WHEEL_NOTCH_PX = 100; // 1 detent mouse generik = 100px = TEPAT 1 data\nconst WHEEL_LINE_PX = 40; // mode baris (Firefox): 1 baris ~= 40px\nconst easeOutCubic = (p: number) => Math.pow(p - 1, 3) + 1;\nconst clamp = (v: number, min: number, max: number) => Math.max(min, Math.min(v, max));\n\nexport function SurahWheelPicker({ value, onChange, nameSurah = \"surah_number\", nameAyat = \"ayat\", physics, loop = false, chrome = true, ariaSurahLabel, ariaAyatLabel, labels: labelsProp }: Props) {\n const labels = resolveLabels(labelsProp);\n const surahLabel = ariaSurahLabel ?? labels.surah;\n const ayatLabel = ariaAyatLabel ?? labels.ayah;\n const friction = physics?.friction ?? 5;\n const maxVelocity = physics?.maxVelocity ?? 120;\n const snapMs = physics?.snapMs ?? 120;\n // loop = bungkus modulo, non-loop = jepit di ujung\n const boundIndex = (norm: number, len: number) =>\n liveRef.current.loop ? ((norm % len) + len) % len : clamp(norm, 0, len - 1);\n const [surah, setSurah] = useState(value?.surah ?? 3);\n const [ayat, setAyat] = useState(value?.ayat ?? 3);\n\n const surahScrollRef = useRef(0);\n const ayatScrollRef = useRef(0);\n\n const surahContainerRef = useRef<HTMLDivElement>(null);\n const ayatContainerRef = useRef<HTMLDivElement>(null);\n const surahWheelRef = useRef<HTMLUListElement>(null);\n const ayatWheelRef = useRef<HTMLUListElement>(null);\n const surahHighlightRef = useRef<HTMLUListElement>(null);\n const ayatHighlightRef = useRef<HTMLUListElement>(null);\n\n const surahMoveId = useRef(0);\n const ayatMoveId = useRef(0);\n const surahDragging = useRef(false);\n const ayatDragging = useRef(false);\n const motionRef = useRef(false); // true selama fling/animasi — efek sinkron skip dulu\n const lastVibRef = useRef(0);\n const wheelTimerSurah = useRef(0);\n const wheelTimerAyat = useRef(0);\n const wheelAccumSurah = useRef(0); // sisa delta wheel (notch) belum jadi step\n const wheelAccumAyat = useRef(0);\n const wheelTargetSurah = useRef<number | null>(null); // target notch wheel-gesture\n const wheelTargetAyat = useRef<number | null>(null);\n\n const activeSurah = SURAH_LIST.find((s) => s.number === surah) ?? SURAH_LIST[2];\n const ayatCount = getAyatCount(surah);\n\n const surahValRef = useRef(surah);\n const ayatValRef = useRef(ayat);\n useEffect(() => { surahValRef.current = surah; }, [surah]);\n useEffect(() => { ayatValRef.current = ayat; }, [ayat]);\n\n const surahOptions = SURAH_LIST;\n const ayatOptions = Array.from({ length: ayatCount }, (_, i) => i + 1);\n\n // Handler native di-attach sekali (closure render pertama) — semua yang\n // bisa berubah (loop/physics/ayatLen/onChange) dibaca via ref agar toggle\n // loop & knob fisika berlaku untuk drag/wheel/fling, bukan cuma keyboard.\n const liveRef = useRef({ loop, friction, maxVelocity, snapMs, ayatLen: ayatOptions.length });\n liveRef.current = { loop, friction, maxVelocity, snapMs, ayatLen: ayatOptions.length };\n const onChangeRef = useRef(onChange);\n onChangeRef.current = onChange;\n const ayatLenOf = (isSurah: boolean) => (isSurah ? surahOptions.length : liveRef.current.ayatLen);\n\n useEffect(() => {\n // pindah surat: ayat selalu mulai dari 1 (bukan dipertahankan/clamp)\n if (ayat > ayatCount || ayat < 1) {\n setAyat(1);\n ayatValRef.current = 1;\n onChange({ surah, ayat: 1 });\n }\n }, [surah, ayatCount]); // eslint-disable-line\n\n useEffect(() => {\n if (!value) return;\n // gema commit sendiri (fling/drag/wheel) — jangan bunuh motion yang jalan\n if (value.surah === surahValRef.current && value.ayat === ayatValRef.current) return;\n cancelAll(); // intent eksternal (knob lab, reset form) menang atas motion\n surahValRef.current = value.surah;\n ayatValRef.current = value.ayat;\n setSurah(value.surah);\n setAyat(value.ayat);\n }, [value?.surah, value?.ayat]);\n\n // Silinder VIRTUAL: tiap item diposisikan dari offset terpendek (wrap)\n // terhadap posisi scroll, bukan silinder kaku yang diputar.\n // Silinder kaku rusak di infinite loop karena 114 % 8 = 2: tiap putaran\n // penuh menggeser fase visual, sehingga twin (i dan i+8, sudut 3D sama)\n // dari kedua ujung tampil berimpit di seam (0&112, 1&113) + lompat rotasi.\n // Di sini tiap index visible punya offset unik -> sudut unik. Seamless.\n const scrollTo = useCallback((isSurah: boolean, scroll: number) => {\n const wheelRef = isSurah ? surahWheelRef : ayatWheelRef;\n const highlightRef = isSurah ? surahHighlightRef : ayatHighlightRef;\n const len = ayatLenOf(isSurah);\n if (wheelRef.current) {\n wheelRef.current.childNodes.forEach((node) => {\n const li = node as HTMLLIElement;\n const idx = Number(li.dataset.index);\n let d = (idx - scroll) % len;\n d = ((d % len) + len) % len;\n if (d > len / 2) d -= len; // offset bertanda terpendek\n const cache = li as HTMLLIElement & { _w?: string };\n if (Math.abs(d) > quarterCount) {\n if (cache._w !== \"h\") {\n cache._w = \"h\";\n li.style.visibility = \"hidden\";\n }\n } else {\n const t = `rotateX(${-itemAngle * d}deg) translateZ(${radius}px)`;\n if (cache._w !== t) {\n cache._w = t;\n li.style.visibility = \"visible\";\n li.style.transform = t;\n }\n }\n });\n }\n if (highlightRef.current) {\n highlightRef.current.style.transform = `translateY(${-scroll * itemHeight}px)`;\n }\n return scroll; // tak-batas untuk fisika; normalisasi hanya saat select\n }, [surahOptions.length, ayatOptions.length]);\n\n const cancelSurah = () => cancelAnimationFrame(surahMoveId.current);\n const cancelAyat = () => cancelAnimationFrame(ayatMoveId.current);\n const cancelAll = () => {\n cancelSurah();\n cancelAyat();\n motionRef.current = false;\n };\n\n const animateScroll = (\n isSurah: boolean,\n start: number,\n end: number,\n duration: number,\n onComplete?: () => void,\n ) => {\n if (start === end || duration === 0) {\n scrollTo(isSurah, start);\n return;\n }\n motionRef.current = true;\n const startTime = performance.now();\n const dist = end - start;\n const ref = isSurah ? surahScrollRef : ayatScrollRef;\n const moveRef = isSurah ? surahMoveId : ayatMoveId;\n const tick = (now: number) => {\n // Pakai performance.now() sendiri: timestamp bawaan rAF tidak selalu\n // se-epoch (mis. di jsdom), yang membuat dt negatif raksasa.\n const t = performance.now();\n const elapsed = (t - startTime) / 1000;\n if (elapsed < duration) {\n const p = easeOutCubic(elapsed / duration);\n ref.current = scrollTo(isSurah, start + p * dist);\n moveRef.current = requestAnimationFrame(tick);\n } else {\n motionRef.current = false;\n if (isSurah) cancelSurah(); else cancelAyat();\n ref.current = scrollTo(isSurah, end);\n onComplete?.();\n }\n };\n requestAnimationFrame(tick);\n };\n\n const selectByScroll = (isSurah: boolean, scroll: number) => {\n const len = ayatLenOf(isSurah);\n const norm = Math.round(scroll);\n const bounded = boundIndex(norm, len);\n if (isSurah) {\n surahScrollRef.current = scrollTo(true, bounded);\n const sel = surahOptions[surahScrollRef.current];\n if (sel) {\n const n = sel.number;\n if (n !== surahValRef.current) {\n vibrate();\n surahValRef.current = n;\n ayatValRef.current = 1; // pindah surat: ayat mulai dari 1\n setSurah(n);\n setAyat(1);\n onChangeRef.current({ surah: n, ayat: 1 });\n }\n }\n } else {\n ayatScrollRef.current = scrollTo(false, bounded);\n const n = bounded + 1;\n if (n !== ayatValRef.current) {\n vibrate();\n ayatValRef.current = n;\n setAyat(n);\n onChangeRef.current({ surah: surahValRef.current, ayat: n });\n }\n }\n };\n\n const throttledVibrate = () => {\n const now = performance.now();\n if (now - lastVibRef.current > VIB_THROTTLE_MS) {\n lastVibRef.current = now;\n vibrate();\n }\n };\n\n // Velocity dari regresi least-squares atas sampel 120ms terakhir.\n // Jauh lebih stabil dari selisih 2 sampel (1 frame berisik tidak menentukan).\n const calcVelocity = (yList: [number, number][]) => {\n if (yList.length < 2) return 0;\n const clampV = (v: number) => clamp(v, -liveRef.current.maxVelocity, liveRef.current.maxVelocity);\n const last = yList[yList.length - 1];\n const pts = yList.filter(([_, t]) => last[1] - t <= 120);\n if (pts.length < 2) {\n const [sy, st] = yList[yList.length - 2];\n const [ey, et] = last;\n const dt = (et - st) / 1000;\n if (dt <= 0) return 0;\n return clampV(((sy - ey) / itemHeight) / dt);\n }\n const n = pts.length;\n const t0 = pts[0][1] / 1000;\n let sx = 0, sy2 = 0, sxx = 0, sxy = 0;\n for (const [y, t] of pts) {\n const x = t / 1000 - t0;\n sx += x; sy2 += y; sxx += x * x; sxy += x * y;\n }\n const denom = n * sxx - sx * sx;\n if (denom === 0) return 0;\n const slope = (n * sxy - sx * sy2) / denom; // px/detik (negatif saat seret ke atas)\n return clampV(-slope / itemHeight); // notch/detik (positif = maju)\n };\n\n // Commit 1 notch tanpa menggerakkan transform (posisi sudah ditulis pemanggil).\n // Pakai write-through ref agar closure fling tidak basi.\n const commitNotch = (isSurah: boolean, notch: number) => {\n const len = ayatLenOf(isSurah);\n const bounded = boundIndex(notch, len);\n if (isSurah) {\n const sel = surahOptions[bounded];\n if (sel && sel.number !== surahValRef.current) {\n surahValRef.current = sel.number;\n ayatValRef.current = 1; // pindah surat: ayat mulai dari 1\n setSurah(sel.number);\n setAyat(1);\n onChangeRef.current({ surah: sel.number, ayat: 1 });\n }\n } else {\n const n = bounded + 1;\n if (n !== ayatValRef.current) {\n ayatValRef.current = n;\n setAyat(n);\n onChangeRef.current({ surah: surahValRef.current, ayat: n });\n }\n }\n };\n\n // Loop momentum roulette: gesekan eksponensial, tick per notch, snap di akhir.\n const fling = (isSurah: boolean, velocity: number) => {\n const scrollRef = isSurah ? surahScrollRef : ayatScrollRef;\n const moveRef = isSurah ? surahMoveId : ayatMoveId;\n const len = ayatLenOf(isSurah);\n const { friction, snapMs, loop } = liveRef.current;\n let v = velocity;\n let last = performance.now();\n let lastNotch = Math.round(scrollRef.current);\n motionRef.current = true;\n const step = (_rafNow: number) => {\n // Lihat catatan di animateScroll: jangan percaya timestamp rAF.\n const now = performance.now();\n const dt = clamp((now - last) / 1000, 0, 0.05);\n last = now;\n v *= Math.exp(-friction * dt);\n if (Math.abs(v) < STOP_VELOCITY) {\n const target = loop ? Math.round(scrollRef.current) : clamp(Math.round(scrollRef.current), 0, len - 1);\n animateScroll(isSurah, scrollRef.current, target, snapMs / 1000, () => selectByScroll(isSurah, target));\n return;\n }\n let next = scrollRef.current + v * dt;\n if (!loop && (next < 0 || next > len - 1)) {\n next = clamp(next, 0, len - 1); // mentok tepi: berhenti, snap frame berikut\n v = 0;\n }\n scrollRef.current = scrollTo(isSurah, next);\n const notch = Math.round(scrollRef.current);\n if (notch !== lastNotch) {\n lastNotch = notch;\n throttledVibrate();\n commitNotch(isSurah, notch);\n }\n moveRef.current = requestAnimationFrame(step);\n };\n moveRef.current = requestAnimationFrame(step);\n };\n\n const scrollByStep = (isSurah: boolean, step: number) => {\n const ref = isSurah ? surahScrollRef : ayatScrollRef;\n const start = ref.current;\n const len = ayatLenOf(isSurah);\n let end = Math.round(start + step);\n if (!liveRef.current.loop) end = clamp(end, 0, len - 1);\n const dist = Math.abs(end - start);\n if (dist === 0) return;\n const duration = Math.sqrt(dist / 5);\n cancelAll();\n animateScroll(isSurah, start, end, duration, () => selectByScroll(isSurah, ref.current));\n };\n\n // initial sync\n useEffect(() => {\n const si = surahOptions.findIndex((s) => s.number === surah);\n const ai = ayat - 1;\n surahScrollRef.current = scrollTo(true, si);\n ayatScrollRef.current = scrollTo(false, ai);\n }, []); // once\n\n useEffect(() => {\n // jangan rebut transform dari fling/animasi, atau dari jari yang menempel\n if (motionRef.current || surahDragging.current) return;\n const si = surahOptions.findIndex((s) => s.number === surah);\n if (si !== -1) {\n surahScrollRef.current = scrollTo(true, si);\n }\n }, [surah, scrollTo, surahOptions]);\n\n useEffect(() => {\n // jangan rebut transform dari fling/animasi, atau dari jari yang menempel\n if (motionRef.current || ayatDragging.current) return;\n ayatScrollRef.current = scrollTo(false, ayat - 1);\n }, [ayat, ayatCount, scrollTo]);\n\n // touch/drag: follow 1:1 + tick getar, lepas = fling roulette (chanhdai style)\n const makeDrag = (isSurah: boolean) => {\n const containerRef = isSurah ? surahContainerRef : ayatContainerRef;\n const draggingRef = isSurah ? surahDragging : ayatDragging;\n const scrollRef = isSurah ? surahScrollRef : ayatScrollRef;\n const wheelTimerRef = isSurah ? wheelTimerSurah : wheelTimerAyat;\n const yList: [number, number][] = [];\n let startY = 0;\n let touchScroll = 0;\n let isClick = true;\n let lastTick = 0;\n\n const onDown = (e: MouseEvent | TouchEvent) => {\n draggingRef.current = true;\n const y = (e instanceof MouseEvent ? e.clientY : e.touches?.[0]?.clientY) || 0;\n startY = y;\n yList.length = 0;\n yList.push([y, Date.now()]);\n touchScroll = scrollRef.current;\n lastTick = Math.round(touchScroll);\n isClick = true;\n window.clearTimeout(wheelTimerRef.current);\n cancelAll();\n };\n const onMove = (e: MouseEvent | TouchEvent) => {\n if (!draggingRef.current) return;\n if (e.cancelable) e.preventDefault();\n const y = (e instanceof MouseEvent ? e.clientY : e.touches?.[0]?.clientY) || 0;\n if (isClick && Math.abs(y - startY) > 5) isClick = false;\n yList.push([y, Date.now()]);\n if (yList.length > 5) yList.shift();\n const delta = (startY - y) / itemHeight;\n let next = touchScroll + delta;\n const len = ayatLenOf(isSurah);\n if (!liveRef.current.loop) {\n if (next < 0) next *= RESISTANCE;\n else if (next > len - 1) next = len - 1 + (next - (len - 1)) * RESISTANCE;\n }\n scrollRef.current = scrollTo(isSurah, next);\n // select live tiap notch (efek sinkron dijaga draggingRef, tak berebut);\n const notch = Math.round(scrollRef.current);\n if (notch !== lastTick) {\n lastTick = notch;\n throttledVibrate();\n commitNotch(isSurah, notch);\n }\n };\n\n const onUp = (e: MouseEvent | TouchEvent) => {\n if (!draggingRef.current) return;\n draggingRef.current = false;\n // click handling - advance one notch toward click position\n if (isClick) {\n const y = (e instanceof MouseEvent ? e.clientY : (e as TouchEvent).changedTouches?.[0]?.clientY) || 0;\n const container = containerRef.current;\n if (container) {\n const top = container.getBoundingClientRect().top;\n const clickY = y - top;\n const quarter = visibleCount >> 2;\n // find segment\n let pos = 0;\n const degToRad = Math.PI / 180;\n for (let i = quarter - 1; i >= -quarter + 1; --i) {\n const segLen = itemHeight * Math.cos(i * itemAngle * degToRad);\n const start = pos;\n pos += segLen;\n if (clickY >= start && clickY <= pos) {\n const steps = (quarter - i - 1) * -1;\n if (steps !== 0) scrollByStep(isSurah, steps);\n return;\n }\n }\n }\n return;\n }\n cancelAll();\n const live = liveRef.current;\n const len = ayatLenOf(isSurah);\n if (!live.loop && (scrollRef.current < 0 || scrollRef.current > len - 1)) {\n // lepas di luar batas: tarik kembali (non-loop saja)\n const t = clamp(scrollRef.current, 0, len - 1);\n animateScroll(isSurah, scrollRef.current, t, live.snapMs / 1000, () => selectByScroll(isSurah, t));\n return;\n }\n const velocity = calcVelocity(yList);\n if (Math.abs(velocity) < MIN_FLICK_VELOCITY) {\n // lepas pelan: snap ke notch terdekat (loop: tanpa clamp agar tak lompat)\n const t = live.loop ? Math.round(scrollRef.current) : clamp(Math.round(scrollRef.current), 0, len - 1);\n animateScroll(isSurah, scrollRef.current, t, live.snapMs / 1000, () => selectByScroll(isSurah, t));\n return;\n }\n fling(isSurah, velocity);\n };\n\n return { onDown, onMove, onUp };\n };\n\n // we need to keep drag handlers stable, attach via effect\n const surahDrag = useRef<ReturnType<typeof makeDrag> | null>(null);\n const ayatDrag = useRef<ReturnType<typeof makeDrag> | null>(null);\n\n useEffect(() => {\n const sDrag = makeDrag(true);\n const aDrag = makeDrag(false);\n surahDrag.current = sDrag as any;\n ayatDrag.current = aDrag as any;\n const sEl = surahContainerRef.current;\n const aEl = ayatContainerRef.current;\n if (sEl) {\n sEl.addEventListener(\"touchstart\", sDrag.onDown as any, { passive: false });\n sEl.addEventListener(\"touchmove\", sDrag.onMove as any, { passive: false });\n sEl.addEventListener(\"touchend\", sDrag.onUp as any);\n sEl.addEventListener(\"mousedown\", sDrag.onDown as any);\n document.addEventListener(\"mousemove\", sDrag.onMove as any);\n document.addEventListener(\"mouseup\", sDrag.onUp as any);\n }\n if (aEl) {\n aEl.addEventListener(\"touchstart\", aDrag.onDown as any, { passive: false });\n aEl.addEventListener(\"touchmove\", aDrag.onMove as any, { passive: false });\n aEl.addEventListener(\"touchend\", aDrag.onUp as any);\n aEl.addEventListener(\"mousedown\", aDrag.onDown as any);\n document.addEventListener(\"mousemove\", aDrag.onMove as any);\n document.addEventListener(\"mouseup\", aDrag.onUp as any);\n }\n // wheel: akumulasi delta -> step halus TEPAT 1 data per detent.\n // 1 detent mouse generik = 100px (deltaY mentah 1:1 bikin 1 detent\n // 100px = 2-3 step = loncat). Sisa pecahan disimpan untuk tick berikut.\n // Tiap step commit live + animasi pendek; timer settle memfinalkan.\n const onWheel = (e: WheelEvent, isSurah: boolean) => {\n if (e.cancelable) e.preventDefault();\n cancelAll();\n motionRef.current = true; // tahan efek sinkron selama roda bergulir\n const timerRef = isSurah ? wheelTimerSurah : wheelTimerAyat;\n const accRef = isSurah ? wheelAccumSurah : wheelAccumAyat;\n const targetRef = isSurah ? wheelTargetSurah : wheelTargetAyat;\n window.clearTimeout(timerRef.current);\n const ref = isSurah ? surahScrollRef : ayatScrollRef;\n const live = liveRef.current;\n const len = ayatLenOf(isSurah);\n let target: number = targetRef.current ?? Math.round(ref.current);\n const unit = e.deltaMode === 1 ? WHEEL_LINE_PX : e.deltaMode === 2 ? 400 : 1;\n accRef.current += (e.deltaY * unit) / WHEEL_NOTCH_PX; // akumulasi dalam notch\n let guard = 0;\n while (Math.abs(accRef.current) >= 1 && guard++ < 8) {\n const dir = Math.sign(accRef.current);\n const t = target + dir;\n if (!live.loop && (t < 0 || t > len - 1)) {\n accRef.current = 0; // mentok tepi: buang sisa agar tak menumpuk\n break;\n }\n accRef.current -= dir;\n target = t;\n throttledVibrate();\n commitNotch(isSurah, t);\n }\n targetRef.current = target;\n animateScroll(isSurah, ref.current, target, live.snapMs / 1000, undefined);\n timerRef.current = window.setTimeout(() => {\n targetRef.current = null;\n const t = live.loop ? Math.round(ref.current) : clamp(Math.round(ref.current), 0, len - 1);\n animateScroll(isSurah, ref.current, t, live.snapMs / 1000, () => selectByScroll(isSurah, t));\n }, WHEEL_SETTLE_MS);\n };\n const sWheel = (e: WheelEvent) => onWheel(e, true);\n const aWheel = (e: WheelEvent) => onWheel(e, false);\n sEl?.addEventListener(\"wheel\", sWheel as any, { passive: false });\n aEl?.addEventListener(\"wheel\", aWheel as any, { passive: false });\n return () => {\n window.clearTimeout(wheelTimerSurah.current);\n window.clearTimeout(wheelTimerAyat.current);\n cancelAll();\n sEl?.removeEventListener(\"touchstart\", sDrag.onDown as any);\n sEl?.removeEventListener(\"touchmove\", sDrag.onMove as any);\n sEl?.removeEventListener(\"touchend\", sDrag.onUp as any);\n sEl?.removeEventListener(\"mousedown\", sDrag.onDown as any);\n document.removeEventListener(\"mousemove\", sDrag.onMove as any);\n document.removeEventListener(\"mouseup\", sDrag.onUp as any);\n aEl?.removeEventListener(\"touchstart\", aDrag.onDown as any);\n aEl?.removeEventListener(\"touchmove\", aDrag.onMove as any);\n aEl?.removeEventListener(\"touchend\", aDrag.onUp as any);\n aEl?.removeEventListener(\"mousedown\", aDrag.onDown as any);\n document.removeEventListener(\"mousemove\", aDrag.onMove as any);\n document.removeEventListener(\"mouseup\", aDrag.onUp as any);\n sEl?.removeEventListener(\"wheel\", sWheel as any);\n aEl?.removeEventListener(\"wheel\", aWheel as any);\n };\n }, []);\n\n const onKeySurah = (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowDown\") { e.preventDefault(); scrollByStep(true, 1); }\n if (e.key === \"ArrowUp\") { e.preventDefault(); scrollByStep(true, -1); }\n };\n const onKeyAyat = (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowDown\") { e.preventDefault(); scrollByStep(false, 1); }\n if (e.key === \"ArrowUp\") { e.preventDefault(); scrollByStep(false, -1); }\n };\n\n return (\n <div className={chrome ? \"rounded-[20px] bg-surface border border-border p-4\" : \"\"}>\n {chrome ? (\n <>\n <div className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-3\">\n <div>\n <div className=\"text-[18px] font-bold leading-none tracking-tight text-foreground\">{labels.surah}</div>\n <div className=\"text-xs text-muted mt-1\">{labels.subtitle}</div>\n </div>\n <div className=\"rounded-xl px-4 py-2.5 text-[13px] font-medium min-w-[170px] text-center border-2 border-accent text-foreground w-full sm:w-auto\">\n {pad2(surah)} {activeSurah.name} : {ayat}\n </div>\n </div>\n\n <input type=\"hidden\" name={nameSurah} value={String(surah)} />\n <input type=\"hidden\" name={nameAyat} value={String(ayat)} />\n </>\n ) : null}\n\n <div className=\"relative flex gap-2 rounded-2xl bg-accent/5 border border-border p-2 overflow-hidden\" style={{ perspective: \"2000px\" } as any}>\n {/* surah wheel */}\n <div\n ref={surahContainerRef}\n tabIndex={0}\n role=\"listbox\"\n aria-label={surahLabel}\n onKeyDown={onKeySurah}\n className=\"flex-1 min-w-0 relative overflow-hidden focus:outline-none focus-visible:ring-2 focus-visible:ring-accent rounded-xl\"\n style={{ height: containerHeight, maskImage: \"linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%)\" } as any}\n >\n <ul\n ref={surahWheelRef as any}\n className=\"absolute top-1/2 left-0 w-full h-0 m-0 p-0 list-none\"\n style={{ transformStyle: \"preserve-3d\", willChange: \"transform\", backfaceVisibility: \"hidden\" as any }}\n >\n {SURAH_LIST.map((s, idx) => (\n <li\n key={s.number}\n data-index={idx}\n className=\"absolute top-0 left-0 w-full flex items-center px-3 cursor-pointer select-none text-[13px]\"\n style={{\n top: -halfItemHeight,\n height: itemHeight,\n lineHeight: `${itemHeight}px`,\n visibility: \"hidden\",\n } as any}\n >\n <span className={s.number === surah ? \"text-foreground font-bold\" : \"text-muted\"}>{pad2(s.number)} {s.name}</span>\n </li>\n ))}\n </ul>\n <div className=\"pointer-events-none absolute top-1/2 inset-x-2 -translate-y-1/2 h-9 rounded-xl border-2 border-accent z-10\" />\n </div>\n\n {/* ayat wheel */}\n <div\n ref={ayatContainerRef}\n tabIndex={0}\n role=\"listbox\"\n aria-label={ayatLabel}\n onKeyDown={onKeyAyat}\n className=\"flex-1 min-w-0 sm:flex-none sm:w-[88px] relative overflow-hidden shrink-0 border-l border-border focus:outline-none focus-visible:ring-2 focus-visible:ring-accent rounded-xl\"\n style={{ height: containerHeight, maskImage: \"linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%)\" } as any}\n >\n <ul\n ref={ayatWheelRef as any}\n className=\"absolute top-1/2 left-0 w-full h-0 m-0 p-0 list-none\"\n style={{ transformStyle: \"preserve-3d\", willChange: \"transform\", backfaceVisibility: \"hidden\" as any }}\n >\n {ayatOptions.map((n, idx) => (\n <li\n key={n}\n data-index={idx}\n className=\"absolute top-0 left-0 w-full flex items-center justify-center cursor-pointer select-none text-[13px]\"\n style={{\n top: -halfItemHeight,\n height: itemHeight,\n lineHeight: `${itemHeight}px`,\n visibility: \"hidden\",\n } as any}\n >\n <span className={n === ayat ? \"text-foreground font-bold\" : \"text-muted\"}>{n}</span>\n </li>\n ))}\n </ul>\n <div className=\"pointer-events-none absolute top-1/2 inset-x-2 -translate-y-1/2 h-9 rounded-xl border-2 border-accent z-10\" />\n </div>\n </div>\n\n {/* highlight list for a11y, hidden visually but keeps structure */}\n <div className=\"sr-only\" aria-hidden>\n <ul ref={surahHighlightRef as any} />\n <ul ref={ayatHighlightRef as any} />\n </div>\n </div>\n );\n}\n","export interface Surah {\n number: number;\n name: string;\n arabic: string;\n ayatCount: number;\n}\n\nexport const SURAH_LIST: Surah[] = [\n { number: 1, name: \"Al-Fatihah\", arabic: \"الفاتحة\", ayatCount: 7 },\n { number: 2, name: \"Al-Baqarah\", arabic: \"البقرة\", ayatCount: 286 },\n { number: 3, name: \"Ali Imran\", arabic: \"آل عمران\", ayatCount: 200 },\n { number: 4, name: \"An-Nisa\", arabic: \"النساء\", ayatCount: 176 },\n { number: 5, name: \"Al-Maidah\", arabic: \"المائدة\", ayatCount: 120 },\n { number: 6, name: \"Al-An'am\", arabic: \"الأنعام\", ayatCount: 165 },\n { number: 7, name: \"Al-A'raf\", arabic: \"الأعراف\", ayatCount: 206 },\n { number: 8, name: \"Al-Anfal\", arabic: \"الأنفال\", ayatCount: 75 },\n { number: 9, name: \"At-Taubah\", arabic: \"التوبة\", ayatCount: 129 },\n { number: 10, name: \"Yunus\", arabic: \"يونس\", ayatCount: 109 },\n { number: 11, name: \"Hud\", arabic: \"هود\", ayatCount: 123 },\n { number: 12, name: \"Yusuf\", arabic: \"يوسف\", ayatCount: 111 },\n { number: 13, name: \"Ar-Ra'd\", arabic: \"الرعد\", ayatCount: 43 },\n { number: 14, name: \"Ibrahim\", arabic: \"إبراهيم\", ayatCount: 52 },\n { number: 15, name: \"Al-Hijr\", arabic: \"الحجر\", ayatCount: 99 },\n { number: 16, name: \"An-Nahl\", arabic: \"النحل\", ayatCount: 128 },\n { number: 17, name: \"Al-Isra\", arabic: \"الإسراء\", ayatCount: 111 },\n { number: 18, name: \"Al-Kahf\", arabic: \"الكهف\", ayatCount: 110 },\n { number: 19, name: \"Maryam\", arabic: \"مريم\", ayatCount: 98 },\n { number: 20, name: \"Ta-Ha\", arabic: \"طه\", ayatCount: 135 },\n { number: 21, name: \"Al-Anbiya\", arabic: \"الأنبياء\", ayatCount: 112 },\n { number: 22, name: \"Al-Hajj\", arabic: \"الحج\", ayatCount: 78 },\n { number: 23, name: \"Al-Mu'minun\", arabic: \"المؤمنون\", ayatCount: 118 },\n { number: 24, name: \"An-Nur\", arabic: \"النور\", ayatCount: 64 },\n { number: 25, name: \"Al-Furqan\", arabic: \"الفرقان\", ayatCount: 77 },\n { number: 26, name: \"Ash-Shu'ara\", arabic: \"الشعراء\", ayatCount: 227 },\n { number: 27, name: \"An-Naml\", arabic: \"النمل\", ayatCount: 93 },\n { number: 28, name: \"Al-Qasas\", arabic: \"القصص\", ayatCount: 88 },\n { number: 29, name: \"Al-Ankabut\", arabic: \"العنكبوت\", ayatCount: 69 },\n { number: 30, name: \"Ar-Rum\", arabic: \"الروم\", ayatCount: 60 },\n { number: 31, name: \"Luqman\", arabic: \"لقمان\", ayatCount: 34 },\n { number: 32, name: \"As-Sajdah\", arabic: \"السجدة\", ayatCount: 30 },\n { number: 33, name: \"Al-Ahzab\", arabic: \"الأحزاب\", ayatCount: 73 },\n { number: 34, name: \"Saba\", arabic: \"سبأ\", ayatCount: 54 },\n { number: 35, name: \"Fatir\", arabic: \"فاطر\", ayatCount: 45 },\n { number: 36, name: \"Ya Sin\", arabic: \"يس\", ayatCount: 83 },\n { number: 37, name: \"As-Saffat\", arabic: \"الصافات\", ayatCount: 182 },\n { number: 38, name: \"Sad\", arabic: \"ص\", ayatCount: 88 },\n { number: 39, name: \"Az-Zumar\", arabic: \"الزمر\", ayatCount: 75 },\n { number: 40, name: \"Ghafir\", arabic: \"غافر\", ayatCount: 85 },\n { number: 41, name: \"Fussilat\", arabic: \"فصلت\", ayatCount: 54 },\n { number: 42, name: \"Ash-Shura\", arabic: \"الشورى\", ayatCount: 53 },\n { number: 43, name: \"Az-Zukhruf\", arabic: \"الزخرف\", ayatCount: 89 },\n { number: 44, name: \"Ad-Dukhan\", arabic: \"الدخان\", ayatCount: 59 },\n { number: 45, name: \"Al-Jathiyah\", arabic: \"الجاثية\", ayatCount: 37 },\n { number: 46, name: \"Al-Ahqaf\", arabic: \"الأحقاف\", ayatCount: 35 },\n { number: 47, name: \"Muhammad\", arabic: \"محمد\", ayatCount: 38 },\n { number: 48, name: \"Al-Fath\", arabic: \"الفتح\", ayatCount: 29 },\n { number: 49, name: \"Al-Hujurat\", arabic: \"الحجرات\", ayatCount: 18 },\n { number: 50, name: \"Qaf\", arabic: \"ق\", ayatCount: 45 },\n { number: 51, name: \"Adh-Dhariyat\", arabic: \"الذاريات\", ayatCount: 60 },\n { number: 52, name: \"At-Tur\", arabic: \"الطور\", ayatCount: 49 },\n { number: 53, name: \"An-Najm\", arabic: \"النجم\", ayatCount: 62 },\n { number: 54, name: \"Al-Qamar\", arabic: \"القمر\", ayatCount: 55 },\n { number: 55, name: \"Ar-Rahman\", arabic: \"الرحمن\", ayatCount: 78 },\n { number: 56, name: \"Al-Waqi'ah\", arabic: \"الواقعة\", ayatCount: 96 },\n { number: 57, name: \"Al-Hadid\", arabic: \"الحديد\", ayatCount: 29 },\n { number: 58, name: \"Al-Mujadilah\", arabic: \"المجادلة\", ayatCount: 22 },\n { number: 59, name: \"Al-Hashr\", arabic: \"الحشر\", ayatCount: 24 },\n { number: 60, name: \"Al-Mumtahanah\", arabic: \"الممتحنة\", ayatCount: 13 },\n { number: 61, name: \"As-Saff\", arabic: \"الصف\", ayatCount: 14 },\n { number: 62, name: \"Al-Jumu'ah\", arabic: \"الجمعة\", ayatCount: 11 },\n { number: 63, name: \"Al-Munafiqun\", arabic: \"المنافقون\", ayatCount: 11 },\n { number: 64, name: \"At-Taghabun\", arabic: \"التغابن\", ayatCount: 18 },\n { number: 65, name: \"At-Talaq\", arabic: \"الطلاق\", ayatCount: 12 },\n { number: 66, name: \"At-Tahrim\", arabic: \"التحريم\", ayatCount: 12 },\n { number: 67, name: \"Al-Mulk\", arabic: \"الملك\", ayatCount: 30 },\n { number: 68, name: \"Al-Qalam\", arabic: \"القلم\", ayatCount: 52 },\n { number: 69, name: \"Al-Haqqah\", arabic: \"الحاقة\", ayatCount: 52 },\n { number: 70, name: \"Al-Ma'arij\", arabic: \"المعارج\", ayatCount: 44 },\n { number: 71, name: \"Nuh\", arabic: \"نوح\", ayatCount: 28 },\n { number: 72, name: \"Al-Jinn\", arabic: \"الجن\", ayatCount: 28 },\n { number: 73, name: \"Al-Muzzammil\", arabic: \"المزمل\", ayatCount: 20 },\n { number: 74, name: \"Al-Muddaththir\", arabic: \"المدثر\", ayatCount: 56 },\n { number: 75, name: \"Al-Qiyamah\", arabic: \"القيامة\", ayatCount: 40 },\n { number: 76, name: \"Al-Insan\", arabic: \"الإنسان\", ayatCount: 31 },\n { number: 77, name: \"Al-Mursalat\", arabic: \"المرسلات\", ayatCount: 50 },\n { number: 78, name: \"An-Naba\", arabic: \"النبأ\", ayatCount: 40 },\n { number: 79, name: \"An-Nazi'at\", arabic: \"النازعات\", ayatCount: 46 },\n { number: 80, name: \"Abasa\", arabic: \"عبس\", ayatCount: 42 },\n { number: 81, name: \"At-Takwir\", arabic: \"التكوير\", ayatCount: 29 },\n { number: 82, name: \"Al-Infitar\", arabic: \"الانفطار\", ayatCount: 19 },\n { number: 83, name: \"Al-Mutaffifin\", arabic: \"المطففين\", ayatCount: 36 },\n { number: 84, name: \"Al-Inshiqaq\", arabic: \"الانشقاق\", ayatCount: 25 },\n { number: 85, name: \"Al-Buruj\", arabic: \"البروج\", ayatCount: 22 },\n { number: 86, name: \"At-Tariq\", arabic: \"الطارق\", ayatCount: 17 },\n { number: 87, name: \"Al-A'la\", arabic: \"الأعلى\", ayatCount: 19 },\n { number: 88, name: \"Al-Ghashiyah\", arabic: \"الغاشية\", ayatCount: 26 },\n { number: 89, name: \"Al-Fajr\", arabic: \"الفجر\", ayatCount: 30 },\n { number: 90, name: \"Al-Balad\", arabic: \"البلد\", ayatCount: 20 },\n { number: 91, name: \"Ash-Shams\", arabic: \"الشمس\", ayatCount: 15 },\n { number: 92, name: \"Al-Lail\", arabic: \"الليل\", ayatCount: 21 },\n { number: 93, name: \"Ad-Dhuha\", arabic: \"الضحى\", ayatCount: 11 },\n { number: 94, name: \"Ash-Sharh\", arabic: \"الشرح\", ayatCount: 8 },\n { number: 95, name: \"At-Tin\", arabic: \"التين\", ayatCount: 8 },\n { number: 96, name: \"Al-Alaq\", arabic: \"العلق\", ayatCount: 19 },\n { number: 97, name: \"Al-Qadr\", arabic: \"القدر\", ayatCount: 5 },\n { number: 98, name: \"Al-Bayyinah\", arabic: \"البينة\", ayatCount: 8 },\n { number: 99, name: \"Az-Zalzalah\", arabic: \"الزلزلة\", ayatCount: 8 },\n { number: 100, name: \"Al-Adiyat\", arabic: \"العاديات\", ayatCount: 11 },\n { number: 101, name: \"Al-Qari'ah\", arabic: \"القارعة\", ayatCount: 11 },\n { number: 102, name: \"At-Takathur\", arabic: \"التكاثر\", ayatCount: 8 },\n { number: 103, name: \"Al-Asr\", arabic: \"العصر\", ayatCount: 3 },\n { number: 104, name: \"Al-Humazah\", arabic: \"الهمزة\", ayatCount: 9 },\n { number: 105, name: \"Al-Fil\", arabic: \"الفيل\", ayatCount: 5 },\n { number: 106, name: \"Quraysh\", arabic: \"قريش\", ayatCount: 4 },\n { number: 107, name: \"Al-Ma'un\", arabic: \"الماعون\", ayatCount: 7 },\n { number: 108, name: \"Al-Kawthar\", arabic: \"الكوثر\", ayatCount: 3 },\n { number: 109, name: \"Al-Kafirun\", arabic: \"الكافرون\", ayatCount: 6 },\n { number: 110, name: \"An-Nasr\", arabic: \"النصر\", ayatCount: 3 },\n { number: 111, name: \"Al-Masad\", arabic: \"المسد\", ayatCount: 5 },\n { number: 112, name: \"Al-Ikhlas\", arabic: \"الإخلاص\", ayatCount: 4 },\n { number: 113, name: \"Al-Falaq\", arabic: \"الفلق\", ayatCount: 5 },\n { number: 114, name: \"An-Nas\", arabic: \"الناس\", ayatCount: 6 },\n];\n\nexport function getSurah(number: number): Surah | undefined {\n return SURAH_LIST.find((s) => s.number === number);\n}\n\nexport function getAyatCount(surahNumber: number): number {\n return getSurah(surahNumber)?.ayatCount ?? 0;\n}\n","// Label UI dengan default Inggris. Override sebagian via prop `labels`.\nexport interface SurahPickerLabels {\n surah: string;\n ayah: string;\n subtitle: string;\n from: string;\n to: string;\n fromSurah: string;\n fromAyah: string;\n toSurah: string;\n toAyah: string;\n select: string;\n cancel: string;\n}\n\nexport const defaultLabels: SurahPickerLabels = {\n surah: \"Surah\",\n ayah: \"Ayah\",\n subtitle: \"Select surah and ayah\",\n from: \"From\",\n to: \"To\",\n fromSurah: \"Start surah\",\n fromAyah: \"Start ayah\",\n toSurah: \"End surah\",\n toAyah: \"End ayah\",\n select: \"Select\",\n cancel: \"Cancel\",\n};\n\nexport function resolveLabels(\n partial?: Partial<SurahPickerLabels>\n): SurahPickerLabels {\n return { ...defaultLabels, ...partial };\n}\n","import { useState } from \"react\";\nimport { resolveLabels, type SurahPickerLabels } from \"../labels\";\nimport { SurahWheelPicker, type SurahWheelValue } from \"./SurahWheelPicker\";\nimport { getSurah } from \"../data/quran\";\n\nexport interface SurahRangeValue {\n from: SurahWheelValue;\n to: SurahWheelValue;\n}\n\ninterface SurahRangePickerProps {\n value?: SurahRangeValue;\n labels?: Partial<SurahPickerLabels>;\n onChange: (v: SurahRangeValue) => void;\n physics?: React.ComponentProps<typeof SurahWheelPicker>[\"physics\"];\n loop?: boolean;\n nameFromSurah?: string;\n nameFromAyat?: string;\n nameToSurah?: string;\n nameToAyat?: string;\n}\n\nconst DEFAULT_RANGE: SurahRangeValue = {\n from: { surah: 1, ayat: 1 },\n to: { surah: 2, ayat: 5 },\n};\n\n// Urutan posisi: surah dulu, lalu ayat. Auto-follow menjaga from <= to.\nconst cmpPos = (a: SurahWheelValue, b: SurahWheelValue) =>\n a.surah !== b.surah ? a.surah - b.surah : a.ayat - b.ayat;\n\nexport function SurahRangePicker({\n value,\n labels: labelsProp,\n onChange,\n physics,\n loop = false,\n nameFromSurah = \"from_surah_number\",\n nameFromAyat = \"from_ayat\",\n nameToSurah = \"to_surah_number\",\n nameToAyat = \"to_ayat\",\n}: SurahRangePickerProps) {\n const labels = resolveLabels(labelsProp);\n const [from, setFrom] = useState(value?.from ?? DEFAULT_RANGE.from);\n const [to, setTo] = useState(value?.to ?? DEFAULT_RANGE.to);\n\n const emit = (next: SurahRangeValue) => {\n setFrom(next.from);\n setTo(next.to);\n onChange(next);\n };\n\n const handleFrom = (f: SurahWheelValue) => {\n emit({ from: f, to: cmpPos(f, to) > 0 ? f : to });\n };\n\n const handleTo = (next: SurahWheelValue) => {\n emit({ from: cmpPos(from, next) > 0 ? next : from, to: next });\n };\n\n const nameOf = (n: number) => getSurah(n)?.name ?? String(n);\n\n return (\n <div className=\"rounded-[20px] bg-surface border border-border p-4\">\n <div className=\"flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-3\">\n <div>\n <div className=\"text-[18px] font-bold leading-none tracking-tight text-foreground\">{labels.surah}</div>\n <div className=\"text-xs text-muted mt-1\">{labels.subtitle}</div>\n </div>\n <div className=\"rounded-xl px-4 py-2.5 text-[13px] font-medium min-w-[170px] text-center border-2 border-accent text-foreground w-full sm:w-auto\">\n {nameOf(from.surah)}:{from.ayat} - {nameOf(to.surah)}:{to.ayat}\n </div>\n </div>\n <input type=\"hidden\" name={nameFromSurah} value={String(from.surah)} />\n <input type=\"hidden\" name={nameFromAyat} value={String(from.ayat)} />\n <input type=\"hidden\" name={nameToSurah} value={String(to.surah)} />\n <input type=\"hidden\" name={nameToAyat} value={String(to.ayat)} />\n <div className=\"space-y-4\">\n <div className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold text-foreground\">{labels.from}</h3>\n <SurahWheelPicker\n value={from}\n onChange={handleFrom}\n physics={physics}\n loop={loop}\n chrome={false}\n ariaSurahLabel={labels.fromSurah}\n ariaAyatLabel={labels.fromAyah}\n />\n </div>\n <div className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold text-foreground\">{labels.to}</h3>\n <SurahWheelPicker\n value={to}\n onChange={handleTo}\n physics={physics}\n loop={loop}\n chrome={false}\n ariaSurahLabel={labels.toSurah}\n ariaAyatLabel={labels.toAyah}\n />\n </div>\n </div>\n </div>\n );\n}\n","import { useRef, useState, type ReactNode } from \"react\";\nimport { SurahWheelPicker, type SurahWheelValue } from \"./SurahWheelPicker\";\nimport { getSurah } from \"../data/quran\";\nimport { resolveLabels, type SurahPickerLabels } from \"../labels\";\nimport { Popup, type PopupPlacement } from \"../ui/Popup\";\nimport { BookIcon } from \"../icons/icons\";\n\ninterface SurahFieldPickerProps {\n value?: SurahWheelValue;\n onChange: (v: SurahWheelValue) => void;\n physics?: React.ComponentProps<typeof SurahWheelPicker>[\"physics\"];\n loop?: boolean;\n placeholder?: string;\n className?: string;\n popoverClassName?: string;\n /** Ikon kanan field (default ikon surat). Bisa diganti ikon lib lain. */\n icon?: ReactNode;\n /** Posisi popup (default kanan, flip otomatis bila sempit). */\n placement?: PopupPlacement;\n labels?: Partial<SurahPickerLabels>;\n nameSurah?: string;\n nameAyat?: string;\n}\n\n// Field yang membuka popup wheel di kanan (flip otomatis bila sempit).\n// Draft di dalam popup, commit hanya via Pilih; Batal/klik-luar/Escape buang.\nexport function SurahFieldPicker({\n value,\n onChange,\n physics,\n loop = false,\n placeholder,\n className,\n popoverClassName,\n icon,\n placement = \"right\",\n labels: labelsProp,\n nameSurah = \"surah_number\",\n nameAyat = \"ayat\",\n}: SurahFieldPickerProps) {\n const labels = resolveLabels(labelsProp);\n const [committed, setCommitted] = useState<SurahWheelValue>(value ?? { surah: 3, ayat: 3 });\n const [draft, setDraft] = useState<SurahWheelValue>(committed);\n const [open, setOpen] = useState(false);\n const fieldRef = useRef<HTMLButtonElement>(null);\n\n const current = value ?? committed;\n const text =\n placeholder && !value\n ? placeholder\n : `${getSurah(current.surah)?.name ?? current.surah}:${current.ayat}`;\n\n const handleOpenChange = (next: boolean) => {\n if (next) setDraft(current);\n setOpen(next);\n };\n\n const handleSelect = () => {\n setCommitted(draft);\n onChange(draft);\n setOpen(false);\n };\n\n return (\n <>\n <input type=\"hidden\" name={nameSurah} value={String(current.surah)} />\n <input type=\"hidden\" name={nameAyat} value={String(current.ayat)} />\n <button\n ref={fieldRef}\n type=\"button\"\n onClick={() => handleOpenChange(!open)}\n className={`flex w-full items-center justify-between gap-2 rounded-xl border border-divider bg-background px-3 py-2.5 text-sm text-foreground ${className ?? \"\"}`}\n >\n <span className=\"truncate\">{text}</span>\n {icon ?? <BookIcon className=\"w-4 h-4 shrink-0 text-muted\" />}\n </button>\n <Popup\n open={open}\n onClose={() => setOpen(false)}\n anchorRef={fieldRef}\n placement={placement}\n label={labels.surah}\n className={popoverClassName}\n >\n <div className=\"w-[320px] max-w-[calc(100vw-2rem)] p-3\">\n <SurahWheelPicker\n value={draft}\n onChange={setDraft}\n physics={physics}\n loop={loop}\n chrome={false}\n labels={labelsProp}\n nameSurah={nameSurah}\n nameAyat={nameAyat}\n />\n <div className=\"mt-3 flex justify-end gap-2\">\n <button type=\"button\" className=\"sp-btn sp-btn-ghost\" onClick={() => setOpen(false)}>\n {labels.cancel}\n </button>\n <button type=\"button\" className=\"sp-btn sp-btn-primary\" onClick={handleSelect}>\n {labels.select}\n </button>\n </div>\n </div>\n </Popup>\n </>\n );\n}\n","import {\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type ReactNode,\n type RefObject,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nconst useIsoLayoutEffect =\n typeof window !== \"undefined\" ? useLayoutEffect : useEffect;\n\nexport type PopupPlacement = \"bottom\" | \"right\";\n\ninterface PopupProps {\n open: boolean;\n onClose: () => void;\n anchorRef: RefObject<HTMLElement | null>;\n placement?: PopupPlacement;\n label?: string;\n className?: string;\n children: ReactNode;\n}\n\ninterface Pos {\n x: number;\n y: number;\n}\n\nconst GAP = 8;\n\nfunction clamp(v: number, min: number, max: number) {\n return Math.max(min, Math.min(v, max));\n}\n\n// Hitung posisi fixed + flip otomatis bila mentok viewport.\nfunction place(\n anchor: DOMRect,\n popW: number,\n popH: number,\n placement: PopupPlacement\n): Pos {\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n if (placement === \"right\") {\n let x = anchor.right + GAP;\n if (x + popW > vw) x = anchor.left - popW - GAP; // flip kiri\n const y = clamp(\n anchor.top + anchor.height / 2 - popH / 2,\n GAP,\n Math.max(GAP, vh - popH - GAP)\n );\n return { x: Math.max(GAP, x), y };\n }\n let y = anchor.bottom + GAP;\n if (y + popH > vh) y = anchor.top - popH - GAP; // flip atas\n const x = clamp(anchor.left, GAP, Math.max(GAP, vw - popW - GAP));\n return { x, y: Math.max(GAP, y) };\n}\n\n// Popup hand-rolled: tanpa dependensi selain react(-dom).\n// Portal ke body, Escape + klik-luar menutup, fokus kembali ke anchor.\nexport function Popup({\n open,\n onClose,\n anchorRef,\n placement = \"bottom\",\n label,\n className,\n children,\n}: PopupProps) {\n const popRef = useRef<HTMLDivElement>(null);\n const [pos, setPos] = useState<Pos | null>(null);\n\n useIsoLayoutEffect(() => {\n if (!open) {\n setPos(null);\n return;\n }\n const anchor = anchorRef.current;\n const pop = popRef.current;\n if (!anchor || !pop || typeof window === \"undefined\") return;\n const doPlace = () => {\n const el = popRef.current;\n const a = anchorRef.current;\n if (!el || !a) return;\n setPos(place(a.getBoundingClientRect(), el.offsetWidth, el.offsetHeight, placement));\n };\n doPlace();\n window.addEventListener(\"resize\", doPlace);\n window.addEventListener(\"scroll\", doPlace, true);\n return () => {\n window.removeEventListener(\"resize\", doPlace);\n window.removeEventListener(\"scroll\", doPlace, true);\n };\n }, [open, anchorRef, placement, children]);\n\n useEffect(() => {\n if (!open || typeof document === \"undefined\") return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n const onPointer = (e: PointerEvent) => {\n const t = e.target as Node;\n if (popRef.current?.contains(t)) return;\n if (anchorRef.current?.contains(t)) return;\n onClose();\n };\n document.addEventListener(\"keydown\", onKey);\n document.addEventListener(\"pointerdown\", onPointer);\n return () => {\n document.removeEventListener(\"keydown\", onKey);\n document.removeEventListener(\"pointerdown\", onPointer);\n };\n }, [open, onClose, anchorRef]);\n\n // Fokus kembali ke anchor bila fokus tertinggal di popup yang tutup.\n useEffect(() => {\n if (!open && typeof document !== \"undefined\") {\n const active = document.activeElement;\n if (active && popRef.current?.contains(active)) {\n anchorRef.current?.focus();\n }\n }\n }, [open, anchorRef]);\n\n if (!open || typeof document === \"undefined\") return null;\n return createPortal(\n <div\n ref={popRef}\n role=\"dialog\"\n aria-label={label}\n aria-modal=\"false\"\n className={`sp-popup ${className ?? \"\"}`}\n style={\n pos\n ? { left: pos.x, top: pos.y, visibility: \"visible\" }\n : { left: 0, top: 0, visibility: \"hidden\" }\n }\n >\n {children}\n </div>,\n document.body\n );\n}\n","interface IconProps {\n className?: string;\n}\n\n// ChevronDown: panah bawah (indikator dropdown).\nexport function ChevronDownIcon({ className }: IconProps) {\n return (\n <svg\n className={className}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <polyline points=\"6 9 12 15 18 9\" />\n </svg>\n );\n}\n\n// BookIcon: mushaf/kitab (ikon surat default di field).\nexport function BookIcon({ className }: IconProps) {\n return (\n <svg\n className={className}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M4 19.5A2.5 2.5 0 0 1 6.5 17H20\" />\n <path d=\"M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z\" />\n </svg>\n );\n}\n"],"mappings":"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","names":["friction","snapMs","loop","import_react","import_jsx_runtime","import_react","import_react","import_jsx_runtime","clamp","x","y","import_jsx_runtime","import_jsx_runtime"]}
@@ -0,0 +1,106 @@
1
+ import * as react from 'react';
2
+ import { RefObject, ReactNode } from 'react';
3
+
4
+ interface SurahPickerLabels {
5
+ surah: string;
6
+ ayah: string;
7
+ subtitle: string;
8
+ from: string;
9
+ to: string;
10
+ fromSurah: string;
11
+ fromAyah: string;
12
+ toSurah: string;
13
+ toAyah: string;
14
+ select: string;
15
+ cancel: string;
16
+ }
17
+ declare const defaultLabels: SurahPickerLabels;
18
+ declare function resolveLabels(partial?: Partial<SurahPickerLabels>): SurahPickerLabels;
19
+
20
+ interface SurahWheelValue {
21
+ surah: number;
22
+ ayat: number;
23
+ }
24
+ interface SurahWheelPhysics {
25
+ friction?: number;
26
+ maxVelocity?: number;
27
+ snapMs?: number;
28
+ }
29
+ interface Props {
30
+ value?: SurahWheelValue;
31
+ onChange: (v: SurahWheelValue) => void;
32
+ nameSurah?: string;
33
+ nameAyat?: string;
34
+ physics?: SurahWheelPhysics;
35
+ loop?: boolean;
36
+ chrome?: boolean;
37
+ ariaSurahLabel?: string;
38
+ ariaAyatLabel?: string;
39
+ labels?: Partial<SurahPickerLabels>;
40
+ }
41
+ declare function SurahWheelPicker({ value, onChange, nameSurah, nameAyat, physics, loop, chrome, ariaSurahLabel, ariaAyatLabel, labels: labelsProp }: Props): react.JSX.Element;
42
+
43
+ interface SurahRangeValue {
44
+ from: SurahWheelValue;
45
+ to: SurahWheelValue;
46
+ }
47
+ interface SurahRangePickerProps {
48
+ value?: SurahRangeValue;
49
+ labels?: Partial<SurahPickerLabels>;
50
+ onChange: (v: SurahRangeValue) => void;
51
+ physics?: React.ComponentProps<typeof SurahWheelPicker>["physics"];
52
+ loop?: boolean;
53
+ nameFromSurah?: string;
54
+ nameFromAyat?: string;
55
+ nameToSurah?: string;
56
+ nameToAyat?: string;
57
+ }
58
+ declare function SurahRangePicker({ value, labels: labelsProp, onChange, physics, loop, nameFromSurah, nameFromAyat, nameToSurah, nameToAyat, }: SurahRangePickerProps): react.JSX.Element;
59
+
60
+ type PopupPlacement = "bottom" | "right";
61
+ interface PopupProps {
62
+ open: boolean;
63
+ onClose: () => void;
64
+ anchorRef: RefObject<HTMLElement | null>;
65
+ placement?: PopupPlacement;
66
+ label?: string;
67
+ className?: string;
68
+ children: ReactNode;
69
+ }
70
+ declare function Popup({ open, onClose, anchorRef, placement, label, className, children, }: PopupProps): react.ReactPortal | null;
71
+
72
+ interface SurahFieldPickerProps {
73
+ value?: SurahWheelValue;
74
+ onChange: (v: SurahWheelValue) => void;
75
+ physics?: React.ComponentProps<typeof SurahWheelPicker>["physics"];
76
+ loop?: boolean;
77
+ placeholder?: string;
78
+ className?: string;
79
+ popoverClassName?: string;
80
+ /** Ikon kanan field (default ikon surat). Bisa diganti ikon lib lain. */
81
+ icon?: ReactNode;
82
+ /** Posisi popup (default kanan, flip otomatis bila sempit). */
83
+ placement?: PopupPlacement;
84
+ labels?: Partial<SurahPickerLabels>;
85
+ nameSurah?: string;
86
+ nameAyat?: string;
87
+ }
88
+ declare function SurahFieldPicker({ value, onChange, physics, loop, placeholder, className, popoverClassName, icon, placement, labels: labelsProp, nameSurah, nameAyat, }: SurahFieldPickerProps): react.JSX.Element;
89
+
90
+ interface IconProps {
91
+ className?: string;
92
+ }
93
+ declare function ChevronDownIcon({ className }: IconProps): react.JSX.Element;
94
+ declare function BookIcon({ className }: IconProps): react.JSX.Element;
95
+
96
+ interface Surah {
97
+ number: number;
98
+ name: string;
99
+ arabic: string;
100
+ ayatCount: number;
101
+ }
102
+ declare const SURAH_LIST: Surah[];
103
+ declare function getSurah(number: number): Surah | undefined;
104
+ declare function getAyatCount(surahNumber: number): number;
105
+
106
+ export { BookIcon, ChevronDownIcon, Popup, type PopupPlacement, SURAH_LIST, type Surah, SurahFieldPicker, type SurahPickerLabels, SurahRangePicker, type SurahRangeValue, type SurahWheelPhysics, SurahWheelPicker, type SurahWheelValue, defaultLabels, getAyatCount, getSurah, resolveLabels };
@@ -0,0 +1,106 @@
1
+ import * as react from 'react';
2
+ import { RefObject, ReactNode } from 'react';
3
+
4
+ interface SurahPickerLabels {
5
+ surah: string;
6
+ ayah: string;
7
+ subtitle: string;
8
+ from: string;
9
+ to: string;
10
+ fromSurah: string;
11
+ fromAyah: string;
12
+ toSurah: string;
13
+ toAyah: string;
14
+ select: string;
15
+ cancel: string;
16
+ }
17
+ declare const defaultLabels: SurahPickerLabels;
18
+ declare function resolveLabels(partial?: Partial<SurahPickerLabels>): SurahPickerLabels;
19
+
20
+ interface SurahWheelValue {
21
+ surah: number;
22
+ ayat: number;
23
+ }
24
+ interface SurahWheelPhysics {
25
+ friction?: number;
26
+ maxVelocity?: number;
27
+ snapMs?: number;
28
+ }
29
+ interface Props {
30
+ value?: SurahWheelValue;
31
+ onChange: (v: SurahWheelValue) => void;
32
+ nameSurah?: string;
33
+ nameAyat?: string;
34
+ physics?: SurahWheelPhysics;
35
+ loop?: boolean;
36
+ chrome?: boolean;
37
+ ariaSurahLabel?: string;
38
+ ariaAyatLabel?: string;
39
+ labels?: Partial<SurahPickerLabels>;
40
+ }
41
+ declare function SurahWheelPicker({ value, onChange, nameSurah, nameAyat, physics, loop, chrome, ariaSurahLabel, ariaAyatLabel, labels: labelsProp }: Props): react.JSX.Element;
42
+
43
+ interface SurahRangeValue {
44
+ from: SurahWheelValue;
45
+ to: SurahWheelValue;
46
+ }
47
+ interface SurahRangePickerProps {
48
+ value?: SurahRangeValue;
49
+ labels?: Partial<SurahPickerLabels>;
50
+ onChange: (v: SurahRangeValue) => void;
51
+ physics?: React.ComponentProps<typeof SurahWheelPicker>["physics"];
52
+ loop?: boolean;
53
+ nameFromSurah?: string;
54
+ nameFromAyat?: string;
55
+ nameToSurah?: string;
56
+ nameToAyat?: string;
57
+ }
58
+ declare function SurahRangePicker({ value, labels: labelsProp, onChange, physics, loop, nameFromSurah, nameFromAyat, nameToSurah, nameToAyat, }: SurahRangePickerProps): react.JSX.Element;
59
+
60
+ type PopupPlacement = "bottom" | "right";
61
+ interface PopupProps {
62
+ open: boolean;
63
+ onClose: () => void;
64
+ anchorRef: RefObject<HTMLElement | null>;
65
+ placement?: PopupPlacement;
66
+ label?: string;
67
+ className?: string;
68
+ children: ReactNode;
69
+ }
70
+ declare function Popup({ open, onClose, anchorRef, placement, label, className, children, }: PopupProps): react.ReactPortal | null;
71
+
72
+ interface SurahFieldPickerProps {
73
+ value?: SurahWheelValue;
74
+ onChange: (v: SurahWheelValue) => void;
75
+ physics?: React.ComponentProps<typeof SurahWheelPicker>["physics"];
76
+ loop?: boolean;
77
+ placeholder?: string;
78
+ className?: string;
79
+ popoverClassName?: string;
80
+ /** Ikon kanan field (default ikon surat). Bisa diganti ikon lib lain. */
81
+ icon?: ReactNode;
82
+ /** Posisi popup (default kanan, flip otomatis bila sempit). */
83
+ placement?: PopupPlacement;
84
+ labels?: Partial<SurahPickerLabels>;
85
+ nameSurah?: string;
86
+ nameAyat?: string;
87
+ }
88
+ declare function SurahFieldPicker({ value, onChange, physics, loop, placeholder, className, popoverClassName, icon, placement, labels: labelsProp, nameSurah, nameAyat, }: SurahFieldPickerProps): react.JSX.Element;
89
+
90
+ interface IconProps {
91
+ className?: string;
92
+ }
93
+ declare function ChevronDownIcon({ className }: IconProps): react.JSX.Element;
94
+ declare function BookIcon({ className }: IconProps): react.JSX.Element;
95
+
96
+ interface Surah {
97
+ number: number;
98
+ name: string;
99
+ arabic: string;
100
+ ayatCount: number;
101
+ }
102
+ declare const SURAH_LIST: Surah[];
103
+ declare function getSurah(number: number): Surah | undefined;
104
+ declare function getAyatCount(surahNumber: number): number;
105
+
106
+ export { BookIcon, ChevronDownIcon, Popup, type PopupPlacement, SURAH_LIST, type Surah, SurahFieldPicker, type SurahPickerLabels, SurahRangePicker, type SurahRangeValue, type SurahWheelPhysics, SurahWheelPicker, type SurahWheelValue, defaultLabels, getAyatCount, getSurah, resolveLabels };