@gftdcojp/gftd-orm
Version:
Enterprise-grade real-time data platform with ksqlDB, inspired by Supabase architecture
49 lines • 2.95 kB
JavaScript
'use client';
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SafeAuthComponent = SafeAuthComponent;
exports.withHydrationSafety = withHydrationSafety;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const client_1 = require("@gftdcojp/gftd-orm/client");
/**
* Hydration安全な認証コンポーネント
* React BuildError / Hydration Error を防ぐ実装
*/
function SafeAuthComponent() {
const { user, isLoading, error } = (0, client_1.useUser)();
const [isMounted, setIsMounted] = (0, react_1.useState)(false);
(0, react_1.useEffect)(() => {
setIsMounted(true);
}, []);
// 🔧 Hydration対策: マウント前は統一された表示
if (!isMounted) {
return (0, jsx_runtime_1.jsx)("div", { className: "text-gray-500", children: "\u8AAD\u307F\u8FBC\u307F\u4E2D..." });
}
if (isLoading) {
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2 border-blue-600" }), (0, jsx_runtime_1.jsx)("span", { children: "\u8A8D\u8A3C\u78BA\u8A8D\u4E2D..." })] }));
}
if (error) {
return ((0, jsx_runtime_1.jsxs)("div", { className: "text-red-600", children: [(0, jsx_runtime_1.jsx)("p", { children: "\u8A8D\u8A3C\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => window.location.reload(), className: "text-blue-600 underline", children: "\u518D\u8A66\u884C" })] }));
}
if (user) {
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-4", children: [(0, jsx_runtime_1.jsx)("img", { src: user.picture, alt: "Profile", className: "w-8 h-8 rounded-full" }), (0, jsx_runtime_1.jsxs)("span", { children: ["Welcome, ", user.name, "!"] }), (0, jsx_runtime_1.jsx)("a", { href: "/auth/logout", className: "btn btn-ghost", children: "Logout" })] }));
}
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex gap-2", children: [(0, jsx_runtime_1.jsx)("a", { href: "/auth/login", className: "btn btn-primary", children: "Login" }), (0, jsx_runtime_1.jsx)("a", { href: "/auth/login?screen_hint=signup", className: "btn btn-secondary", children: "Sign Up" })] }));
}
/**
* HOC版: 任意のコンポーネントをHydration安全にする
*/
function withHydrationSafety(Component) {
return function HydrationSafeComponent(props) {
const [isMounted, setIsMounted] = (0, react_1.useState)(false);
(0, react_1.useEffect)(() => {
setIsMounted(true);
}, []);
if (!isMounted) {
return (0, jsx_runtime_1.jsx)("div", { className: "text-gray-500", children: "\u8AAD\u307F\u8FBC\u307F\u4E2D..." });
}
return (0, jsx_runtime_1.jsx)(Component, { ...props });
};
}
//# sourceMappingURL=SafeAuthComponent.js.map