UNPKG

@frank-auth/react

Version:

Flexible and customizable React UI components for Frank Authentication

1 lines 20.9 kB
{"version":3,"file":"use-config.cjs","sources":["../../../src/hooks/use-config.ts"],"sourcesContent":["/**\n * @frank-auth/react - useConfig Hook\n *\n * Configuration hook that provides access to UI configuration, feature flags,\n * localization settings, and organization-specific configuration.\n */\n\nimport { useCallback, useMemo } from \"react\";\n\nimport type {\n\tAppearanceConfig,\n\tComponentOverrides,\n\tFrankAuthUIConfig,\n\tLocalizationConfig,\n\tOrganizationConfig,\n\tTheme,\n} from \"../config\";\n\nimport { useConfig as useConfigProvider } from \"../provider/config-provider\";\nimport { useAuth } from \"./use-auth\";\n\nimport type { AuthFeatures, LinksPathConfig } from \"../provider/types\";\n\n// ============================================================================\n// Config Hook Interface\n// ============================================================================\n\nexport interface UseConfigReturn {\n\t// Core configuration\n\tconfig: FrankAuthUIConfig;\n\tpublishableKey: string;\n\tapiUrl: string;\n\tuserType: string;\n\tdebug: boolean;\n\n\t// UI configuration\n\ttheme: Theme;\n\tappearance: AppearanceConfig;\n\tlocalization: LocalizationConfig;\n\tcomponents: ComponentOverrides;\n\ttitleAlignment: \"left\" | \"center\" | \"right\";\n\tlinksPath?: LinksPathConfig;\n\n\t// Organization configuration\n\torganization: OrganizationConfig | undefined;\n\torganizationSettings: any;\n\n\t// Feature flags\n\tfeatures: AuthFeatures;\n\n\t// Configuration methods\n\tupdateConfig: (updates: Partial<FrankAuthUIConfig>) => void;\n\tsetTheme: (theme: Partial<Theme>) => void;\n\tsetAppearance: (appearance: Partial<AppearanceConfig>) => void;\n\tsetLocale: (locale: string) => void;\n\tresetToDefaults: () => void;\n\n\t// Feature flag helpers\n\thasFeature: (feature: keyof AuthFeatures) => boolean;\n\trequireFeature: (feature: keyof AuthFeatures) => void;\n\n\t// Validation\n\tisConfigValid: boolean;\n\tconfigErrors: string[];\n\n\t// State helpers\n\tisLoaded: boolean;\n\tisMultiTenant: boolean;\n\tisCustomBranded: boolean;\n}\n\n// ============================================================================\n// Main useConfig Hook\n// ============================================================================\n\n/**\n * Configuration hook providing access to all UI configuration and settings\n *\n * @example Basic configuration access\n * ```tsx\n * import { useConfig } from '@frank-auth/react';\n *\n * function ConfigDisplay() {\n * const {\n * theme,\n * features,\n * hasFeature,\n * organization,\n * setTheme\n * } = useConfig();\n *\n * return (\n * <div>\n * <p>Theme mode: {theme.mode}</p>\n * <p>MFA enabled: {hasFeature('mfa') ? 'Yes' : 'No'}</p>\n * {organization && <p>Organization: {organization.name}</p>}\n *\n * <button onClick={() => setTheme({ mode: 'dark' })}>\n * Switch to Dark Mode\n * </button>\n * </div>\n * );\n * }\n * ```\n *\n * @example Feature-based conditional rendering\n * ```tsx\n * function ConditionalFeatures() {\n * const { hasFeature, requireFeature } = useConfig();\n *\n * // Conditional rendering\n * if (!hasFeature('mfa')) {\n * return <div>MFA not available</div>;\n * }\n *\n * // Feature requirement (throws if not available)\n * const handleMFASetup = () => {\n * requireFeature('mfa');\n * // MFA setup logic...\n * };\n *\n * return <button onClick={handleMFASetup}>Setup MFA</button>;\n * }\n * ```\n *\n * @example Organization-specific configuration\n * ```tsx\n * function OrganizationConfig() {\n * const {\n * organization,\n * organizationSettings,\n * isMultiTenant,\n * isCustomBranded\n * } = useConfig();\n *\n * if (!isMultiTenant) {\n * return <div>Single tenant mode</div>;\n * }\n *\n * return (\n * <div>\n * <h3>{organization?.name}</h3>\n * {isCustomBranded && (\n * <img src={organizationSettings?.branding?.logo} alt=\"Organization Logo\" />\n * )}\n * <p>MFA Required: {organizationSettings?.mfaRequired ? 'Yes' : 'No'}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useConfig(): UseConfigReturn {\n\tconst configProvider = useConfigProvider();\n\tconst { activeOrganization } = useAuth();\n\n\t// Feature flag helpers\n\tconst hasFeature = useCallback(\n\t\t(feature: keyof AuthFeatures): boolean => {\n\t\t\treturn configProvider.features[feature];\n\t\t},\n\t\t[configProvider.features],\n\t);\n\n\tconst requireFeature = useCallback(\n\t\t(feature: keyof AuthFeatures): void => {\n\t\t\tif (!configProvider.features[feature]) {\n\t\t\t\tthrow new Error(`Feature ${feature} is not enabled`);\n\t\t\t}\n\t\t},\n\t\t[configProvider.features],\n\t);\n\n\t// Configuration validation\n\tconst { isConfigValid, configErrors } = useMemo(() => {\n\t\tconst errors: string[] = [];\n\n\t\t// Validate required configuration\n\t\tif (!configProvider.publishableKey) {\n\t\t\terrors.push(\"Publishable key is required\");\n\t\t}\n\n\t\tif (!configProvider.userType) {\n\t\t\terrors.push(\"User type is required\");\n\t\t}\n\n\t\t// Validate publishable key format\n\t\tif (\n\t\t\tconfigProvider.publishableKey &&\n\t\t\t!/^pk_(test|live)_[a-zA-Z0-9_]+$/.test(configProvider.publishableKey)\n\t\t) {\n\t\t\terrors.push(\"Invalid publishable key format\");\n\t\t}\n\n\t\t// Validate API URL format\n\t\tif (configProvider.apiUrl) {\n\t\t\ttry {\n\t\t\t\tnew URL(configProvider.apiUrl);\n\t\t\t} catch {\n\t\t\t\terrors.push(\"Invalid API URL format\");\n\t\t\t}\n\t\t}\n\n\t\t// Validate user type\n\t\tif (\n\t\t\tconfigProvider.userType &&\n\t\t\t![\"internal\", \"external\", \"end_user\"].includes(configProvider.userType)\n\t\t) {\n\t\t\terrors.push(\"Invalid user type\");\n\t\t}\n\n\t\treturn {\n\t\t\tisConfigValid: errors.length === 0,\n\t\t\tconfigErrors: errors,\n\t\t};\n\t}, [\n\t\tconfigProvider.publishableKey,\n\t\tconfigProvider.userType,\n\t\tconfigProvider.apiUrl,\n\t]);\n\n\t// State helpers\n\tconst isMultiTenant = useMemo(\n\t\t() => !!configProvider.organizationConfig,\n\t\t[configProvider.organizationConfig],\n\t);\n\tconst isCustomBranded = useMemo(() => {\n\t\treturn !!(\n\t\t\tconfigProvider.organizationSettings?.branding?.logoUrl ||\n\t\t\tconfigProvider.organizationSettings?.branding?.primaryColor ||\n\t\t\tconfigProvider.organizationSettings?.branding?.customCss\n\t\t);\n\t}, [configProvider.organizationSettings]);\n\n\treturn {\n\t\t// Core configuration\n\t\tconfig: configProvider.config,\n\t\tpublishableKey: configProvider.publishableKey,\n\t\tapiUrl: configProvider.apiUrl,\n\t\tuserType: configProvider.userType,\n\t\tdebug: configProvider.debug,\n\n\t\t// UI configuration\n\t\ttitleAlignment: configProvider.config?.appearance?.titleAlignment ?? \"left\",\n\t\ttheme: configProvider.theme,\n\t\tappearance: configProvider.appearance,\n\t\tlocalization: configProvider.localization,\n\t\tcomponents: configProvider.components,\n\t\tlinksPath: configProvider.linksPath,\n\n\t\t// Organization configuration\n\t\torganization: configProvider.organizationConfig,\n\t\torganizationSettings: configProvider.organizationSettings,\n\n\t\t// Feature flags\n\t\tfeatures: configProvider.features,\n\n\t\t// Configuration methods\n\t\tupdateConfig: configProvider.updateConfig,\n\t\tsetTheme: configProvider.setTheme,\n\t\tsetAppearance: configProvider.setAppearance,\n\t\tsetLocale: configProvider.setLocale,\n\t\tresetToDefaults: configProvider.resetToDefaults,\n\n\t\t// Feature flag helpers\n\t\thasFeature,\n\t\trequireFeature,\n\n\t\t// Validation\n\t\tisConfigValid,\n\t\tconfigErrors,\n\n\t\t// State helpers\n\t\tisLoaded: configProvider.isLoaded,\n\t\tisMultiTenant,\n\t\tisCustomBranded,\n\t};\n}\n\n// ============================================================================\n// Specialized Config Hooks\n// ============================================================================\n\n/**\n * Hook for feature flags only\n */\nexport function useFeatureFlags() {\n\tconst { features, hasFeature, requireFeature } = useConfig();\n\n\treturn {\n\t\tfeatures,\n\t\thasFeature,\n\t\trequireFeature,\n\n\t\t// Convenience methods for common features\n\t\tcanSignUp: hasFeature(\"signUp\"),\n\t\tcanSignIn: hasFeature(\"signIn\"),\n\t\tcanResetPassword: hasFeature(\"passwordReset\"),\n\t\thasMFA: hasFeature(\"mfa\"),\n\t\thasPasskeys: hasFeature(\"passkeys\"),\n\t\thasOAuth: hasFeature(\"oauth\"),\n\t\thasMagicLink: hasFeature(\"magicLink\"),\n\t\thasSSO: hasFeature(\"sso\"),\n\t\thasOrganizationManagement: hasFeature(\"organizationManagement\"),\n\t\thasUserProfile: hasFeature(\"userProfile\"),\n\t\thasSessionManagement: hasFeature(\"sessionManagement\"),\n\t};\n}\n\n/**\n * Hook for theme configuration\n */\nexport function useThemeConfig() {\n\tconst { theme, setTheme, appearance, setAppearance } = useConfig();\n\n\treturn {\n\t\ttheme,\n\t\tappearance,\n\t\tsetTheme,\n\t\tsetAppearance,\n\n\t\t// Theme helpers\n\t\tmode: theme.mode,\n\t\tcolors: theme.colors,\n\t\ttypography: theme.typography,\n\t\tspacing: theme.spacing,\n\t\tborderRadius: theme.borderRadius,\n\t\tshadows: theme.shadows,\n\n\t\t// Appearance helpers\n\t\tlayout: appearance.layout,\n\t\tcomponents: appearance.components,\n\t\tbranding: appearance.branding,\n\n\t\t// Quick theme updates\n\t\tsetMode: (mode: \"light\" | \"dark\" | \"system\") => setTheme({ mode }),\n\t\tsetPrimaryColor: (color: string) =>\n\t\t\tsetTheme({\n\t\t\t\tcolors: {\n\t\t\t\t\t...theme.colors,\n\t\t\t\t\tprimary: { ...theme.colors.primary, DEFAULT: color },\n\t\t\t\t},\n\t\t\t}),\n\t\tsetSecondaryColor: (color: string) =>\n\t\t\tsetTheme({\n\t\t\t\tcolors: {\n\t\t\t\t\t...theme.colors,\n\t\t\t\t\tsecondary: { ...theme.colors.secondary, DEFAULT: color },\n\t\t\t\t},\n\t\t\t}),\n\t};\n}\n\n/**\n * Hook for localization configuration\n */\nexport function useLocalizationConfig() {\n\tconst { localization, setLocale } = useConfig();\n\n\treturn {\n\t\tlocalization,\n\t\tsetLocale,\n\n\t\t// Localization helpers\n\t\tcurrentLocale: localization.defaultLocale,\n\t\tsupportedLocales: localization.supportedLocales,\n\t\tdateFormat: localization.dateFormat,\n\t\ttimeFormat: localization.timeFormat,\n\t\tdirection: localization.direction,\n\n\t\t// Quick locale updates\n\t\tisRTL: localization.direction === \"rtl\",\n\t\tsetEnglish: () => setLocale(\"en\"),\n\t\tsetSpanish: () => setLocale(\"es\"),\n\t\tsetFrench: () => setLocale(\"fr\"),\n\t\tsetGerman: () => setLocale(\"de\"),\n\t};\n}\n\n/**\n * Hook for organization-specific configuration\n */\nexport function useOrganizationConfiguration() {\n\tconst {\n\t\torganization,\n\t\torganizationSettings,\n\t\tisMultiTenant,\n\t\tisCustomBranded,\n\t\tfeatures,\n\t} = useConfig();\n\n\tconst organizationFeatures = useMemo(() => {\n\t\tif (!organization) return {};\n\n\t\treturn {\n\t\t\tsso: organization.features?.sso || false,\n\t\t\tmfa: organization.features?.mfa || false,\n\t\t\tauditLogs: organization.features?.auditLogs || false,\n\t\t\tcustomBranding: organization.features?.customBranding || false,\n\t\t\tapiAccess: organization.features?.apiAccess || false,\n\t\t};\n\t}, [organization]);\n\n\treturn {\n\t\torganization,\n\t\torganizationSettings,\n\t\tisMultiTenant,\n\t\tisCustomBranded,\n\t\tfeatures: organizationFeatures,\n\n\t\t// Organization helpers\n\t\torganizationId: organization?.id || null,\n\t\torganizationName: organization?.name || null,\n\t\torganizationSlug: organization?.slug || null,\n\n\t\t// Settings helpers\n\t\tallowPublicSignup: organizationSettings?.allowPublicSignup || false,\n\t\trequireEmailVerification:\n\t\t\torganizationSettings?.requireEmailVerification || false,\n\t\trequirePhoneVerification:\n\t\t\torganizationSettings?.requirePhoneVerification || false,\n\t\tmfaRequired: organizationSettings?.mfaRequired || false,\n\t\tallowedMfaMethods: organizationSettings?.allowedMfaMethods || [],\n\n\t\t// Branding helpers\n\t\tbranding: organizationSettings?.branding,\n\t\tlogo: organizationSettings?.branding?.logo,\n\t\tprimaryColor: organizationSettings?.branding?.primaryColor,\n\t\tsecondaryColor: organizationSettings?.branding?.secondaryColor,\n\t\tcustomCSS: organizationSettings?.branding?.customCSS,\n\n\t\t// Limits\n\t\tlimits: organization?.limits,\n\t\tmaxUsers: organization?.limits?.maxUsers || 0,\n\t\tmaxSessions: organization?.limits?.maxSessions || 0,\n\t\tapiRequestLimit: organization?.limits?.apiRequestLimit || 0,\n\t};\n}\n\n/**\n * Hook for component overrides\n */\nexport function useComponentConfiguration() {\n\tconst { components } = useConfig();\n\n\tconst getComponent = useCallback(\n\t\t<T extends keyof ComponentOverrides>(\n\t\t\tcomponentName: T,\n\t\t\tdefaultComponent: any,\n\t\t) => {\n\t\t\treturn components[componentName] || defaultComponent;\n\t\t},\n\t\t[components],\n\t);\n\n\tconst hasOverride = useCallback(\n\t\t(componentName: keyof ComponentOverrides) => {\n\t\t\treturn !!components[componentName];\n\t\t},\n\t\t[components],\n\t);\n\n\treturn {\n\t\tcomponents,\n\t\tgetComponent,\n\t\thasOverride,\n\n\t\t// Component availability checks\n\t\thasCustomLayout: hasOverride(\"Layout\"),\n\t\thasCustomHeader: hasOverride(\"Header\"),\n\t\thasCustomFooter: hasOverride(\"Footer\"),\n\t\thasCustomSignInForm: hasOverride(\"SignInForm\"),\n\t\thasCustomSignUpForm: hasOverride(\"SignUpForm\"),\n\t\thasCustomUserProfile: hasOverride(\"UserProfile\"),\n\t\thasCustomButton: hasOverride(\"Button\"),\n\t\thasCustomInput: hasOverride(\"Input\"),\n\t\thasCustomCard: hasOverride(\"Card\"),\n\t\thasCustomModal: hasOverride(\"Modal\"),\n\t};\n}\n\n/**\n * Hook for configuration validation and debugging\n */\nexport function useConfigValidation() {\n\tconst {\n\t\tisConfigValid,\n\t\tconfigErrors,\n\t\tdebug,\n\t\tpublishableKey,\n\t\tapiUrl,\n\t\tuserType,\n\t} = useConfig();\n\n\tconst warnings = useMemo(() => {\n\t\tconst warnings: string[] = [];\n\n\t\t// Development warnings\n\t\tif (\n\t\t\tpublishableKey?.startsWith(\"pk_test_\") &&\n\t\t\ttypeof window !== \"undefined\" &&\n\t\t\twindow.location.hostname !== \"localhost\" &&\n\t\t\t!window.location.hostname.includes(\"127.0.0.1\")\n\t\t) {\n\t\t\twarnings.push(\"Using test publishable key in production environment\");\n\t\t}\n\n\t\tif (\n\t\t\tapiUrl?.startsWith(\"http://\") &&\n\t\t\ttypeof window !== \"undefined\" &&\n\t\t\twindow.location.protocol === \"https:\"\n\t\t) {\n\t\t\twarnings.push(\"Using HTTP API URL on HTTPS site\");\n\t\t}\n\n\t\treturn warnings;\n\t}, [publishableKey, apiUrl]);\n\n\treturn {\n\t\tisValid: isConfigValid,\n\t\terrors: configErrors,\n\t\twarnings,\n\t\tdebug,\n\n\t\t// Helper methods\n\t\thasErrors: configErrors.length > 0,\n\t\thasWarnings: warnings.length > 0,\n\t\tisProduction: !publishableKey?.startsWith(\"pk_test_\"),\n\t\tisTestMode: publishableKey?.startsWith(\"pk_test_\"),\n\n\t\t// Validation helpers\n\t\tvalidatePublishableKey: () => {\n\t\t\tif (!publishableKey) return false;\n\t\t\treturn /^pk_(test|live|standalone)_[a-zA-Z0-9_]+$/.test(publishableKey);\n\t\t},\n\t\tvalidateApiUrl: () => {\n\t\t\tif (!apiUrl) return true; // Optional\n\t\t\ttry {\n\t\t\t\tnew URL(apiUrl);\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tvalidateUserType: () => {\n\t\t\treturn [\"internal\", \"external\", \"end_user\"].includes(userType);\n\t\t},\n\t};\n}\n"],"names":["useConfig","configProvider","useConfigProvider","activeOrganization","useAuth","hasFeature","useCallback","feature","requireFeature","isConfigValid","configErrors","useMemo","errors","isMultiTenant","isCustomBranded","useFeatureFlags","features","useThemeConfig","theme","setTheme","appearance","setAppearance","mode","color","useLocalizationConfig","localization","setLocale","useOrganizationConfiguration","organization","organizationSettings","organizationFeatures","useComponentConfiguration","components","getComponent","componentName","defaultComponent","hasOverride","useConfigValidation","debug","publishableKey","apiUrl","userType","warnings"],"mappings":"kLAuJO,SAASA,GAA6B,CAC5C,MAAMC,EAAiBC,EAAAA,UAAkB,EACnC,CAAE,mBAAAC,CAAmB,EAAIC,UAAQ,EAGjCC,EAAaC,EAAA,YACjBC,GACON,EAAe,SAASM,CAAO,EAEvC,CAACN,EAAe,QAAQ,CACzB,EAEMO,EAAiBF,EAAA,YACrBC,GAAsC,CACtC,GAAI,CAACN,EAAe,SAASM,CAAO,EACnC,MAAM,IAAI,MAAM,WAAWA,CAAO,iBAAiB,CAErD,EACA,CAACN,EAAe,QAAQ,CACzB,EAGM,CAAE,cAAAQ,EAAe,aAAAC,CAAa,EAAIC,UAAQ,IAAM,CACrD,MAAMC,EAAmB,CAAC,EAoB1B,GAjBKX,EAAe,gBACnBW,EAAO,KAAK,6BAA6B,EAGrCX,EAAe,UACnBW,EAAO,KAAK,uBAAuB,EAKnCX,EAAe,gBACf,CAAC,iCAAiC,KAAKA,EAAe,cAAc,GAEpEW,EAAO,KAAK,gCAAgC,EAIzCX,EAAe,OACd,GAAA,CACC,IAAA,IAAIA,EAAe,MAAM,CAAA,MACtB,CACPW,EAAO,KAAK,wBAAwB,CAAA,CAMrC,OAAAX,EAAe,UACf,CAAC,CAAC,WAAY,WAAY,UAAU,EAAE,SAASA,EAAe,QAAQ,GAEtEW,EAAO,KAAK,mBAAmB,EAGzB,CACN,cAAeA,EAAO,SAAW,EACjC,aAAcA,CACf,CAAA,EACE,CACFX,EAAe,eACfA,EAAe,SACfA,EAAe,MAAA,CACf,EAGKY,EAAgBF,EAAA,QACrB,IAAM,CAAC,CAACV,EAAe,mBACvB,CAACA,EAAe,kBAAkB,CACnC,EACMa,EAAkBH,EAAAA,QAAQ,IACxB,CAAC,EACPV,EAAe,sBAAsB,UAAU,SAC/CA,EAAe,sBAAsB,UAAU,cAC/CA,EAAe,sBAAsB,UAAU,WAE9C,CAACA,EAAe,oBAAoB,CAAC,EAEjC,MAAA,CAEN,OAAQA,EAAe,OACvB,eAAgBA,EAAe,eAC/B,OAAQA,EAAe,OACvB,SAAUA,EAAe,SACzB,MAAOA,EAAe,MAGtB,eAAgBA,EAAe,QAAQ,YAAY,gBAAkB,OACrE,MAAOA,EAAe,MACtB,WAAYA,EAAe,WAC3B,aAAcA,EAAe,aAC7B,WAAYA,EAAe,WAC3B,UAAWA,EAAe,UAG1B,aAAcA,EAAe,mBAC7B,qBAAsBA,EAAe,qBAGrC,SAAUA,EAAe,SAGzB,aAAcA,EAAe,aAC7B,SAAUA,EAAe,SACzB,cAAeA,EAAe,cAC9B,UAAWA,EAAe,UAC1B,gBAAiBA,EAAe,gBAGhC,WAAAI,EACA,eAAAG,EAGA,cAAAC,EACA,aAAAC,EAGA,SAAUT,EAAe,SACzB,cAAAY,EACA,gBAAAC,CACD,CACD,CASO,SAASC,GAAkB,CACjC,KAAM,CAAE,SAAAC,EAAU,WAAAX,EAAY,eAAAG,CAAA,EAAmBR,EAAU,EAEpD,MAAA,CACN,SAAAgB,EACA,WAAAX,EACA,eAAAG,EAGA,UAAWH,EAAW,QAAQ,EAC9B,UAAWA,EAAW,QAAQ,EAC9B,iBAAkBA,EAAW,eAAe,EAC5C,OAAQA,EAAW,KAAK,EACxB,YAAaA,EAAW,UAAU,EAClC,SAAUA,EAAW,OAAO,EAC5B,aAAcA,EAAW,WAAW,EACpC,OAAQA,EAAW,KAAK,EACxB,0BAA2BA,EAAW,wBAAwB,EAC9D,eAAgBA,EAAW,aAAa,EACxC,qBAAsBA,EAAW,mBAAmB,CACrD,CACD,CAKO,SAASY,GAAiB,CAChC,KAAM,CAAE,MAAAC,EAAO,SAAAC,EAAU,WAAAC,EAAY,cAAAC,CAAA,EAAkBrB,EAAU,EAE1D,MAAA,CACN,MAAAkB,EACA,WAAAE,EACA,SAAAD,EACA,cAAAE,EAGA,KAAMH,EAAM,KACZ,OAAQA,EAAM,OACd,WAAYA,EAAM,WAClB,QAASA,EAAM,QACf,aAAcA,EAAM,aACpB,QAASA,EAAM,QAGf,OAAQE,EAAW,OACnB,WAAYA,EAAW,WACvB,SAAUA,EAAW,SAGrB,QAAUE,GAAsCH,EAAS,CAAE,KAAAG,EAAM,EACjE,gBAAkBC,GACjBJ,EAAS,CACR,OAAQ,CACP,GAAGD,EAAM,OACT,QAAS,CAAE,GAAGA,EAAM,OAAO,QAAS,QAASK,CAAM,CAAA,CACpD,CACA,EACF,kBAAoBA,GACnBJ,EAAS,CACR,OAAQ,CACP,GAAGD,EAAM,OACT,UAAW,CAAE,GAAGA,EAAM,OAAO,UAAW,QAASK,CAAM,CAAA,CAExD,CAAA,CACH,CACD,CAKO,SAASC,GAAwB,CACvC,KAAM,CAAE,aAAAC,EAAc,UAAAC,CAAU,EAAI1B,EAAU,EAEvC,MAAA,CACN,aAAAyB,EACA,UAAAC,EAGA,cAAeD,EAAa,cAC5B,iBAAkBA,EAAa,iBAC/B,WAAYA,EAAa,WACzB,WAAYA,EAAa,WACzB,UAAWA,EAAa,UAGxB,MAAOA,EAAa,YAAc,MAClC,WAAY,IAAMC,EAAU,IAAI,EAChC,WAAY,IAAMA,EAAU,IAAI,EAChC,UAAW,IAAMA,EAAU,IAAI,EAC/B,UAAW,IAAMA,EAAU,IAAI,CAChC,CACD,CAKO,SAASC,GAA+B,CACxC,KAAA,CACL,aAAAC,EACA,qBAAAC,EACA,cAAAhB,EACA,gBAAAC,EACA,SAAAE,GACGhB,EAAU,EAER8B,EAAuBnB,EAAAA,QAAQ,IAC/BiB,EAEE,CACN,IAAKA,EAAa,UAAU,KAAO,GACnC,IAAKA,EAAa,UAAU,KAAO,GACnC,UAAWA,EAAa,UAAU,WAAa,GAC/C,eAAgBA,EAAa,UAAU,gBAAkB,GACzD,UAAWA,EAAa,UAAU,WAAa,EAChD,EAR0B,CAAC,EASzB,CAACA,CAAY,CAAC,EAEV,MAAA,CACN,aAAAA,EACA,qBAAAC,EACA,cAAAhB,EACA,gBAAAC,EACA,SAAUgB,EAGV,eAAgBF,GAAc,IAAM,KACpC,iBAAkBA,GAAc,MAAQ,KACxC,iBAAkBA,GAAc,MAAQ,KAGxC,kBAAmBC,GAAsB,mBAAqB,GAC9D,yBACCA,GAAsB,0BAA4B,GACnD,yBACCA,GAAsB,0BAA4B,GACnD,YAAaA,GAAsB,aAAe,GAClD,kBAAmBA,GAAsB,mBAAqB,CAAC,EAG/D,SAAUA,GAAsB,SAChC,KAAMA,GAAsB,UAAU,KACtC,aAAcA,GAAsB,UAAU,aAC9C,eAAgBA,GAAsB,UAAU,eAChD,UAAWA,GAAsB,UAAU,UAG3C,OAAQD,GAAc,OACtB,SAAUA,GAAc,QAAQ,UAAY,EAC5C,YAAaA,GAAc,QAAQ,aAAe,EAClD,gBAAiBA,GAAc,QAAQ,iBAAmB,CAC3D,CACD,CAKO,SAASG,GAA4B,CACrC,KAAA,CAAE,WAAAC,CAAW,EAAIhC,EAAU,EAE3BiC,EAAe3B,EAAA,YACpB,CACC4B,EACAC,IAEOH,EAAWE,CAAa,GAAKC,EAErC,CAACH,CAAU,CACZ,EAEMI,EAAc9B,EAAA,YAClB4B,GACO,CAAC,CAACF,EAAWE,CAAa,EAElC,CAACF,CAAU,CACZ,EAEO,MAAA,CACN,WAAAA,EACA,aAAAC,EACA,YAAAG,EAGA,gBAAiBA,EAAY,QAAQ,EACrC,gBAAiBA,EAAY,QAAQ,EACrC,gBAAiBA,EAAY,QAAQ,EACrC,oBAAqBA,EAAY,YAAY,EAC7C,oBAAqBA,EAAY,YAAY,EAC7C,qBAAsBA,EAAY,aAAa,EAC/C,gBAAiBA,EAAY,QAAQ,EACrC,eAAgBA,EAAY,OAAO,EACnC,cAAeA,EAAY,MAAM,EACjC,eAAgBA,EAAY,OAAO,CACpC,CACD,CAKO,SAASC,GAAsB,CAC/B,KAAA,CACL,cAAA5B,EACA,aAAAC,EACA,MAAA4B,EACA,eAAAC,EACA,OAAAC,EACA,SAAAC,GACGzC,EAAU,EAER0C,EAAW/B,EAAAA,QAAQ,IAAM,CAC9B,MAAM+B,EAAqB,CAAC,EAG5B,OACCH,GAAgB,WAAW,UAAU,GACrC,OAAO,OAAW,KAClB,OAAO,SAAS,WAAa,aAC7B,CAAC,OAAO,SAAS,SAAS,SAAS,WAAW,GAE9CG,EAAS,KAAK,sDAAsD,EAIpEF,GAAQ,WAAW,SAAS,GAC5B,OAAO,OAAW,KAClB,OAAO,SAAS,WAAa,UAE7BE,EAAS,KAAK,kCAAkC,EAG1CA,CAAA,EACL,CAACH,EAAgBC,CAAM,CAAC,EAEpB,MAAA,CACN,QAAS/B,EACT,OAAQC,EACR,SAAAgC,EACA,MAAAJ,EAGA,UAAW5B,EAAa,OAAS,EACjC,YAAagC,EAAS,OAAS,EAC/B,aAAc,CAACH,GAAgB,WAAW,UAAU,EACpD,WAAYA,GAAgB,WAAW,UAAU,EAGjD,uBAAwB,IAClBA,EACE,4CAA4C,KAAKA,CAAc,EAD1C,GAG7B,eAAgB,IAAM,CACjB,GAAA,CAACC,EAAe,MAAA,GAChB,GAAA,CACH,WAAI,IAAIA,CAAM,EACP,EAAA,MACA,CACA,MAAA,EAAA,CAET,EACA,iBAAkB,IACV,CAAC,WAAY,WAAY,UAAU,EAAE,SAASC,CAAQ,CAE/D,CACD"}