feat: initialize IoT Standards Lab website project with MAM skills & onboarding guide

This commit is contained in:
2026-07-29 23:43:59 +09:00
commit f3f53c1318
123 changed files with 19987 additions and 0 deletions
+60
View File
@@ -0,0 +1,60 @@
"use client";
import { useEffect, useRef, type ElementType, type ReactNode } from "react";
type Variant = "up" | "left" | "right" | "scale";
/**
* Scroll-triggered reveal. Uses a single IntersectionObserver (no deps).
* Pairs with the `.reveal` / `.is-visible` rules in globals.css.
*
* CUSTOMIZATION HOOK — MOTION:
* variant → direction of entrance
* delay → stagger (ms), applied as transition-delay
*/
export default function Reveal({
children,
variant = "up",
delay = 0,
as: Tag = "div",
className = "",
}: {
children: ReactNode;
variant?: Variant;
delay?: number;
as?: ElementType;
className?: string;
}) {
const ref = useRef<HTMLElement>(null);
useEffect(() => {
const el = ref.current;
if (!el) return;
const io = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("is-visible");
io.unobserve(entry.target);
}
});
},
{ threshold: 0.12, rootMargin: "0px 0px -8% 0px" }
);
io.observe(el);
return () => io.disconnect();
}, []);
return (
<Tag
ref={ref}
data-variant={variant}
style={delay ? { transitionDelay: `${delay}ms` } : undefined}
className={`reveal ${className}`}
>
{children}
</Tag>
);
}