UNPKG

@gftdcojp/gftd-orm

Version:

Enterprise-grade real-time data platform with ksqlDB, inspired by Supabase architecture

49 lines 2.95 kB
'use client'; "use strict"; 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