// ui.jsx — shared components: icons, Reveal, Nav, Footer, Newsletter, Toast, ProductCard
const { useState, useEffect, useRef, useCallback } = React;
/* ---------------- Icons (inline, stroke-based) ---------------- */
const I = {
search: (p) => ,
user: (p) => ,
bag: (p) => ,
heart: (p) => ,
eye: (p) => ,
play: (p) => ,
arrow: (p) => ,
close: (p) => ,
menu: (p) => ,
star: (p) => ,
check: (p) => ,
truck: (p) => ,
refresh:(p) => ,
shield: (p) => ,
spark: (p) => ,
phone: (p) => ,
mail: (p) => ,
pin: (p) => ,
social: (p) => ,
};
/* ---------------- Aura model image slot ---------------- */
// A persistent drop target for the user's AI model imagery.
function AuraSlot({ model, shape = "rect", radius, placeholder, src, ...rest }) {
return (
);
}
/* ---------------- Scroll reveal ---------------- */
function Reveal({ children, delay = 0, tag = "div", className = "", style = {} }) {
const ref = useRef(null);
useEffect(() => {
const el = ref.current;
if (!el) return;
const io = new IntersectionObserver((entries) => {
entries.forEach((e) => {
if (e.isIntersecting) { el.classList.add("in"); io.unobserve(el); }
});
}, { threshold: 0.12, rootMargin: "0px 0px -8% 0px" });
io.observe(el);
return () => io.disconnect();
}, []);
const Tag = tag;
return {children};
}
/* ---------------- Stars ---------------- */
function Stars({ n = 5 }) {
return
{Array.from({ length: 5 }).map((_, i) => )}
;
}
const fmt = (n) => new Intl.NumberFormat("tr-TR").format(n) + " ₺";
/* ---------------- Nav ---------------- */
function Nav({ route, go, cartCount, onSearch }) {
const [open, setOpen] = useState(false);
const links = [
["home", "Ana Sayfa"],
["collection", "Koleksiyon"],
["vton", "Sanal Deneme"],
["story", "Hikâye"],
];
return (
);
}
/* ---------------- Product card ---------------- */
function ProductCard({ p, go, onQuick, onFav, onAdd }) {
return (
go("product", p.id)}>
{p.badge &&
{p.badge}}
{p.old && {fmt(p.old)}}
{fmt(p.price)}
);
}
/* ---------------- Newsletter ---------------- */
function Newsletter({ onToast }) {
const [val, setVal] = useState("");
return (
Bülten
Atölyeden ilk haberi siz alın.
Yeni koleksiyonlar, premium atölye ürünleri ve özel kampanyalar — gelen kutunuza, ayda en fazla iki kez.
Abone olarak KVKK aydınlatma metnini kabul etmiş olursunuz. Dilediğiniz zaman çıkabilirsiniz.
);
}
/* ---------------- Footer ---------------- */
function Footer({ go }) {
return (
);
}
/* ---------------- Toast host ---------------- */
function useToasts() {
const [toasts, setToasts] = useState([]);
const push = useCallback((msg) => {
const id = Math.random().toString(36).slice(2);
setToasts((t) => [...t, { id, msg }]);
setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 2600);
}, []);
const node = (
{toasts.map((t) =>
{t.msg}
)}
);
return [push, node];
}
Object.assign(window, { I, AuraSlot, Reveal, Stars, fmt, Nav, ProductCard, Newsletter, Footer, useToasts });