@insforge/nextjs 0.7.1 → 0.7.2

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.
package/dist/index.mjs CHANGED
@@ -1,5 +1,19 @@
1
1
  "use client";
2
2
 
3
+ // Auto-inject InsForge styles
4
+ if (typeof document !== 'undefined' && typeof window !== 'undefined') {
5
+ const styleId = 'insforge-nextjs-styles';
6
+ if (!document.getElementById(styleId)) {
7
+ const style = document.createElement('style');
8
+ style.id = styleId;
9
+ style.textContent = "/**\n * InsForge Next.js Component Library Styles\n * A standalone CSS file for auth components - no Tailwind required!\n */\n\n/* Font Face Declaration */\n@font-face {\n font-family: 'Manrope';\n src: url('./fonts/Manrope-VariableFont_wght.ttf') format('truetype');\n font-weight: 100 900;\n font-style: normal;\n font-display: swap;\n}\n\n/* CSS Variables */\n:root {\n --font-manrope: 'Manrope', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n}\n\n/* Reset and Base Styles */\n.insforge-auth-container * {\n box-sizing: border-box;\n}\n\n/* Main Container - App handles layout, we just provide the card */\n.insforge-auth-container {\n width: 100%;\n max-width: 400px;\n background: white;\n}\n\n.insforge-branding {\n background: #FAFAFA;\n padding: 8px 8px 16px 8px;\n display: flex;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n gap: 4px;\n}\n\n.insforge-branding-text {\n color: #000;\n font-family: var(--font-manrope);\n font-size: 12px;\n font-style: normal;\n font-weight: 400;\n line-height: normal;\n}\n\n/* Form Card */\n.insforge-auth-card {\n width: 100%;\n border-radius: 12px;\n overflow: hidden;\n box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.25);\n}\n\n.insforge-auth-content {\n padding: 24px;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: stretch;\n gap: 24px;\n}\n\n/* Header */\n.insforge-auth-header {\n display: flex;\n flex-direction: column;\n justify-content: start;\n align-items: start;\n gap: 8px;\n}\n\n.insforge-auth-title {\n color: #000;\n font-family: Inter;\n font-size: 24px;\n font-style: normal;\n font-weight: 600;\n line-height: 32px; /* 133.333% */\n}\n\n.insforge-auth-subtitle {\n color: #828282;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 24px; /* 171.429% */\n}\n\n/* Error Banner */\n.insforge-error-banner {\n display: flex;\n padding: 8px 8px 8px 12px;\n margin-bottom: 16px;\n align-items: center;\n gap: 8px;\n align-self: stretch;\n border-radius: 4px;\n border: 2px solid #DC2626;\n background: #FEF2F2;\n color: #DC2626;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 20px; /* 142.857% */\n}\n\n.insforge-error-icon {\n color: #EF4444;\n flex-shrink: 0;\n width: 24px;\n height: 24px;\n}\n\n/* Form Elements */\n.insforge-form {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: stretch;\n gap: 24px;\n}\n\n.insforge-form-group {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: stretch;\n gap: 4px;\n}\n\n.insforge-form-label-row {\n display: flex;\n justify-content: space-between;\n align-items: center;\n}\n\n.insforge-form-label {\n color: #000;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 24px;\n}\n\n.insforge-form-link {\n color: #828282;\n text-align: right;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 24px;\n}\n\n.insforge-form-link:hover {\n color: #828282;\n text-decoration: underline;\n}\n\n/* Input Container for Password (with icon) */\n.insforge-input-wrapper {\n position: relative;\n}\n\n.insforge-input {\n width: 100%;\n display: flex;\n padding: 8px 8px 10px 12px;\n align-items: center;\n gap: 8px;\n align-self: stretch;\n border-radius: 4px;\n border: 1px solid #BCBCBC;\n background: #FFF;\n font-family: Inter;\n font-size: 16px;\n font-style: normal;\n font-weight: 400;\n line-height: 20px;\n}\n\n.insforge-input::placeholder {\n color: #A6A6A6;\n}\n\n.insforge-input:focus {\n outline: none;\n}\n\n.insforge-input-with-icon {\n padding-right: 3rem;\n}\n\n.insforge-input-icon-btn {\n position: absolute;\n right: 8px;\n top: 50%;\n transform: translateY(-50%);\n background: transparent;\n border: none;\n color: #A6A6A6;\n cursor: pointer;\n transition: color 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.insforge-input-icon-btn:hover {\n color: #6b7280;\n}\n\n/* Primary Button */\n.insforge-btn-primary {\n border-radius: 4px;\n background: #000;\n width: 100%;\n display: flex;\n margin: 16px 0 0 0;\n padding: 8px 16px;\n justify-content: center;\n align-items: center;\n gap: 10px;\n align-self: stretch;\n color: #FFF;\n font-family: Manrope;\n font-size: 16px;\n font-style: normal;\n font-weight: 600;\n line-height: normal;\n border: none;\n cursor: pointer;\n}\n\n.insforge-btn-primary:hover {\n background: #303030;\n}\n\n.insforge-btn-primary:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.insforge-btn-primary .insforge-btn-loader {\n display: none;\n animation: insforge-spin 1s linear infinite;\n}\n\n.insforge-btn-primary[data-loading] .insforge-btn-loader {\n display: block;\n}\n\n.insforge-btn-primary .insforge-btn-check {\n display: none;\n}\n\n.insforge-btn-primary[data-confirmed] .insforge-btn-check {\n display: block;\n}\n\n/* Text Link Section */\n.insforge-text-center {\n text-align: center;\n color: #828282;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 24px;\n}\n\n.insforge-link-primary {\n color: #000;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 500;\n line-height: 24px;\n}\n\n/* Divider */\n.insforge-divider {\n display: flex;\n justify-content: center;\n align-items: center;\n gap: 24px;\n align-self: stretch;\n}\n\n.insforge-divider::before,\n.insforge-divider::after {\n content: '';\n flex: 1;\n height: 1px;\n background: #C6C6C6;\n}\n\n.insforge-divider-text {\n color: #C6C6C6;\n font-family: Manrope;\n font-size: 14px;\n font-style: normal;\n font-weight: 600;\n line-height: normal;\n}\n\n/* OAuth Section */\n.insforge-oauth-container {\n display: grid;\n gap: 12px;\n width: 100%;\n}\n\n/* ============================================================================\n SMART OAUTH GRID LAYOUT SYSTEM\n Pattern: 1→1x1, 2→1x2, 3→1x3, 4→2x2, 5+→auto (3 per row, last row centered)\n ============================================================================ */\n\n/* 1 provider: single column, full width - displays \"Continue with Provider\" */\n.insforge-oauth-container[data-provider-count=\"1\"] {\n grid-template-columns: 1fr;\n}\n\n/* 2 providers: two columns - displays \"Provider\" */\n.insforge-oauth-container[data-provider-count=\"2\"] {\n grid-template-columns: repeat(2, 1fr);\n}\n\n/* 3 providers: three columns - icon only */\n.insforge-oauth-container[data-provider-count=\"3\"] {\n grid-template-columns: repeat(3, 1fr);\n}\n\n/* 4 providers: 2x2 grid - displays \"Provider\" */\n.insforge-oauth-container[data-provider-count=\"4\"] {\n grid-template-columns: repeat(2, 1fr);\n}\n\n/* 5+ providers: Universal 6-column grid system\n - Grid columns managed by OAuthProviderList component via inline styles\n - This provides precise control over button positioning */\n.insforge-oauth-container:not([data-provider-count=\"1\"]):not([data-provider-count=\"2\"]):not([data-provider-count=\"3\"]):not([data-provider-count=\"4\"]) {\n grid-template-columns: repeat(6, 1fr);\n}\n\n/* OAuth Button */\n.insforge-oauth-btn {\n display: flex;\n width: 100%;\n height: 36px;\n padding: 8px 12px;\n flex-direction: row;\n justify-content: center;\n align-items: center;\n gap: 12px;\n border-radius: 6px;\n border: 1px solid #E4E4E7;\n background: #FFF;\n box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.10);\n color: #09090B;\n text-align: center;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 500;\n line-height: 20px;\n cursor: pointer;\n transition: all 0.2s ease;\n}\n\n/* Full mode: show icon + \"Continue with Provider\" */\n.insforge-oauth-btn[data-display-mode=\"full\"] {\n justify-content: center;\n}\n\n/* Short mode: show icon + \"Provider\" */\n.insforge-oauth-btn[data-display-mode=\"short\"] {\n justify-content: center;\n padding: 8px;\n gap: 8px;\n}\n\n/* Icon only mode: show only icon */\n.insforge-oauth-btn[data-display-mode=\"icon\"] {\n justify-content: center;\n gap: 0;\n}\n\n.insforge-oauth-btn[data-display-mode=\"icon\"] .insforge-oauth-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n.insforge-oauth-btn:hover {\n background: #f9fafb;\n border-color: #9ca3af;\n}\n\n.insforge-oauth-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.insforge-oauth-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.insforge-oauth-loader {\n display: none;\n animation: insforge-spin 1s linear infinite;\n}\n\n.insforge-oauth-btn[data-loading] .insforge-oauth-icon {\n display: none;\n}\n\n.insforge-oauth-btn[data-loading] .insforge-oauth-loader {\n display: block;\n}\n\n/* Spin Animation */\n@keyframes insforge-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n/* UserButton Styles */\n.insforge-user-button-container {\n position: relative;\n display: inline-block;\n}\n\n.insforge-user-button {\n padding: 0.25rem;\n background: transparent;\n border: none;\n border-radius: 9999px;\n cursor: pointer;\n transition: all 0.2s;\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n}\n\n.insforge-user-button:hover {\n background: rgba(0, 0, 0, 0.05);\n}\n\n.insforge-user-button-detailed {\n border-radius: 0.5rem;\n padding: 0.5rem;\n}\n\n.insforge-user-button-info {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 0.125rem;\n}\n\n.insforge-user-button-name {\n font-size: 0.875rem;\n font-weight: 600;\n color: #111827;\n line-height: 1.25rem;\n text-align: left;\n}\n\n.insforge-user-button-email {\n font-size: 0.75rem;\n color: #6b7280;\n line-height: 1rem;\n text-align: left;\n}\n\n.insforge-user-avatar {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: 9999px;\n object-fit: cover;\n}\n\n.insforge-user-avatar-placeholder {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 2.5rem;\n height: 2.5rem;\n background: #3b82f6;\n color: white;\n font-weight: 600;\n font-size: 0.875rem;\n border-radius: 9999px;\n}\n\n.insforge-user-dropdown {\n position: absolute;\n top: 100%;\n right: 0;\n margin-top: 0.5rem;\n min-width: 10rem;\n background: white;\n border: 1px solid #e5e7eb;\n border-radius: 0.5rem;\n box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n z-index: 50;\n overflow: hidden;\n padding: 0.25rem;\n}\n\n.insforge-sign-out-button {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 0.5rem;\n width: 100%;\n padding: 0.5rem 0.75rem;\n font-size: 0.875rem;\n font-family: inherit;\n color: #dc2626;\n background: transparent;\n border: none;\n border-radius: 0.375rem;\n cursor: pointer;\n transition: background 0.2s;\n text-align: left;\n}\n\n.insforge-sign-out-button:hover {\n background: #fef2f2;\n}\n\n/* Loading State */\n.insforge-loading {\n display: flex;\n justify-content: center;\n align-items: center;\n padding: 2rem;\n color: #6b7280;\n font-size: 0.875rem;\n}\n\n/* Password Strength Indicator */\n.insforge-password-strength {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n margin-top: 0.5rem;\n}\n\n.insforge-password-requirement {\n height: 1.5rem;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.insforge-password-check {\n width: 1.25rem;\n height: 1.25rem;\n border-radius: 9999px;\n display: flex;\n border-width: 2px;\n border-style: solid;\n align-items: center;\n justify-content: center;\n transition: all 0.2s ease-in-out;\n background-color: transparent;\n border-color: #a3a3a3;\n flex-shrink: 0;\n}\n\n.insforge-password-check-valid {\n background-color: #22c55e;\n border-color: transparent;\n}\n\n.insforge-password-check-icon {\n color: #fff;\n stroke-width: 3;\n}\n\n.insforge-password-requirement-label {\n color:#000;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 24px;\n}\n\n/* Verification Code Input */\n.insforge-verification-code-container {\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 24px;\n}\n\n.insforge-verification-instructions {\n color: #525252;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 20px;\n}\n\n.insforge-verification-instructions > span {\n color: #000;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 600;\n line-height: 20px;\n}\n\n.insforge-verification-code-inputs {\n display: flex;\n flex-direction: row;\n gap: 12px;\n justify-content: center;\n align-items: center;\n}\n\n.insforge-verification-code-input {\n width: 100%;\n height: 48px;\n padding: 8px 12px;\n border-radius: 4px;\n border: 1px solid #E0E0E0;\n background: #FFF;\n text-align: center;\n font-size: 16px;\n font-style: normal;\n line-height: 20px;\n font-weight: 600;\n font-family: var(--font-manrope);\n color: #000;\n transition: all 0.2s ease-in-out;\n outline: none;\n}\n\n.insforge-verification-code-input:focus {\n border-color: #000;\n box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.1);\n}\n\n.insforge-verification-code-input:disabled {\n background-color: #F5F5F5;\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n/* Verification Instructions */\n.insforge-verification-instructions {\n color: #4F4F4F;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 24px;\n margin-bottom: 8px;\n}\n\n.insforge-verification-email {\n color: #000;\n font-weight: 600;\n}\n\n.insforge-resend-code {\n color: #525252;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 400;\n line-height: 24px;\n text-align: center;\n}\n\n.insforge-resend-link {\n color: #000;\n font-family: Inter;\n font-size: 14px;\n font-style: normal;\n font-weight: 500;\n line-height: 24px;\n}\n\n.insforge-resend-link:hover {\n text-decoration: underline;\n}\n\n.insforge-resend-link:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n/* Responsive adjustments */\n@media (max-width: 640px) {\n .insforge-auth-card {\n padding: 2rem 1.5rem;\n }\n\n .insforge-auth-title {\n font-size: 1.75rem;\n }\n\n .insforge-verification-code-container {\n gap: 8px;\n }\n\n .insforge-verification-code-input {\n width: 40px;\n height: 48px;\n font-size: 20px;\n }\n}\n\n";
10
+ if (document.head) {
11
+ document.head.appendChild(style);
12
+ }
13
+ }
14
+ }
15
+
16
+
3
17
  // src/provider/InsforgeProvider.tsx
4
18
  import { createContext, useContext, useEffect, useState, useCallback, useRef } from "react";
5
19
  import { createClient } from "@insforge/sdk";