@cedros/login-react 0.0.14 → 0.0.15

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.
Files changed (70) hide show
  1. package/dist/{AuthenticationSettings-D739nNul.cjs → AuthenticationSettings-CjGGqbcS.cjs} +1 -1
  2. package/dist/{AuthenticationSettings-D739nNul.cjs.map → AuthenticationSettings-CjGGqbcS.cjs.map} +1 -1
  3. package/dist/{AuthenticationSettings-Dx3JCI3m.js → AuthenticationSettings-DGWktSVw.js} +1 -1
  4. package/dist/{AuthenticationSettings-Dx3JCI3m.js.map → AuthenticationSettings-DGWktSVw.js.map} +1 -1
  5. package/dist/{AuthenticationSettings-vowmQPXz.js → AuthenticationSettings-Dg6ATgOl.js} +2 -2
  6. package/dist/{AuthenticationSettings-vowmQPXz.js.map → AuthenticationSettings-Dg6ATgOl.js.map} +1 -1
  7. package/dist/{AuthenticationSettings-DtLoxQ2z.cjs → AuthenticationSettings-HhrUAmM6.cjs} +1 -1
  8. package/dist/{AuthenticationSettings-DtLoxQ2z.cjs.map → AuthenticationSettings-HhrUAmM6.cjs.map} +1 -1
  9. package/dist/AutosaveStatus-BDWxAg4U.cjs +1 -0
  10. package/dist/AutosaveStatus-BDWxAg4U.cjs.map +1 -0
  11. package/dist/{AutosaveStatus-Ciyt350A.js → AutosaveStatus-DeViUyyI.js} +0 -6
  12. package/dist/AutosaveStatus-DeViUyyI.js.map +1 -0
  13. package/dist/{CreditSystemSettings-C6dUsu72.cjs → CreditSystemSettings-BykhytcS.cjs} +1 -1
  14. package/dist/{CreditSystemSettings-C6dUsu72.cjs.map → CreditSystemSettings-BykhytcS.cjs.map} +1 -1
  15. package/dist/{CreditSystemSettings-bVuNLsqp.js → CreditSystemSettings-CSlsQynZ.js} +1 -1
  16. package/dist/{CreditSystemSettings-bVuNLsqp.js.map → CreditSystemSettings-CSlsQynZ.js.map} +1 -1
  17. package/dist/{CreditSystemSettings-CBot8EPW.cjs → CreditSystemSettings-CyFQbXMh.cjs} +1 -1
  18. package/dist/{CreditSystemSettings-CBot8EPW.cjs.map → CreditSystemSettings-CyFQbXMh.cjs.map} +1 -1
  19. package/dist/{CreditSystemSettings-BQ3h4CyM.js → CreditSystemSettings-DBr7QS59.js} +1 -1
  20. package/dist/{CreditSystemSettings-BQ3h4CyM.js.map → CreditSystemSettings-DBr7QS59.js.map} +1 -1
  21. package/dist/{EmailSettings-B9qwPSiM.cjs → EmailSettings-Bup2rCgU.cjs} +1 -1
  22. package/dist/{EmailSettings-B9qwPSiM.cjs.map → EmailSettings-Bup2rCgU.cjs.map} +1 -1
  23. package/dist/{EmailSettings-mxlKNcPl.js → EmailSettings-C04qdJCz.js} +1 -1
  24. package/dist/{EmailSettings-mxlKNcPl.js.map → EmailSettings-C04qdJCz.js.map} +1 -1
  25. package/dist/{EmailSettings-RbgAq9FB.cjs → EmailSettings-C0Ss6Cne.cjs} +1 -1
  26. package/dist/{EmailSettings-RbgAq9FB.cjs.map → EmailSettings-C0Ss6Cne.cjs.map} +1 -1
  27. package/dist/{EmailSettings-CCA8dNCi.js → EmailSettings-DAqH_xum.js} +1 -1
  28. package/dist/{EmailSettings-CCA8dNCi.js.map → EmailSettings-DAqH_xum.js.map} +1 -1
  29. package/dist/{EmbeddedWalletSettings-B4h-8rxB.cjs → EmbeddedWalletSettings-B0XkNuPR.cjs} +1 -1
  30. package/dist/{EmbeddedWalletSettings-B4h-8rxB.cjs.map → EmbeddedWalletSettings-B0XkNuPR.cjs.map} +1 -1
  31. package/dist/{EmbeddedWalletSettings-CXlZFFDw.js → EmbeddedWalletSettings-DDFQhQOw.js} +1 -1
  32. package/dist/{EmbeddedWalletSettings-CXlZFFDw.js.map → EmbeddedWalletSettings-DDFQhQOw.js.map} +1 -1
  33. package/dist/{EmbeddedWalletSettings-BInZvFZf.js → EmbeddedWalletSettings-DYh884HP.js} +1 -1
  34. package/dist/{EmbeddedWalletSettings-BInZvFZf.js.map → EmbeddedWalletSettings-DYh884HP.js.map} +1 -1
  35. package/dist/{EmbeddedWalletSettings-D5JXae1L.cjs → EmbeddedWalletSettings-YX0Dk_b_.cjs} +1 -1
  36. package/dist/{EmbeddedWalletSettings-D5JXae1L.cjs.map → EmbeddedWalletSettings-YX0Dk_b_.cjs.map} +1 -1
  37. package/dist/{ServerSettings-CYTlQ2xy.cjs → ServerSettings-CInJe4jY.cjs} +1 -1
  38. package/dist/{ServerSettings-CYTlQ2xy.cjs.map → ServerSettings-CInJe4jY.cjs.map} +1 -1
  39. package/dist/{ServerSettings-DFs9jQ3f.cjs → ServerSettings-CwnEI-PC.cjs} +1 -1
  40. package/dist/{ServerSettings-DFs9jQ3f.cjs.map → ServerSettings-CwnEI-PC.cjs.map} +1 -1
  41. package/dist/{ServerSettings-pSmWDC1d.js → ServerSettings-DVEtfDQo.js} +1 -1
  42. package/dist/{ServerSettings-pSmWDC1d.js.map → ServerSettings-DVEtfDQo.js.map} +1 -1
  43. package/dist/{ServerSettings-BE8fsE5k.js → ServerSettings-DakhpYcO.js} +1 -1
  44. package/dist/{ServerSettings-BE8fsE5k.js.map → ServerSettings-DakhpYcO.js.map} +1 -1
  45. package/dist/{SettingsPageLayout-j5lMjEID.cjs → SettingsPageLayout-C6DWgyXS.cjs} +1 -1
  46. package/dist/{SettingsPageLayout-j5lMjEID.cjs.map → SettingsPageLayout-C6DWgyXS.cjs.map} +1 -1
  47. package/dist/{SettingsPageLayout--GZ_iHLc.js → SettingsPageLayout-CLJI6hFQ.js} +1 -1
  48. package/dist/{SettingsPageLayout--GZ_iHLc.js.map → SettingsPageLayout-CLJI6hFQ.js.map} +1 -1
  49. package/dist/{WebhookSettings-CGyDKjrm.cjs → WebhookSettings-BMeykdRP.cjs} +1 -1
  50. package/dist/{WebhookSettings-CGyDKjrm.cjs.map → WebhookSettings-BMeykdRP.cjs.map} +1 -1
  51. package/dist/{WebhookSettings-C-gvNAW1.cjs → WebhookSettings-BNVooF0B.cjs} +1 -1
  52. package/dist/{WebhookSettings-C-gvNAW1.cjs.map → WebhookSettings-BNVooF0B.cjs.map} +1 -1
  53. package/dist/{WebhookSettings-kIstSjZi.js → WebhookSettings-DXeDYhAe.js} +1 -1
  54. package/dist/{WebhookSettings-kIstSjZi.js.map → WebhookSettings-DXeDYhAe.js.map} +1 -1
  55. package/dist/{WebhookSettings-Bb70MbFj.js → WebhookSettings-DdbxNPZ9.js} +1 -1
  56. package/dist/{WebhookSettings-Bb70MbFj.js.map → WebhookSettings-DdbxNPZ9.js.map} +1 -1
  57. package/dist/admin-only.cjs +1 -1
  58. package/dist/admin-only.js +1 -1
  59. package/dist/index.cjs +8 -8
  60. package/dist/index.cjs.map +1 -1
  61. package/dist/index.js +10 -16
  62. package/dist/index.js.map +1 -1
  63. package/dist/{plugin-D1NdppqC.js → plugin-CW_ycXye.js} +1 -1
  64. package/dist/{plugin-D1NdppqC.js.map → plugin-CW_ycXye.js.map} +1 -1
  65. package/dist/{plugin-8_dpq7tC.cjs → plugin-CnbFRy5o.cjs} +1 -1
  66. package/dist/{plugin-8_dpq7tC.cjs.map → plugin-CnbFRy5o.cjs.map} +1 -1
  67. package/package.json +1 -1
  68. package/dist/AutosaveStatus-CCrZszKA.cjs +0 -1
  69. package/dist/AutosaveStatus-CCrZszKA.cjs.map +0 -1
  70. package/dist/AutosaveStatus-Ciyt350A.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-8_dpq7tC.cjs","sources":["../src/components/admin/ProfileDropdown.tsx","../src/admin/AdminShell.tsx","../src/admin/icons.tsx","../src/admin/plugin.tsx"],"sourcesContent":["/**\n * Profile Dropdown Component\n *\n * Displays user avatar/name with a dropdown menu for settings and logout.\n */\n\nimport { useState, useRef, useEffect, useCallback } from 'react';\n\nexport interface ProfileDropdownProps {\n /** User's display name */\n name?: string;\n /** User's email */\n email?: string;\n /** User's profile picture URL */\n picture?: string;\n /** Callback when Settings is clicked */\n onSettings?: () => void;\n /** Callback when Logout is clicked */\n onLogout?: () => void;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * Profile dropdown button with settings and logout options.\n *\n * @example\n * ```tsx\n * <ProfileDropdown\n * name={user.name}\n * email={user.email}\n * picture={user.picture}\n * onSettings={() => navigate('/settings')}\n * onLogout={logout}\n * />\n * ```\n */\nexport function ProfileDropdown({\n name,\n email,\n picture,\n onSettings,\n onLogout,\n className = '',\n}: ProfileDropdownProps) {\n const [isOpen, setIsOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n // Close dropdown on escape key\n useEffect(() => {\n function handleEscape(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n setIsOpen(false);\n }\n }\n\n if (isOpen) {\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }\n }, [isOpen]);\n\n const handleSettings = useCallback(() => {\n setIsOpen(false);\n onSettings?.();\n }, [onSettings]);\n\n const handleLogout = useCallback(() => {\n setIsOpen(false);\n onLogout?.();\n }, [onLogout]);\n\n const displayName = name || 'User';\n const initial = (name?.[0] || email?.[0] || '?').toUpperCase();\n\n return (\n <div className={`cedros-profile-dropdown ${className}`} ref={dropdownRef}>\n <button\n type=\"button\"\n className=\"cedros-profile-dropdown__trigger\"\n onClick={() => setIsOpen(!isOpen)}\n aria-expanded={isOpen}\n aria-haspopup=\"menu\"\n >\n <div className=\"cedros-profile-dropdown__avatar\">\n {picture ? (\n <img\n src={picture}\n alt={displayName}\n className=\"cedros-profile-dropdown__avatar-img\"\n referrerPolicy=\"no-referrer\"\n />\n ) : (\n <span className=\"cedros-profile-dropdown__avatar-placeholder\">{initial}</span>\n )}\n </div>\n <div className=\"cedros-profile-dropdown__info\">\n <span className=\"cedros-profile-dropdown__name\">{displayName}</span>\n {email && <span className=\"cedros-profile-dropdown__email\">{email}</span>}\n </div>\n <svg\n className={`cedros-profile-dropdown__chevron ${isOpen ? 'cedros-profile-dropdown__chevron--open' : ''}`}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n\n {isOpen && (\n <div className=\"cedros-profile-dropdown__menu\" role=\"menu\">\n {onSettings && (\n <button\n type=\"button\"\n className=\"cedros-profile-dropdown__item\"\n onClick={handleSettings}\n role=\"menuitem\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n Settings\n </button>\n )}\n {onLogout && (\n <button\n type=\"button\"\n className=\"cedros-profile-dropdown__item cedros-profile-dropdown__item--danger\"\n onClick={handleLogout}\n role=\"menuitem\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\" />\n <polyline points=\"16 17 21 12 16 7\" />\n <line x1=\"21\" x2=\"9\" y1=\"12\" y2=\"12\" />\n </svg>\n Log out\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * AdminShell - Unified Admin Dashboard Host\n *\n * A shell component that hosts admin plugins from cedros-login, cedros-pay,\n * or any compatible plugin. Provides unified sidebar navigation and content area.\n *\n * @example\n * ```tsx\n * import { AdminShell } from '@cedros/login-react';\n * import { cedrosLoginPlugin } from '@cedros/login-react';\n * import { cedrosPayPlugin } from '@cedros/pay-react';\n *\n * function AdminPage() {\n * const hostContext = useBuildHostContext();\n * return (\n * <AdminShell\n * plugins={[cedrosLoginPlugin, cedrosPayPlugin]}\n * hostContext={hostContext}\n * />\n * );\n * }\n * ```\n */\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useMemo,\n useEffect,\n Suspense,\n type ReactNode,\n} from 'react';\nimport type {\n AdminPlugin,\n PluginRegistry,\n HostContext,\n QualifiedSectionId,\n PluginContext,\n ResolvedSection,\n} from './types';\nimport { LoadingSpinner } from '../components/shared/LoadingSpinner';\nimport { ProfileDropdown } from '../components/admin/ProfileDropdown';\nimport { CedrosLoginContext, type CedrosLoginContextValue } from '../context/CedrosLoginContext';\nimport type { AuthUser } from '../types';\n\n// ============================================================================\n// Plugin Registry Implementation\n// ============================================================================\n\nclass PluginRegistryImpl implements PluginRegistry {\n private plugins = new Map<string, AdminPlugin>();\n private listeners = new Set<(plugins: AdminPlugin[]) => void>();\n\n register(plugin: AdminPlugin): void {\n if (this.plugins.has(plugin.id)) {\n console.warn(`Plugin ${plugin.id} already registered, replacing...`);\n }\n this.plugins.set(plugin.id, plugin);\n plugin.onRegister?.(this);\n this.notify();\n }\n\n unregister(pluginId: string): void {\n const plugin = this.plugins.get(pluginId);\n if (plugin) {\n plugin.onUnregister?.();\n this.plugins.delete(pluginId);\n this.notify();\n }\n }\n\n get(pluginId: string): AdminPlugin | undefined {\n return this.plugins.get(pluginId);\n }\n\n getAll(): AdminPlugin[] {\n return Array.from(this.plugins.values());\n }\n\n subscribe(listener: (plugins: AdminPlugin[]) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notify(): void {\n const plugins = this.getAll();\n this.listeners.forEach((listener) => listener(plugins));\n }\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface AdminShellContextValue {\n registry: PluginRegistry;\n hostContext: HostContext;\n activeSection: QualifiedSectionId | null;\n setActiveSection: (section: QualifiedSectionId) => void;\n getPluginContext: (pluginId: string) => PluginContext | null;\n}\n\nconst AdminShellContext = createContext<AdminShellContextValue | null>(null);\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useAdminShell(): AdminShellContextValue {\n const ctx = useContext(AdminShellContext);\n if (!ctx) throw new Error('useAdminShell must be used within AdminShell');\n return ctx;\n}\n\n// ============================================================================\n// Props\n// ============================================================================\n\nexport interface AdminShellProps {\n /** Dashboard title */\n title?: string;\n /** Plugins to load */\n plugins?: AdminPlugin[];\n /** Host context from parent providers */\n hostContext: HostContext;\n /** Default active section (qualified ID) */\n defaultSection?: QualifiedSectionId;\n /** Page size for lists */\n pageSize?: number;\n /** Refresh interval in ms (0 to disable) */\n refreshInterval?: number;\n /** Callback when section changes */\n onSectionChange?: (section: QualifiedSectionId) => void;\n /** Custom logo/header content */\n logo?: ReactNode;\n /** Additional sidebar footer content */\n sidebarFooter?: ReactNode;\n /** Callback when user clicks Settings in profile dropdown */\n onSettingsClick?: () => void;\n /** Callback when user clicks Logout in profile dropdown */\n onLogoutClick?: () => void;\n /** Additional CSS class */\n className?: string;\n}\n\n// ============================================================================\n// Group Order Helpers\n// ============================================================================\n\n/** Build a group-label → order map from all registered plugins' groups[] config. */\nfunction buildGroupOrder(plugins: AdminPlugin[]): Map<string, number> {\n const order = new Map<string, number>();\n for (const plugin of plugins) {\n for (const group of plugin.groups ?? []) {\n // Key by label (sections reference groups by display name via section.group).\n // First plugin to declare a group wins; later plugins don't override.\n if (!order.has(group.label)) {\n order.set(group.label, group.order);\n }\n }\n }\n return order;\n}\n\n// ============================================================================\n// AdminShell Component\n// ============================================================================\n\nexport function AdminShell({\n title = 'Admin',\n plugins: initialPlugins = [],\n hostContext,\n defaultSection,\n pageSize = 20,\n refreshInterval = 0,\n onSectionChange,\n logo,\n sidebarFooter,\n onSettingsClick,\n onLogoutClick,\n className = '',\n}: AdminShellProps): React.JSX.Element {\n // Plugin registry\n const [registry] = useState(() => {\n const reg = new PluginRegistryImpl();\n initialPlugins.forEach((p) => reg.register(p));\n return reg;\n });\n\n // Track registered plugins for re-renders\n const [registeredPlugins, setRegisteredPlugins] = useState<AdminPlugin[]>(() =>\n registry.getAll()\n );\n\n useEffect(() => {\n return registry.subscribe(setRegisteredPlugins);\n }, [registry]);\n\n // Aggregate sections from all plugins\n const allSections = useMemo(() => {\n return registeredPlugins.flatMap((plugin) =>\n plugin.sections\n .filter((section) => {\n // Check RBAC permissions (role-based)\n if (section.requiredPermission) {\n if (!plugin.checkPermission(section.requiredPermission, hostContext)) {\n return false;\n }\n }\n // Check dashboard section permissions (owner-configured per role)\n if (hostContext.dashboardPermissions) {\n if (!hostContext.dashboardPermissions.canAccess(section.id)) {\n return false;\n }\n }\n return true;\n })\n .map(\n (section): ResolvedSection => ({\n ...section,\n qualifiedId: `${plugin.id}:${section.id}` as QualifiedSectionId,\n pluginId: plugin.id,\n cssNamespace: plugin.cssNamespace,\n })\n )\n );\n }, [registeredPlugins, hostContext]);\n\n // Active section state\n const [activeSection, setActiveSectionInternal] = useState<QualifiedSectionId | null>(\n () => defaultSection ?? allSections[0]?.qualifiedId ?? null\n );\n\n // Collapsible groups state\n const [collapsedGroups, setCollapsedGroups] = useState<Set<string>>(new Set());\n\n const toggleGroup = useCallback((groupName: string) => {\n setCollapsedGroups((prev) => {\n const next = new Set(prev);\n if (next.has(groupName)) {\n next.delete(groupName);\n } else {\n next.add(groupName);\n }\n return next;\n });\n }, []);\n\n // Update active section when sections change and current is invalid\n useEffect(() => {\n if (activeSection && !allSections.find((s) => s.qualifiedId === activeSection)) {\n setActiveSectionInternal(allSections[0]?.qualifiedId ?? null);\n }\n }, [allSections, activeSection]);\n\n const setActiveSection = useCallback(\n (section: QualifiedSectionId) => {\n setActiveSectionInternal(section);\n onSectionChange?.(section);\n },\n [onSectionChange]\n );\n\n // Plugin context factory\n const getPluginContext = useCallback(\n (pluginId: string): PluginContext | null => {\n const plugin = registry.get(pluginId);\n if (!plugin) return null;\n return plugin.createPluginContext(hostContext);\n },\n [registry, hostContext]\n );\n\n // Group sections by group name, sorted by plugin-defined group order\n const groupedSections = useMemo(() => {\n const groupOrder = buildGroupOrder(registeredPlugins);\n const groups = new Map<string, ResolvedSection[]>();\n\n allSections.forEach((section) => {\n const groupName = section.group ?? 'Menu';\n const existing = groups.get(groupName) ?? [];\n groups.set(groupName, [...existing, section]);\n });\n\n // Sort groups by plugin-defined order (undeclared groups sink to bottom)\n const sortedGroups = Array.from(groups.entries()).sort(([a], [b]) => {\n const orderA = groupOrder.get(a) ?? 99;\n const orderB = groupOrder.get(b) ?? 99;\n return orderA - orderB;\n });\n\n return sortedGroups;\n }, [allSections, registeredPlugins]);\n\n // Get current section's component\n const currentSection = useMemo(() => {\n if (!activeSection) return null;\n const [pluginId, sectionId] = activeSection.split(':') as [string, string];\n const plugin = registry.get(pluginId);\n if (!plugin) return null;\n const Component = plugin.components[sectionId];\n if (!Component) return null;\n const pluginContext = plugin.createPluginContext(hostContext);\n return { Component, pluginContext, plugin };\n }, [activeSection, registry, hostContext]);\n\n // Context value\n const contextValue = useMemo<AdminShellContextValue>(\n () => ({\n registry,\n hostContext,\n activeSection,\n setActiveSection,\n getPluginContext,\n }),\n [registry, hostContext, activeSection, setActiveSection, getPluginContext]\n );\n\n // Bridge hostContext.cedrosLogin into CedrosLoginContext so hooks\n // (useOrgs, useAdminDeposits, etc.) work inside AdminShell sections.\n const cedrosLoginContextValue = useMemo<CedrosLoginContextValue | null>(() => {\n const cl = hostContext.cedrosLogin;\n if (!cl) return null;\n const user: AuthUser | null = cl.user\n ? { authMethods: [], emailVerified: false, createdAt: '', updatedAt: '', ...cl.user }\n : null;\n return {\n config: { serverUrl: cl.serverUrl },\n user,\n authState: cl.user ? 'authenticated' : 'unauthenticated',\n error: null,\n logout: async () => {},\n refreshUser: async () => {},\n isModalOpen: false,\n openModal: () => {},\n closeModal: () => {},\n _internal: {\n handleLoginSuccess: () => {},\n getAccessToken: cl.getAccessToken,\n },\n };\n }, [hostContext.cedrosLogin]);\n\n return (\n <AdminShellContext.Provider value={contextValue}>\n <CedrosLoginContext.Provider value={cedrosLoginContextValue}>\n <div className={`cedros-admin cedros-admin-shell ${className || ''}`}>\n {/* Sidebar */}\n <aside className=\"cedros-admin-shell__sidebar\">\n <div className=\"cedros-admin-shell__sidebar-header\">\n {logo ?? (\n <div className=\"cedros-admin-shell__logo\">\n <span className=\"cedros-admin-shell__logo-text\">{title}</span>\n </div>\n )}\n </div>\n\n <nav className=\"cedros-admin-shell__nav\">\n {groupedSections.map(([groupName, sections]) => {\n const isCollapsible = groupName === 'Configuration';\n const isCollapsed = collapsedGroups.has(groupName);\n\n return (\n <div key={groupName} className=\"cedros-admin-shell__nav-group\">\n {isCollapsible ? (\n <button\n type=\"button\"\n className=\"cedros-admin-shell__nav-label cedros-admin-shell__nav-label--collapsible\"\n onClick={() => toggleGroup(groupName)}\n aria-expanded={!isCollapsed}\n >\n <span>{groupName}</span>\n <span\n className={`cedros-admin-shell__nav-chevron ${!isCollapsed ? 'cedros-admin-shell__nav-chevron--expanded' : ''}`}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </span>\n </button>\n ) : (\n <span className=\"cedros-admin-shell__nav-label\">{groupName}</span>\n )}\n {(!isCollapsible || !isCollapsed) &&\n sections\n .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))\n .map((section) => (\n <button\n key={section.qualifiedId}\n type=\"button\"\n className={`cedros-admin-shell__nav-item ${\n activeSection === section.qualifiedId\n ? 'cedros-admin-shell__nav-item--active'\n : ''\n }`}\n onClick={() => setActiveSection(section.qualifiedId)}\n aria-current={\n activeSection === section.qualifiedId ? 'page' : undefined\n }\n >\n <span className=\"cedros-admin-shell__nav-icon\">{section.icon}</span>\n <span className=\"cedros-admin-shell__nav-text\">{section.label}</span>\n {section.badge && (\n <span className=\"cedros-admin-shell__nav-badge\">{section.badge}</span>\n )}\n </button>\n ))}\n </div>\n );\n })}\n </nav>\n\n {/* User profile dropdown + optional custom footer */}\n {(hostContext.cedrosLogin?.user || sidebarFooter) && (\n <div className=\"cedros-admin-shell__sidebar-footer\">\n {hostContext.cedrosLogin?.user && (\n <ProfileDropdown\n name={hostContext.cedrosLogin.user.name}\n email={hostContext.cedrosLogin.user.email}\n picture={hostContext.cedrosLogin.user.picture}\n onSettings={onSettingsClick}\n onLogout={onLogoutClick}\n />\n )}\n {sidebarFooter}\n </div>\n )}\n </aside>\n\n {/* Main Content */}\n <main className=\"cedros-admin-shell__main\">\n {currentSection ? (\n <Suspense fallback={<LoadingFallback />}>\n <div\n className=\"cedros-admin-shell__section\"\n data-plugin-namespace={currentSection.plugin.cssNamespace}\n >\n <currentSection.Component\n pluginContext={currentSection.pluginContext}\n pageSize={pageSize}\n refreshInterval={refreshInterval}\n />\n </div>\n </Suspense>\n ) : (\n <div className=\"cedros-admin-shell__empty\">\n {allSections.length === 0\n ? 'No plugins loaded'\n : 'Select a section from the sidebar'}\n </div>\n )}\n </main>\n </div>\n </CedrosLoginContext.Provider>\n </AdminShellContext.Provider>\n );\n}\n\n// ============================================================================\n// Helper Components\n// ============================================================================\n\nfunction LoadingFallback(): React.JSX.Element {\n return (\n <div className=\"cedros-admin-shell__loading\">\n <LoadingSpinner />\n <span>Loading...</span>\n </div>\n );\n}\n","/**\n * Admin Dashboard Icons\n *\n * SVG icons for the admin dashboard sidebar and sections.\n * Lucide-style, 24x24 viewBox rendered at 16x16.\n */\n\nimport type { ReactNode } from 'react';\n\nconst iconProps = {\n width: '16',\n height: '16',\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: '2',\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n};\n\nexport const Icons: Record<string, ReactNode> = {\n users: (\n <svg {...iconProps}>\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n ),\n\n members: (\n <svg {...iconProps}>\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n ),\n\n invites: (\n <svg {...iconProps}>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n ),\n\n deposits: (\n <svg {...iconProps}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8\" />\n <path d=\"M12 18V6\" />\n </svg>\n ),\n\n withdrawals: (\n <svg {...iconProps}>\n <rect width=\"16\" height=\"20\" x=\"4\" y=\"2\" rx=\"2\" ry=\"2\" />\n <path d=\"M9 22v-4h6v4\" />\n <path d=\"M8 6h.01\" />\n <path d=\"M16 6h.01\" />\n <path d=\"M12 6h.01\" />\n <path d=\"M12 10h.01\" />\n <path d=\"M12 14h.01\" />\n <path d=\"M16 10h.01\" />\n <path d=\"M16 14h.01\" />\n <path d=\"M8 10h.01\" />\n <path d=\"M8 14h.01\" />\n </svg>\n ),\n\n settings: (\n <svg {...iconProps}>\n <path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n ),\n\n wallet: (\n <svg {...iconProps}>\n <path d=\"M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1\" />\n <path d=\"M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4\" />\n </svg>\n ),\n\n chevronRight: (\n <svg {...iconProps}>\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n ),\n\n // Settings sub-page icons\n key: (\n <svg {...iconProps}>\n <path d=\"M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4\" />\n </svg>\n ),\n\n toggles: (\n <svg {...iconProps}>\n <rect width=\"20\" height=\"12\" x=\"2\" y=\"6\" rx=\"6\" />\n <circle cx=\"8\" cy=\"12\" r=\"2\" />\n </svg>\n ),\n\n shield: (\n <svg {...iconProps}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n </svg>\n ),\n\n mail: (\n <svg {...iconProps}>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n ),\n\n webhook: (\n <svg {...iconProps}>\n <path d=\"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2\" />\n <path d=\"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06\" />\n <path d=\"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8\" />\n </svg>\n ),\n\n coins: (\n <svg {...iconProps}>\n <circle cx=\"8\" cy=\"8\" r=\"6\" />\n <path d=\"M18.09 10.37A6 6 0 1 1 10.34 18\" />\n <path d=\"M7 6h1v4\" />\n <path d=\"m16.71 13.88.7.71-2.82 2.82\" />\n </svg>\n ),\n\n server: (\n <svg {...iconProps}>\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\" ry=\"2\" />\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\" ry=\"2\" />\n <line x1=\"6\" x2=\"6.01\" y1=\"6\" y2=\"6\" />\n <line x1=\"6\" x2=\"6.01\" y1=\"18\" y2=\"18\" />\n </svg>\n ),\n};\n","/**\n * Cedros Login Admin Plugin\n *\n * Exports the cedrosLoginPlugin for use with AdminShell.\n * Provides user management, deposits, withdrawals, and configuration sections.\n */\n\nimport { lazy } from 'react';\nimport type { AdminPlugin, HostContext, PluginContext, AdminSectionConfig } from './types';\nimport { Icons } from './icons';\n\n// ============================================================================\n// Lazy-loaded Section Components\n// ============================================================================\n\nconst UsersSection = lazy(() => import('./sections/UsersSection'));\nconst TeamSection = lazy(() => import('./sections/TeamSection'));\nconst DepositsSection = lazy(() => import('./sections/DepositsSection'));\nconst WithdrawalsSection = lazy(() => import('./sections/WithdrawalsSection'));\nconst AuthenticationSettings = lazy(() => import('./sections/AuthenticationSettings'));\nconst EmbeddedWalletSettings = lazy(() => import('./sections/EmbeddedWalletSettings'));\nconst EmailSettings = lazy(() => import('./sections/EmailSettings'));\nconst WebhookSettings = lazy(() => import('./sections/WebhookSettings'));\nconst CreditSystemSettings = lazy(() => import('./sections/CreditSystemSettings'));\nconst ServerSettings = lazy(() => import('./sections/ServerSettings'));\n\n// ============================================================================\n// Permission Mapping\n// ============================================================================\n\ntype LoginPermission =\n | 'login:users:read'\n | 'login:users:write'\n | 'login:members:read'\n | 'login:members:write'\n | 'login:invites:read'\n | 'login:invites:write'\n | 'login:deposits:read'\n | 'login:deposits:write'\n | 'login:settings:read'\n | 'login:settings:write';\n\n/**\n * Maps plugin permissions to org-level permissions/roles.\n */\nconst PERMISSION_MAP: Record<LoginPermission, string[]> = {\n 'login:users:read': ['admin', 'owner'],\n 'login:users:write': ['admin', 'owner'],\n 'login:members:read': ['member:read', 'admin', 'owner'],\n 'login:members:write': ['member:remove', 'member:role_change'],\n 'login:invites:read': ['invite:read', 'admin', 'owner'],\n 'login:invites:write': ['invite:create', 'invite:cancel'],\n 'login:deposits:read': ['admin', 'owner'],\n 'login:deposits:write': ['admin', 'owner'],\n 'login:settings:read': ['admin', 'owner'],\n 'login:settings:write': ['admin', 'owner'],\n};\n\n// ============================================================================\n// Section Configuration\n// ============================================================================\n\nconst SECTIONS: AdminSectionConfig[] = [\n // Users group (main sections)\n {\n id: 'users',\n label: 'Users',\n icon: Icons.users,\n group: 'Users',\n order: 0,\n requiredPermission: 'login:users:read',\n },\n {\n id: 'team',\n label: 'Team',\n icon: Icons.members,\n group: 'Users',\n order: 1,\n requiredPermission: 'login:members:read',\n },\n {\n id: 'deposits',\n label: 'Deposits',\n icon: Icons.deposits,\n group: 'Users',\n order: 2,\n requiredPermission: 'login:deposits:read',\n },\n {\n id: 'withdrawals',\n label: 'Withdrawals',\n icon: Icons.withdrawals,\n group: 'Users',\n order: 3,\n requiredPermission: 'login:deposits:read',\n },\n\n // Configuration group (settings sections)\n {\n id: 'settings-auth',\n label: 'Authentication',\n icon: Icons.key,\n group: 'Configuration',\n order: 0,\n requiredPermission: 'login:settings:read',\n },\n {\n id: 'settings-email',\n label: 'Email & SMTP',\n icon: Icons.mail,\n group: 'Configuration',\n order: 1,\n requiredPermission: 'login:settings:read',\n },\n {\n id: 'settings-webhooks',\n label: 'Webhooks',\n icon: Icons.webhook,\n group: 'Configuration',\n order: 2,\n requiredPermission: 'login:settings:read',\n },\n {\n id: 'settings-wallet',\n label: 'User Wallets',\n icon: Icons.wallet,\n group: 'Configuration',\n order: 3,\n requiredPermission: 'login:settings:read',\n },\n {\n id: 'settings-credits',\n label: 'Credit System',\n icon: Icons.coins,\n group: 'Configuration',\n order: 4,\n requiredPermission: 'login:settings:read',\n },\n {\n id: 'settings-server',\n label: 'Auth Server',\n icon: Icons.server,\n group: 'Configuration',\n order: 5,\n requiredPermission: 'login:settings:read',\n },\n];\n\n// ============================================================================\n// Plugin Definition\n// ============================================================================\n\nexport const cedrosLoginPlugin: AdminPlugin = {\n id: 'cedros-login',\n name: 'Cedros Login',\n version: '1.0.0',\n\n sections: SECTIONS,\n\n groups: [\n { id: 'users', label: 'Users', order: 0 },\n { id: 'configuration', label: 'Configuration', order: 2 },\n ],\n\n components: {\n users: UsersSection,\n team: TeamSection,\n deposits: DepositsSection,\n withdrawals: WithdrawalsSection,\n 'settings-auth': AuthenticationSettings,\n 'settings-wallet': EmbeddedWalletSettings,\n 'settings-email': EmailSettings,\n 'settings-webhooks': WebhookSettings,\n 'settings-credits': CreditSystemSettings,\n 'settings-server': ServerSettings,\n },\n\n createPluginContext(hostContext: HostContext): PluginContext {\n const cedrosLogin = hostContext.cedrosLogin;\n if (!cedrosLogin) {\n throw new Error('cedros-login plugin requires cedrosLogin in hostContext');\n }\n\n return {\n serverUrl: cedrosLogin.serverUrl,\n userId: cedrosLogin.user?.id,\n getAccessToken: cedrosLogin.getAccessToken,\n hasPermission: (permission) => this.checkPermission(permission, hostContext),\n orgId: hostContext.org?.orgId,\n pluginData: {\n user: cedrosLogin.user,\n orgRole: hostContext.org?.role,\n },\n };\n },\n\n checkPermission(permission: string, hostContext: HostContext): boolean {\n const org = hostContext.org;\n\n // No org context = admin-level access (for global admins)\n if (!org) {\n // Check if user is in cedrosLogin context - assume admin if present\n return Boolean(hostContext.cedrosLogin?.user);\n }\n\n const requiredPerms = PERMISSION_MAP[permission as LoginPermission];\n if (!requiredPerms) {\n // Unknown permission - default deny\n return false;\n }\n\n // Check if user has any of the required permissions\n return requiredPerms.some(\n (p) =>\n org.permissions.includes(p) ||\n p === org.role ||\n (p === 'admin' && ['admin', 'owner'].includes(org.role)) ||\n (p === 'owner' && org.role === 'owner')\n );\n },\n\n cssNamespace: 'cedros-dashboard',\n};\n\n// Named export for convenience\nexport { cedrosLoginPlugin as loginPlugin };\n"],"names":["ProfileDropdown","name","email","picture","onSettings","onLogout","className","isOpen","setIsOpen","useState","dropdownRef","useRef","useEffect","handleClickOutside","event","handleEscape","handleSettings","useCallback","handleLogout","displayName","initial","jsxs","jsx","PluginRegistryImpl","plugin","pluginId","listener","plugins","AdminShellContext","createContext","useAdminShell","ctx","useContext","buildGroupOrder","order","group","AdminShell","title","initialPlugins","hostContext","defaultSection","pageSize","refreshInterval","onSectionChange","logo","sidebarFooter","onSettingsClick","onLogoutClick","registry","reg","p","registeredPlugins","setRegisteredPlugins","allSections","useMemo","section","activeSection","setActiveSectionInternal","collapsedGroups","setCollapsedGroups","toggleGroup","groupName","prev","next","setActiveSection","getPluginContext","groupedSections","groupOrder","groups","existing","a","b","orderA","orderB","currentSection","sectionId","Component","pluginContext","contextValue","cedrosLoginContextValue","cl","user","CedrosLoginContext","sections","isCollapsible","isCollapsed","Suspense","LoadingFallback","LoadingSpinner","iconProps","Icons","UsersSection","lazy","TeamSection","DepositsSection","WithdrawalsSection","AuthenticationSettings","EmbeddedWalletSettings","EmailSettings","WebhookSettings","CreditSystemSettings","ServerSettings","PERMISSION_MAP","SECTIONS","cedrosLoginPlugin","cedrosLogin","permission","org","requiredPerms"],"mappings":"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"}
1
+ {"version":3,"file":"plugin-CnbFRy5o.cjs","sources":["../src/components/admin/ProfileDropdown.tsx","../src/admin/AdminShell.tsx","../src/admin/icons.tsx","../src/admin/plugin.tsx"],"sourcesContent":["/**\n * Profile Dropdown Component\n *\n * Displays user avatar/name with a dropdown menu for settings and logout.\n */\n\nimport { useState, useRef, useEffect, useCallback } from 'react';\n\nexport interface ProfileDropdownProps {\n /** User's display name */\n name?: string;\n /** User's email */\n email?: string;\n /** User's profile picture URL */\n picture?: string;\n /** Callback when Settings is clicked */\n onSettings?: () => void;\n /** Callback when Logout is clicked */\n onLogout?: () => void;\n /** Additional CSS class */\n className?: string;\n}\n\n/**\n * Profile dropdown button with settings and logout options.\n *\n * @example\n * ```tsx\n * <ProfileDropdown\n * name={user.name}\n * email={user.email}\n * picture={user.picture}\n * onSettings={() => navigate('/settings')}\n * onLogout={logout}\n * />\n * ```\n */\nexport function ProfileDropdown({\n name,\n email,\n picture,\n onSettings,\n onLogout,\n className = '',\n}: ProfileDropdownProps) {\n const [isOpen, setIsOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Close dropdown when clicking outside\n useEffect(() => {\n function handleClickOutside(event: MouseEvent) {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n // Close dropdown on escape key\n useEffect(() => {\n function handleEscape(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n setIsOpen(false);\n }\n }\n\n if (isOpen) {\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }\n }, [isOpen]);\n\n const handleSettings = useCallback(() => {\n setIsOpen(false);\n onSettings?.();\n }, [onSettings]);\n\n const handleLogout = useCallback(() => {\n setIsOpen(false);\n onLogout?.();\n }, [onLogout]);\n\n const displayName = name || 'User';\n const initial = (name?.[0] || email?.[0] || '?').toUpperCase();\n\n return (\n <div className={`cedros-profile-dropdown ${className}`} ref={dropdownRef}>\n <button\n type=\"button\"\n className=\"cedros-profile-dropdown__trigger\"\n onClick={() => setIsOpen(!isOpen)}\n aria-expanded={isOpen}\n aria-haspopup=\"menu\"\n >\n <div className=\"cedros-profile-dropdown__avatar\">\n {picture ? (\n <img\n src={picture}\n alt={displayName}\n className=\"cedros-profile-dropdown__avatar-img\"\n referrerPolicy=\"no-referrer\"\n />\n ) : (\n <span className=\"cedros-profile-dropdown__avatar-placeholder\">{initial}</span>\n )}\n </div>\n <div className=\"cedros-profile-dropdown__info\">\n <span className=\"cedros-profile-dropdown__name\">{displayName}</span>\n {email && <span className=\"cedros-profile-dropdown__email\">{email}</span>}\n </div>\n <svg\n className={`cedros-profile-dropdown__chevron ${isOpen ? 'cedros-profile-dropdown__chevron--open' : ''}`}\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </button>\n\n {isOpen && (\n <div className=\"cedros-profile-dropdown__menu\" role=\"menu\">\n {onSettings && (\n <button\n type=\"button\"\n className=\"cedros-profile-dropdown__item\"\n onClick={handleSettings}\n role=\"menuitem\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n Settings\n </button>\n )}\n {onLogout && (\n <button\n type=\"button\"\n className=\"cedros-profile-dropdown__item cedros-profile-dropdown__item--danger\"\n onClick={handleLogout}\n role=\"menuitem\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4\" />\n <polyline points=\"16 17 21 12 16 7\" />\n <line x1=\"21\" x2=\"9\" y1=\"12\" y2=\"12\" />\n </svg>\n Log out\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * AdminShell - Unified Admin Dashboard Host\n *\n * A shell component that hosts admin plugins from cedros-login, cedros-pay,\n * or any compatible plugin. Provides unified sidebar navigation and content area.\n *\n * @example\n * ```tsx\n * import { AdminShell } from '@cedros/login-react';\n * import { cedrosLoginPlugin } from '@cedros/login-react';\n * import { cedrosPayPlugin } from '@cedros/pay-react';\n *\n * function AdminPage() {\n * const hostContext = useBuildHostContext();\n * return (\n * <AdminShell\n * plugins={[cedrosLoginPlugin, cedrosPayPlugin]}\n * hostContext={hostContext}\n * />\n * );\n * }\n * ```\n */\n\nimport React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useMemo,\n useEffect,\n Suspense,\n type ReactNode,\n} from 'react';\nimport type {\n AdminPlugin,\n PluginRegistry,\n HostContext,\n QualifiedSectionId,\n PluginContext,\n ResolvedSection,\n} from './types';\nimport { LoadingSpinner } from '../components/shared/LoadingSpinner';\nimport { ProfileDropdown } from '../components/admin/ProfileDropdown';\nimport { CedrosLoginContext, type CedrosLoginContextValue } from '../context/CedrosLoginContext';\nimport type { AuthUser } from '../types';\n\n// ============================================================================\n// Plugin Registry Implementation\n// ============================================================================\n\nclass PluginRegistryImpl implements PluginRegistry {\n private plugins = new Map<string, AdminPlugin>();\n private listeners = new Set<(plugins: AdminPlugin[]) => void>();\n\n register(plugin: AdminPlugin): void {\n if (this.plugins.has(plugin.id)) {\n console.warn(`Plugin ${plugin.id} already registered, replacing...`);\n }\n this.plugins.set(plugin.id, plugin);\n plugin.onRegister?.(this);\n this.notify();\n }\n\n unregister(pluginId: string): void {\n const plugin = this.plugins.get(pluginId);\n if (plugin) {\n plugin.onUnregister?.();\n this.plugins.delete(pluginId);\n this.notify();\n }\n }\n\n get(pluginId: string): AdminPlugin | undefined {\n return this.plugins.get(pluginId);\n }\n\n getAll(): AdminPlugin[] {\n return Array.from(this.plugins.values());\n }\n\n subscribe(listener: (plugins: AdminPlugin[]) => void): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n private notify(): void {\n const plugins = this.getAll();\n this.listeners.forEach((listener) => listener(plugins));\n }\n}\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface AdminShellContextValue {\n registry: PluginRegistry;\n hostContext: HostContext;\n activeSection: QualifiedSectionId | null;\n setActiveSection: (section: QualifiedSectionId) => void;\n getPluginContext: (pluginId: string) => PluginContext | null;\n}\n\nconst AdminShellContext = createContext<AdminShellContextValue | null>(null);\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useAdminShell(): AdminShellContextValue {\n const ctx = useContext(AdminShellContext);\n if (!ctx) throw new Error('useAdminShell must be used within AdminShell');\n return ctx;\n}\n\n// ============================================================================\n// Props\n// ============================================================================\n\nexport interface AdminShellProps {\n /** Dashboard title */\n title?: string;\n /** Plugins to load */\n plugins?: AdminPlugin[];\n /** Host context from parent providers */\n hostContext: HostContext;\n /** Default active section (qualified ID) */\n defaultSection?: QualifiedSectionId;\n /** Page size for lists */\n pageSize?: number;\n /** Refresh interval in ms (0 to disable) */\n refreshInterval?: number;\n /** Callback when section changes */\n onSectionChange?: (section: QualifiedSectionId) => void;\n /** Custom logo/header content */\n logo?: ReactNode;\n /** Additional sidebar footer content */\n sidebarFooter?: ReactNode;\n /** Callback when user clicks Settings in profile dropdown */\n onSettingsClick?: () => void;\n /** Callback when user clicks Logout in profile dropdown */\n onLogoutClick?: () => void;\n /** Additional CSS class */\n className?: string;\n}\n\n// ============================================================================\n// Group Order Helpers\n// ============================================================================\n\n/** Build a group-label → order map from all registered plugins' groups[] config. */\nfunction buildGroupOrder(plugins: AdminPlugin[]): Map<string, number> {\n const order = new Map<string, number>();\n for (const plugin of plugins) {\n for (const group of plugin.groups ?? []) {\n // Key by label (sections reference groups by display name via section.group).\n // First plugin to declare a group wins; later plugins don't override.\n if (!order.has(group.label)) {\n order.set(group.label, group.order);\n }\n }\n }\n return order;\n}\n\n// ============================================================================\n// AdminShell Component\n// ============================================================================\n\nexport function AdminShell({\n title = 'Admin',\n plugins: initialPlugins = [],\n hostContext,\n defaultSection,\n pageSize = 20,\n refreshInterval = 0,\n onSectionChange,\n logo,\n sidebarFooter,\n onSettingsClick,\n onLogoutClick,\n className = '',\n}: AdminShellProps): React.JSX.Element {\n // Plugin registry\n const [registry] = useState(() => {\n const reg = new PluginRegistryImpl();\n initialPlugins.forEach((p) => reg.register(p));\n return reg;\n });\n\n // Track registered plugins for re-renders\n const [registeredPlugins, setRegisteredPlugins] = useState<AdminPlugin[]>(() =>\n registry.getAll()\n );\n\n useEffect(() => {\n return registry.subscribe(setRegisteredPlugins);\n }, [registry]);\n\n // Aggregate sections from all plugins\n const allSections = useMemo(() => {\n return registeredPlugins.flatMap((plugin) =>\n plugin.sections\n .filter((section) => {\n // Check RBAC permissions (role-based)\n if (section.requiredPermission) {\n if (!plugin.checkPermission(section.requiredPermission, hostContext)) {\n return false;\n }\n }\n // Check dashboard section permissions (owner-configured per role)\n if (hostContext.dashboardPermissions) {\n if (!hostContext.dashboardPermissions.canAccess(section.id)) {\n return false;\n }\n }\n return true;\n })\n .map(\n (section): ResolvedSection => ({\n ...section,\n qualifiedId: `${plugin.id}:${section.id}` as QualifiedSectionId,\n pluginId: plugin.id,\n cssNamespace: plugin.cssNamespace,\n })\n )\n );\n }, [registeredPlugins, hostContext]);\n\n // Active section state\n const [activeSection, setActiveSectionInternal] = useState<QualifiedSectionId | null>(\n () => defaultSection ?? allSections[0]?.qualifiedId ?? null\n );\n\n // Collapsible groups state\n const [collapsedGroups, setCollapsedGroups] = useState<Set<string>>(new Set());\n\n const toggleGroup = useCallback((groupName: string) => {\n setCollapsedGroups((prev) => {\n const next = new Set(prev);\n if (next.has(groupName)) {\n next.delete(groupName);\n } else {\n next.add(groupName);\n }\n return next;\n });\n }, []);\n\n // Update active section when sections change and current is invalid\n useEffect(() => {\n if (activeSection && !allSections.find((s) => s.qualifiedId === activeSection)) {\n setActiveSectionInternal(allSections[0]?.qualifiedId ?? null);\n }\n }, [allSections, activeSection]);\n\n const setActiveSection = useCallback(\n (section: QualifiedSectionId) => {\n setActiveSectionInternal(section);\n onSectionChange?.(section);\n },\n [onSectionChange]\n );\n\n // Plugin context factory\n const getPluginContext = useCallback(\n (pluginId: string): PluginContext | null => {\n const plugin = registry.get(pluginId);\n if (!plugin) return null;\n return plugin.createPluginContext(hostContext);\n },\n [registry, hostContext]\n );\n\n // Group sections by group name, sorted by plugin-defined group order\n const groupedSections = useMemo(() => {\n const groupOrder = buildGroupOrder(registeredPlugins);\n const groups = new Map<string, ResolvedSection[]>();\n\n allSections.forEach((section) => {\n const groupName = section.group ?? 'Menu';\n const existing = groups.get(groupName) ?? [];\n groups.set(groupName, [...existing, section]);\n });\n\n // Sort groups by plugin-defined order (undeclared groups sink to bottom)\n const sortedGroups = Array.from(groups.entries()).sort(([a], [b]) => {\n const orderA = groupOrder.get(a) ?? 99;\n const orderB = groupOrder.get(b) ?? 99;\n return orderA - orderB;\n });\n\n return sortedGroups;\n }, [allSections, registeredPlugins]);\n\n // Get current section's component\n const currentSection = useMemo(() => {\n if (!activeSection) return null;\n const [pluginId, sectionId] = activeSection.split(':') as [string, string];\n const plugin = registry.get(pluginId);\n if (!plugin) return null;\n const Component = plugin.components[sectionId];\n if (!Component) return null;\n const pluginContext = plugin.createPluginContext(hostContext);\n return { Component, pluginContext, plugin };\n }, [activeSection, registry, hostContext]);\n\n // Context value\n const contextValue = useMemo<AdminShellContextValue>(\n () => ({\n registry,\n hostContext,\n activeSection,\n setActiveSection,\n getPluginContext,\n }),\n [registry, hostContext, activeSection, setActiveSection, getPluginContext]\n );\n\n // Bridge hostContext.cedrosLogin into CedrosLoginContext so hooks\n // (useOrgs, useAdminDeposits, etc.) work inside AdminShell sections.\n const cedrosLoginContextValue = useMemo<CedrosLoginContextValue | null>(() => {\n const cl = hostContext.cedrosLogin;\n if (!cl) return null;\n const user: AuthUser | null = cl.user\n ? { authMethods: [], emailVerified: false, createdAt: '', updatedAt: '', ...cl.user }\n : null;\n return {\n config: { serverUrl: cl.serverUrl },\n user,\n authState: cl.user ? 'authenticated' : 'unauthenticated',\n error: null,\n logout: async () => {},\n refreshUser: async () => {},\n isModalOpen: false,\n openModal: () => {},\n closeModal: () => {},\n _internal: {\n handleLoginSuccess: () => {},\n getAccessToken: cl.getAccessToken,\n },\n };\n }, [hostContext.cedrosLogin]);\n\n return (\n <AdminShellContext.Provider value={contextValue}>\n <CedrosLoginContext.Provider value={cedrosLoginContextValue}>\n <div className={`cedros-admin cedros-admin-shell ${className || ''}`}>\n {/* Sidebar */}\n <aside className=\"cedros-admin-shell__sidebar\">\n <div className=\"cedros-admin-shell__sidebar-header\">\n {logo ?? (\n <div className=\"cedros-admin-shell__logo\">\n <span className=\"cedros-admin-shell__logo-text\">{title}</span>\n </div>\n )}\n </div>\n\n <nav className=\"cedros-admin-shell__nav\">\n {groupedSections.map(([groupName, sections]) => {\n const isCollapsible = groupName === 'Configuration';\n const isCollapsed = collapsedGroups.has(groupName);\n\n return (\n <div key={groupName} className=\"cedros-admin-shell__nav-group\">\n {isCollapsible ? (\n <button\n type=\"button\"\n className=\"cedros-admin-shell__nav-label cedros-admin-shell__nav-label--collapsible\"\n onClick={() => toggleGroup(groupName)}\n aria-expanded={!isCollapsed}\n >\n <span>{groupName}</span>\n <span\n className={`cedros-admin-shell__nav-chevron ${!isCollapsed ? 'cedros-admin-shell__nav-chevron--expanded' : ''}`}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n </span>\n </button>\n ) : (\n <span className=\"cedros-admin-shell__nav-label\">{groupName}</span>\n )}\n {(!isCollapsible || !isCollapsed) &&\n sections\n .sort((a, b) => (a.order ?? 0) - (b.order ?? 0))\n .map((section) => (\n <button\n key={section.qualifiedId}\n type=\"button\"\n className={`cedros-admin-shell__nav-item ${\n activeSection === section.qualifiedId\n ? 'cedros-admin-shell__nav-item--active'\n : ''\n }`}\n onClick={() => setActiveSection(section.qualifiedId)}\n aria-current={\n activeSection === section.qualifiedId ? 'page' : undefined\n }\n >\n <span className=\"cedros-admin-shell__nav-icon\">{section.icon}</span>\n <span className=\"cedros-admin-shell__nav-text\">{section.label}</span>\n {section.badge && (\n <span className=\"cedros-admin-shell__nav-badge\">{section.badge}</span>\n )}\n </button>\n ))}\n </div>\n );\n })}\n </nav>\n\n {/* User profile dropdown + optional custom footer */}\n {(hostContext.cedrosLogin?.user || sidebarFooter) && (\n <div className=\"cedros-admin-shell__sidebar-footer\">\n {hostContext.cedrosLogin?.user && (\n <ProfileDropdown\n name={hostContext.cedrosLogin.user.name}\n email={hostContext.cedrosLogin.user.email}\n picture={hostContext.cedrosLogin.user.picture}\n onSettings={onSettingsClick}\n onLogout={onLogoutClick}\n />\n )}\n {sidebarFooter}\n </div>\n )}\n </aside>\n\n {/* Main Content */}\n <main className=\"cedros-admin-shell__main\">\n {currentSection ? (\n <Suspense fallback={<LoadingFallback />}>\n <div\n className=\"cedros-admin-shell__section\"\n data-plugin-namespace={currentSection.plugin.cssNamespace}\n >\n <currentSection.Component\n pluginContext={currentSection.pluginContext}\n pageSize={pageSize}\n refreshInterval={refreshInterval}\n />\n </div>\n </Suspense>\n ) : (\n <div className=\"cedros-admin-shell__empty\">\n {allSections.length === 0\n ? 'No plugins loaded'\n : 'Select a section from the sidebar'}\n </div>\n )}\n </main>\n </div>\n </CedrosLoginContext.Provider>\n </AdminShellContext.Provider>\n );\n}\n\n// ============================================================================\n// Helper Components\n// ============================================================================\n\nfunction LoadingFallback(): React.JSX.Element {\n return (\n <div className=\"cedros-admin-shell__loading\">\n <LoadingSpinner />\n <span>Loading...</span>\n </div>\n );\n}\n","/**\n * Admin Dashboard Icons\n *\n * SVG icons for the admin dashboard sidebar and sections.\n * Lucide-style, 24x24 viewBox rendered at 16x16.\n */\n\nimport type { ReactNode } from 'react';\n\nconst iconProps = {\n width: '16',\n height: '16',\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: '2',\n strokeLinecap: 'round' as const,\n strokeLinejoin: 'round' as const,\n};\n\nexport const Icons: Record<string, ReactNode> = {\n users: (\n <svg {...iconProps}>\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n ),\n\n members: (\n <svg {...iconProps}>\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\n </svg>\n ),\n\n invites: (\n <svg {...iconProps}>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n ),\n\n deposits: (\n <svg {...iconProps}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8\" />\n <path d=\"M12 18V6\" />\n </svg>\n ),\n\n withdrawals: (\n <svg {...iconProps}>\n <rect width=\"16\" height=\"20\" x=\"4\" y=\"2\" rx=\"2\" ry=\"2\" />\n <path d=\"M9 22v-4h6v4\" />\n <path d=\"M8 6h.01\" />\n <path d=\"M16 6h.01\" />\n <path d=\"M12 6h.01\" />\n <path d=\"M12 10h.01\" />\n <path d=\"M12 14h.01\" />\n <path d=\"M16 10h.01\" />\n <path d=\"M16 14h.01\" />\n <path d=\"M8 10h.01\" />\n <path d=\"M8 14h.01\" />\n </svg>\n ),\n\n settings: (\n <svg {...iconProps}>\n <path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\" />\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n </svg>\n ),\n\n wallet: (\n <svg {...iconProps}>\n <path d=\"M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1\" />\n <path d=\"M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4\" />\n </svg>\n ),\n\n chevronRight: (\n <svg {...iconProps}>\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n ),\n\n // Settings sub-page icons\n key: (\n <svg {...iconProps}>\n <path d=\"M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4\" />\n </svg>\n ),\n\n toggles: (\n <svg {...iconProps}>\n <rect width=\"20\" height=\"12\" x=\"2\" y=\"6\" rx=\"6\" />\n <circle cx=\"8\" cy=\"12\" r=\"2\" />\n </svg>\n ),\n\n shield: (\n <svg {...iconProps}>\n <path d=\"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z\" />\n </svg>\n ),\n\n mail: (\n <svg {...iconProps}>\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n ),\n\n webhook: (\n <svg {...iconProps}>\n <path d=\"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2\" />\n <path d=\"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06\" />\n <path d=\"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8\" />\n </svg>\n ),\n\n coins: (\n <svg {...iconProps}>\n <circle cx=\"8\" cy=\"8\" r=\"6\" />\n <path d=\"M18.09 10.37A6 6 0 1 1 10.34 18\" />\n <path d=\"M7 6h1v4\" />\n <path d=\"m16.71 13.88.7.71-2.82 2.82\" />\n </svg>\n ),\n\n server: (\n <svg {...iconProps}>\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\" ry=\"2\" />\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\" ry=\"2\" />\n <line x1=\"6\" x2=\"6.01\" y1=\"6\" y2=\"6\" />\n <line x1=\"6\" x2=\"6.01\" y1=\"18\" y2=\"18\" />\n </svg>\n ),\n};\n","/**\n * Cedros Login Admin Plugin\n *\n * Exports the cedrosLoginPlugin for use with AdminShell.\n * Provides user management, deposits, withdrawals, and configuration sections.\n */\n\nimport { lazy } from 'react';\nimport type { AdminPlugin, HostContext, PluginContext, AdminSectionConfig } from './types';\nimport { Icons } from './icons';\n\n// ============================================================================\n// Lazy-loaded Section Components\n// ============================================================================\n\nconst UsersSection = lazy(() => import('./sections/UsersSection'));\nconst TeamSection = lazy(() => import('./sections/TeamSection'));\nconst DepositsSection = lazy(() => import('./sections/DepositsSection'));\nconst WithdrawalsSection = lazy(() => import('./sections/WithdrawalsSection'));\nconst AuthenticationSettings = lazy(() => import('./sections/AuthenticationSettings'));\nconst EmbeddedWalletSettings = lazy(() => import('./sections/EmbeddedWalletSettings'));\nconst EmailSettings = lazy(() => import('./sections/EmailSettings'));\nconst WebhookSettings = lazy(() => import('./sections/WebhookSettings'));\nconst CreditSystemSettings = lazy(() => import('./sections/CreditSystemSettings'));\nconst ServerSettings = lazy(() => import('./sections/ServerSettings'));\n\n// ============================================================================\n// Permission Mapping\n// ============================================================================\n\ntype LoginPermission =\n | 'login:users:read'\n | 'login:users:write'\n | 'login:members:read'\n | 'login:members:write'\n | 'login:invites:read'\n | 'login:invites:write'\n | 'login:deposits:read'\n | 'login:deposits:write'\n | 'login:settings:read'\n | 'login:settings:write';\n\n/**\n * Maps plugin permissions to org-level permissions/roles.\n */\nconst PERMISSION_MAP: Record<LoginPermission, string[]> = {\n 'login:users:read': ['admin', 'owner'],\n 'login:users:write': ['admin', 'owner'],\n 'login:members:read': ['member:read', 'admin', 'owner'],\n 'login:members:write': ['member:remove', 'member:role_change'],\n 'login:invites:read': ['invite:read', 'admin', 'owner'],\n 'login:invites:write': ['invite:create', 'invite:cancel'],\n 'login:deposits:read': ['admin', 'owner'],\n 'login:deposits:write': ['admin', 'owner'],\n 'login:settings:read': ['admin', 'owner'],\n 'login:settings:write': ['admin', 'owner'],\n};\n\n// ============================================================================\n// Section Configuration\n// ============================================================================\n\nconst SECTIONS: AdminSectionConfig[] = [\n // Users group (main sections)\n {\n id: 'users',\n label: 'Users',\n icon: Icons.users,\n group: 'Users',\n order: 0,\n requiredPermission: 'login:users:read',\n },\n {\n id: 'team',\n label: 'Team',\n icon: Icons.members,\n group: 'Users',\n order: 1,\n requiredPermission: 'login:members:read',\n },\n {\n id: 'deposits',\n label: 'Deposits',\n icon: Icons.deposits,\n group: 'Users',\n order: 2,\n requiredPermission: 'login:deposits:read',\n },\n {\n id: 'withdrawals',\n label: 'Withdrawals',\n icon: Icons.withdrawals,\n group: 'Users',\n order: 3,\n requiredPermission: 'login:deposits:read',\n },\n\n // Configuration group (settings sections)\n {\n id: 'settings-auth',\n label: 'Authentication',\n icon: Icons.key,\n group: 'Configuration',\n order: 0,\n requiredPermission: 'login:settings:read',\n },\n {\n id: 'settings-email',\n label: 'Email & SMTP',\n icon: Icons.mail,\n group: 'Configuration',\n order: 1,\n requiredPermission: 'login:settings:read',\n },\n {\n id: 'settings-webhooks',\n label: 'Webhooks',\n icon: Icons.webhook,\n group: 'Configuration',\n order: 2,\n requiredPermission: 'login:settings:read',\n },\n {\n id: 'settings-wallet',\n label: 'User Wallets',\n icon: Icons.wallet,\n group: 'Configuration',\n order: 3,\n requiredPermission: 'login:settings:read',\n },\n {\n id: 'settings-credits',\n label: 'Credit System',\n icon: Icons.coins,\n group: 'Configuration',\n order: 4,\n requiredPermission: 'login:settings:read',\n },\n {\n id: 'settings-server',\n label: 'Auth Server',\n icon: Icons.server,\n group: 'Configuration',\n order: 5,\n requiredPermission: 'login:settings:read',\n },\n];\n\n// ============================================================================\n// Plugin Definition\n// ============================================================================\n\nexport const cedrosLoginPlugin: AdminPlugin = {\n id: 'cedros-login',\n name: 'Cedros Login',\n version: '1.0.0',\n\n sections: SECTIONS,\n\n groups: [\n { id: 'users', label: 'Users', order: 0 },\n { id: 'configuration', label: 'Configuration', order: 2 },\n ],\n\n components: {\n users: UsersSection,\n team: TeamSection,\n deposits: DepositsSection,\n withdrawals: WithdrawalsSection,\n 'settings-auth': AuthenticationSettings,\n 'settings-wallet': EmbeddedWalletSettings,\n 'settings-email': EmailSettings,\n 'settings-webhooks': WebhookSettings,\n 'settings-credits': CreditSystemSettings,\n 'settings-server': ServerSettings,\n },\n\n createPluginContext(hostContext: HostContext): PluginContext {\n const cedrosLogin = hostContext.cedrosLogin;\n if (!cedrosLogin) {\n throw new Error('cedros-login plugin requires cedrosLogin in hostContext');\n }\n\n return {\n serverUrl: cedrosLogin.serverUrl,\n userId: cedrosLogin.user?.id,\n getAccessToken: cedrosLogin.getAccessToken,\n hasPermission: (permission) => this.checkPermission(permission, hostContext),\n orgId: hostContext.org?.orgId,\n pluginData: {\n user: cedrosLogin.user,\n orgRole: hostContext.org?.role,\n },\n };\n },\n\n checkPermission(permission: string, hostContext: HostContext): boolean {\n const org = hostContext.org;\n\n // No org context = admin-level access (for global admins)\n if (!org) {\n // Check if user is in cedrosLogin context - assume admin if present\n return Boolean(hostContext.cedrosLogin?.user);\n }\n\n const requiredPerms = PERMISSION_MAP[permission as LoginPermission];\n if (!requiredPerms) {\n // Unknown permission - default deny\n return false;\n }\n\n // Check if user has any of the required permissions\n return requiredPerms.some(\n (p) =>\n org.permissions.includes(p) ||\n p === org.role ||\n (p === 'admin' && ['admin', 'owner'].includes(org.role)) ||\n (p === 'owner' && org.role === 'owner')\n );\n },\n\n cssNamespace: 'cedros-dashboard',\n};\n\n// Named export for convenience\nexport { cedrosLoginPlugin as loginPlugin };\n"],"names":["ProfileDropdown","name","email","picture","onSettings","onLogout","className","isOpen","setIsOpen","useState","dropdownRef","useRef","useEffect","handleClickOutside","event","handleEscape","handleSettings","useCallback","handleLogout","displayName","initial","jsxs","jsx","PluginRegistryImpl","plugin","pluginId","listener","plugins","AdminShellContext","createContext","useAdminShell","ctx","useContext","buildGroupOrder","order","group","AdminShell","title","initialPlugins","hostContext","defaultSection","pageSize","refreshInterval","onSectionChange","logo","sidebarFooter","onSettingsClick","onLogoutClick","registry","reg","p","registeredPlugins","setRegisteredPlugins","allSections","useMemo","section","activeSection","setActiveSectionInternal","collapsedGroups","setCollapsedGroups","toggleGroup","groupName","prev","next","setActiveSection","getPluginContext","groupedSections","groupOrder","groups","existing","a","b","orderA","orderB","currentSection","sectionId","Component","pluginContext","contextValue","cedrosLoginContextValue","cl","user","CedrosLoginContext","sections","isCollapsible","isCollapsed","Suspense","LoadingFallback","LoadingSpinner","iconProps","Icons","UsersSection","lazy","TeamSection","DepositsSection","WithdrawalsSection","AuthenticationSettings","EmbeddedWalletSettings","EmailSettings","WebhookSettings","CreditSystemSettings","ServerSettings","PERMISSION_MAP","SECTIONS","cedrosLoginPlugin","cedrosLogin","permission","org","requiredPerms"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cedros/login-react",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "description": "React component library for authentication with email/password, Google OAuth, and Solana wallet sign-in",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -1 +0,0 @@
1
- "use strict";const u=require("react"),N=require("./useSystemSettings-DRrreszl.cjs"),e=require("react/jsx-runtime"),P=800,C=2e3;function L(){const{settings:t,isLoading:s,error:a,fetchSettings:n,updateSettings:l}=N.useSystemSettings(),[i,p]=u.useState({}),[r,o]=u.useState("idle"),[c,d]=u.useState(null),_=u.useRef(null),h=u.useRef(null),g=u.useRef({});u.useEffect(()=>()=>{_.current&&clearTimeout(_.current),h.current&&clearTimeout(h.current)},[]);const k=u.useCallback(async()=>{const b={...g.current};if(Object.keys(b).length===0){o("idle");return}o("saving"),d(null);const y=Object.entries(b).map(([m,v])=>({key:m,value:v}));try{await l(y),p(m=>{const v={...m};for(const j of Object.keys(b))delete v[j];return v});for(const m of Object.keys(b))delete g.current[m];o("saved"),h.current&&clearTimeout(h.current),h.current=setTimeout(()=>{o("idle")},C)}catch(m){o("error"),d(m instanceof Error?m.message:"Failed to save")}},[l]),S=u.useCallback((b,y)=>{p(m=>({...m,[b]:y})),g.current[b]=y,d(null),o("pending"),_.current&&clearTimeout(_.current),_.current=setTimeout(()=>{k()},P)},[k]),T=u.useCallback(b=>{if(i[b]!==void 0)return i[b];for(const y of Object.values(t)){const m=y.find(v=>v.key===b);if(m)return m.value}return""},[i,t]);return{settings:t,edits:i,isLoading:s,autosaveStatus:r,autosaveError:c,error:a,fetchSettings:n,handleChange:S,getEffectiveValue:T}}function D(t){const s=Math.floor(t/86400),a=Math.floor(t%86400/3600),n=Math.floor(t%3600/60),l=t%60;return{days:s,hours:a,minutes:n,seconds:l}}function A(t){const{days:s,hours:a,minutes:n}=D(t),l=[];return s>0&&l.push(`${s}d`),a>0&&l.push(`${a}h`),n>0&&l.push(`${n}m`),l.length===0&&l.push(`${t}s`),l.join(" ")}const O={auth_email_enabled:{key:"auth_email_enabled",label:"Enable Email Authentication",description:"Allow users to sign up and log in with email/password.",inputType:"boolean"},auth_email_require_verification:{key:"auth_email_require_verification",label:"Require Email Verification",description:"Users must verify their email address before they can log in.",inputType:"boolean"},auth_email_block_disposable:{key:"auth_email_block_disposable",label:"Block Disposable Emails",description:"Reject registrations from known disposable email providers.",inputType:"boolean"},auth_google_enabled:{key:"auth_google_enabled",label:"Enable Google Sign-In",description:"Allow users to authenticate with their Google account.",inputType:"boolean"},auth_google_client_id:{key:"auth_google_client_id",label:"Google Client ID",description:"OAuth 2.0 client ID from Google Cloud Console.",inputType:"text"},auth_google_client_secret:{key:"auth_google_client_secret",label:"Google Client Secret",description:"OAuth 2.0 client secret from Google Cloud Console.",inputType:"secret"},auth_apple_enabled:{key:"auth_apple_enabled",label:"Enable Sign in with Apple",description:"Allow users to authenticate with their Apple ID.",inputType:"boolean"},auth_apple_client_id:{key:"auth_apple_client_id",label:"Apple Services ID",description:"The Services ID configured in your Apple Developer account.",inputType:"text"},auth_apple_team_id:{key:"auth_apple_team_id",label:"Apple Team ID",description:"Your Apple Developer Team ID.",inputType:"text"},auth_apple_key_id:{key:"auth_apple_key_id",label:"Apple Key ID",description:"The Key ID for your Sign in with Apple private key.",inputType:"text"},auth_apple_private_key:{key:"auth_apple_private_key",label:"Apple Private Key",description:"The private key file contents (PEM format) for Sign in with Apple.",inputType:"secret",multiline:!0},auth_solana_enabled:{key:"auth_solana_enabled",label:"Enable Solana Wallet Auth",description:"Allow users to authenticate by signing with their Solana wallet.",inputType:"boolean"},auth_solana_challenge_expiry:{key:"auth_solana_challenge_expiry",label:"Challenge Expiry",description:"How long a wallet signature challenge is valid.",inputType:"duration",min:60,presets:[{label:"1 minute",value:"60"},{label:"5 minutes",value:"300"},{label:"10 minutes",value:"600"}]},auth_webauthn_enabled:{key:"auth_webauthn_enabled",label:"Enable WebAuthn/Passkeys",description:"Allow passwordless authentication with FIDO2/WebAuthn credentials.",inputType:"boolean"},auth_webauthn_rp_id:{key:"auth_webauthn_rp_id",label:"Relying Party ID",description:"Usually your domain (e.g., example.com). Passkeys are bound to this.",inputType:"text"},auth_webauthn_rp_name:{key:"auth_webauthn_rp_name",label:"Relying Party Name",description:"Display name shown to users during passkey registration.",inputType:"text"},auth_webauthn_rp_origin:{key:"auth_webauthn_rp_origin",label:"Allowed Origins",description:"Comma-separated origins allowed for WebAuthn (e.g., https://example.com).",inputType:"text"},auth_instantlink_enabled:{key:"auth_instantlink_enabled",label:"Enable Instant Link",description:"Allow passwordless login via magic link sent to email.",inputType:"boolean"},auth_instantlink_expiry:{key:"auth_instantlink_expiry",label:"Link Expiry",description:"How long the magic link remains valid.",inputType:"duration",min:60,presets:[{label:"5 minutes",value:"300"},{label:"15 minutes",value:"900"},{label:"30 minutes",value:"1800"},{label:"1 hour",value:"3600"}]},auth_instantlink_rate_limit:{key:"auth_instantlink_rate_limit",label:"Rate Limit",description:"Maximum instant link requests per email per hour.",inputType:"select",presets:[{label:"3 per hour",value:"3"},{label:"5 per hour",value:"5"},{label:"10 per hour",value:"10"}]},feature_organizations:{key:"feature_organizations",label:"Organizations",description:"Enable multi-user organizations with role-based access.",inputType:"boolean"},feature_sso:{key:"feature_sso",label:"Enterprise SSO",description:"Enable SAML/OIDC single sign-on for enterprise customers.",inputType:"boolean"},feature_mfa:{key:"feature_mfa",label:"Two-Factor Authentication",description:"Allow users to enable TOTP-based two-factor authentication.",inputType:"boolean"},feature_wallet_signing:{key:"feature_wallet_signing",label:"Enable Embedded Wallet",description:"Enable the embedded wallet for transaction signing.",inputType:"boolean"},wallet_recovery_mode:{key:"wallet_recovery_mode",label:"Recovery Mode",description:"How users can recover their wallet if they lose access.",inputType:"select",presets:[{label:"Share C Only (Recommended)",value:"share_c_only"},{label:"Full Seed Phrase",value:"full_seed"},{label:"No Recovery",value:"none"}]},feature_credits:{key:"feature_credits",label:"Credit System",description:"Enable the deposits and credits system. Users can deposit tokens to receive platform credits.",inputType:"boolean"},feature_user_withdrawals:{key:"feature_user_withdrawals",label:"User Withdrawals",description:"Allow users to withdraw SOL/SPL tokens from their embedded wallet to external addresses.",inputType:"boolean"},security_cors_origins:{key:"security_cors_origins",label:"CORS Origins",description:"Allowed origins for cross-origin requests (comma-separated). Empty = same origin only.",inputType:"text"},security_cookie_domain:{key:"security_cookie_domain",label:"Cookie Domain",description:"Domain for auth cookies. Empty uses the request origin.",inputType:"text"},security_cookie_secure:{key:"security_cookie_secure",label:"Secure Cookies",description:"Require HTTPS for cookies. Disable only for local development.",inputType:"boolean"},security_cookie_same_site:{key:"security_cookie_same_site",label:"Cookie SameSite",description:'SameSite policy for cookies. Use "none" only if needed for cross-site embeds.',inputType:"select",presets:[{label:"Strict",value:"strict"},{label:"Lax (Recommended)",value:"lax"},{label:"None (cross-site)",value:"none"}]},security_session_timeout:{key:"security_session_timeout",label:"Session Timeout",description:"How long sessions remain valid before requiring re-authentication.",inputType:"duration",min:300,presets:[{label:"1 hour",value:"3600"},{label:"24 hours",value:"86400"},{label:"7 days",value:"604800"},{label:"30 days",value:"2592000"}]},security_jwt_issuer:{key:"security_jwt_issuer",label:"JWT Issuer",description:"Issuer claim for JWTs. Empty uses the server URL.",inputType:"text"},security_jwt_audience:{key:"security_jwt_audience",label:"JWT Audience",description:"Audience claim for JWTs. Empty uses default.",inputType:"text"},email_provider:{key:"email_provider",label:"Email Provider",description:"Select your email service provider for automatic configuration.",inputType:"select",presets:[{label:"Mailgun",value:"mailgun"},{label:"SendGrid",value:"sendgrid"},{label:"Postmark",value:"postmark"},{label:"AWS SES",value:"ses"},{label:"Resend",value:"resend"},{label:"Custom SMTP",value:"custom"}]},email_smtp_host:{key:"email_smtp_host",label:"SMTP Host",description:"SMTP server hostname (e.g., smtp.sendgrid.net).",inputType:"text"},email_smtp_port:{key:"email_smtp_port",label:"SMTP Port",description:"SMTP server port. Common: 587 (TLS), 465 (SSL), 25 (unencrypted).",inputType:"select",presets:[{label:"587 (TLS)",value:"587"},{label:"465 (SSL)",value:"465"},{label:"25 (Plain)",value:"25"}]},email_smtp_user:{key:"email_smtp_user",label:"SMTP Username",description:"Username for SMTP authentication.",inputType:"text"},email_smtp_password:{key:"email_smtp_password",label:"API Key",description:"API key or password for your email provider.",inputType:"secret"},email_smtp_tls:{key:"email_smtp_tls",label:"Use TLS",description:"Enable TLS encryption for SMTP connections.",inputType:"boolean"},email_from_address:{key:"email_from_address",label:"From Address",description:"Default sender email address (e.g., noreply@example.com).",inputType:"text"},email_from_name:{key:"email_from_name",label:"From Name",description:'Default sender display name (e.g., "My App").',inputType:"text"},webhook_enabled:{key:"webhook_enabled",label:"Enable Webhooks",description:"Send notifications to a Discord or Slack webhook URL.",inputType:"boolean"},webhook_url:{key:"webhook_url",label:"Webhook URL",description:"Discord or Slack webhook URL to receive notifications.",inputType:"text",placeholder:"https://discord.com/api/webhooks/..."},webhook_notify_registrations:{key:"webhook_notify_registrations",label:"New Registrations",description:"Notify when a new user registers.",inputType:"boolean"},webhook_notify_signins:{key:"webhook_notify_signins",label:"Sign-Ins",description:"Notify when a user signs in.",inputType:"boolean"},webhook_notify_deposits:{key:"webhook_notify_deposits",label:"Deposits",description:"Notify when a user makes a deposit.",inputType:"boolean"},server_frontend_url:{key:"server_frontend_url",label:"Frontend URL",description:"URL of your frontend app (for redirects and email links).",inputType:"text"},server_base_path:{key:"server_base_path",label:"Base Path",description:"Base path for auth endpoints (e.g., /auth).",inputType:"text"},server_trust_proxy:{key:"server_trust_proxy",label:"Trust Proxy",description:"Trust X-Forwarded-For headers. Enable if behind a reverse proxy.",inputType:"boolean"},server_cedros_pay_api_key:{key:"server_cedros_pay_api_key",label:"Cedros Pay API Key",description:"API key for Cedros Pay to authenticate with this server. Copy this into your Cedros Pay settings.",inputType:"secret"},jupiter_api_key:{key:"jupiter_api_key",label:"Jupiter API Key",description:'API key for Jupiter Ultra API (gasless swaps). Get a free key at <a href="https://portal.jup.ag" target="_blank" rel="noopener">portal.jup.ag</a>.',inputType:"secret"},server_metrics_api_key:{key:"server_metrics_api_key",label:"Metrics API Key",description:"API key for Prometheus/Grafana to scrape the /metrics endpoint. Use with Authorization: Bearer header.",inputType:"secret"},server_log_level:{key:"server_log_level",label:"Log Level",description:"Minimum severity level for log output. Lower levels are more verbose.",inputType:"select",presets:[{label:"Trace (most verbose)",value:"trace"},{label:"Debug",value:"debug"},{label:"Info",value:"info"},{label:"Warn",value:"warn"},{label:"Error (least verbose)",value:"error"}]},server_log_format:{key:"server_log_format",label:"Log Format",description:"Output format for log messages.",inputType:"select",presets:[{label:"JSON (structured)",value:"json"},{label:"Pretty (human-readable)",value:"pretty"}]},server_environment:{key:"server_environment",label:"Environment",description:"Deployment environment. Affects default behaviors and log verbosity.",inputType:"select",presets:[{label:"Development",value:"development"},{label:"Staging",value:"staging"},{label:"Production",value:"production"}]},privacy_period_secs:{key:"privacy_period_secs",label:"Privacy Period",description:"How long deposits are held before withdrawal to provide timing privacy. Longer periods provide better privacy but delay user access to funds.",inputType:"duration",min:0,presets:[{label:"Disabled",value:"0"},{label:"1 hour",value:"3600"},{label:"6 hours",value:"21600"},{label:"24 hours",value:"86400"},{label:"7 days",value:"604800"},{label:"14 days",value:"1209600"},{label:"30 days",value:"2592000"}],warningThreshold:{below:3600,message:"Very short privacy periods may not provide adequate timing protection."}},treasury_wallet_address:{key:"treasury_wallet_address",label:"Treasury Wallet Address",description:"Solana wallet address where funds are sent. Used for privacy cash withdrawals, micro payment batches, and direct payments.",inputType:"text",placeholder:"e.g., 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"},withdrawal_poll_interval_secs:{key:"withdrawal_poll_interval_secs",label:"Worker Poll Interval",description:"How often the withdrawal worker checks for deposits ready to process. Lower values process faster but increase server load.",inputType:"duration",min:60,presets:[{label:"1 minute",value:"60"},{label:"5 minutes",value:"300"},{label:"15 minutes",value:"900"},{label:"1 hour",value:"3600"},{label:"6 hours",value:"21600"}],warningThreshold:{below:60,message:"Polling more than once per minute may cause excessive load."}},withdrawal_batch_size:{key:"withdrawal_batch_size",label:"Batch Size",description:"Maximum number of withdrawals to process in a single batch. Higher values improve throughput but may cause timeouts.",inputType:"select",min:1,max:100,presets:[{label:"1 (Sequential)",value:"1"},{label:"5",value:"5"},{label:"10 (Recommended)",value:"10"},{label:"25",value:"25"},{label:"50",value:"50"},{label:"100 (Max)",value:"100"}]},withdrawal_timeout_secs:{key:"withdrawal_timeout_secs",label:"Transaction Timeout",description:"How long to wait for a withdrawal transaction to confirm before considering it failed.",inputType:"duration",min:30,presets:[{label:"30 seconds",value:"30"},{label:"1 minute",value:"60"},{label:"2 minutes",value:"120"},{label:"5 minutes",value:"300"}],warningThreshold:{below:30,message:"Very short timeouts may cause premature failure on slow networks."}},withdrawal_max_retries:{key:"withdrawal_max_retries",label:"Max Retries",description:"Number of times to retry a failed withdrawal before marking it as permanently failed.",inputType:"select",min:0,max:10,presets:[{label:"0 (No retries)",value:"0"},{label:"1",value:"1"},{label:"3 (Recommended)",value:"3"},{label:"5",value:"5"},{label:"10",value:"10"}]},withdrawal_percentage:{key:"withdrawal_percentage",label:"Withdrawal Percentage",description:"Percentage of ready funds to withdraw each cycle. Lower values spread withdrawals over time for better privacy.",inputType:"percentage",min:1,max:100,step:5,presets:[{label:"25%",value:"25"},{label:"50%",value:"50"},{label:"75%",value:"75"},{label:"100% (All at once)",value:"100"}],warningThreshold:{above:75,message:"High percentages may reduce timing privacy by processing most withdrawals together."}},partial_withdrawal_count:{key:"partial_withdrawal_count",label:"Partial Withdrawals",description:"Maximum partial withdrawals per batch. Partial withdrawals add noise to timing analysis. Set to 0 to disable.",inputType:"select",min:0,presets:[{label:"Disabled",value:"0"},{label:"1",value:"1"},{label:"3",value:"3"},{label:"5",value:"5"},{label:"10",value:"10"}]},partial_withdrawal_min_lamports:{key:"partial_withdrawal_min_lamports",label:"Min Balance for Partial",description:"Minimum account balance (in lamports) required before partial withdrawals are considered. 1 SOL = 1,000,000,000 lamports.",inputType:"select",min:0,presets:[{label:"0.1 SOL",value:"100000000"},{label:"0.5 SOL",value:"500000000"},{label:"1 SOL",value:"1000000000"},{label:"5 SOL",value:"5000000000"},{label:"10 SOL",value:"10000000000"}]},rate_limit_auth:{key:"rate_limit_auth",label:"Auth Request Limit",description:"Maximum authentication attempts (login, register, password reset) per IP per window. Protects against brute force attacks.",inputType:"select",min:1,unit:"requests",presets:[{label:"5 (Strict)",value:"5"},{label:"10 (Recommended)",value:"10"},{label:"20",value:"20"},{label:"50 (Permissive)",value:"50"}],warningThreshold:{above:20,message:"High auth limits may allow brute force attempts."}},rate_limit_general:{key:"rate_limit_general",label:"General Request Limit",description:"Maximum general API requests per IP per window. Affects all non-auth endpoints.",inputType:"select",min:1,unit:"requests",presets:[{label:"30",value:"30"},{label:"60 (Recommended)",value:"60"},{label:"120",value:"120"},{label:"300",value:"300"}]},rate_limit_credit:{key:"rate_limit_credit",label:"Credit Request Limit",description:"Maximum credit/balance check requests per IP per window. Higher for apps that poll balance frequently.",inputType:"select",min:1,unit:"requests",presets:[{label:"10",value:"10"},{label:"30 (Recommended)",value:"30"},{label:"60",value:"60"},{label:"120",value:"120"}]},rate_limit_window:{key:"rate_limit_window",label:"Rate Limit Window",description:'Time window for rate limiting. All limits above are "per window". Shorter windows are stricter.',inputType:"duration",min:1,presets:[{label:"30 seconds",value:"30"},{label:"1 minute",value:"60"},{label:"5 minutes",value:"300"},{label:"15 minutes",value:"900"}]},solana_rpc_url:{key:"solana_rpc_url",label:"Solana RPC URL",description:'Get a fast RPC endpoint from <a href="https://helius.dev" target="_blank" rel="noopener">Helius</a> or <a href="https://quicknode.com" target="_blank" rel="noopener">QuickNode</a>.',inputType:"text",placeholder:"https://api.mainnet-beta.solana.com"},solana_network:{key:"solana_network",label:"Solana Network",description:"The Solana network to use for deposits and withdrawals.",inputType:"select",presets:[{label:"Mainnet",value:"mainnet-beta"},{label:"Devnet",value:"devnet"}]},deposit_privacy_enabled:{key:"deposit_privacy_enabled",label:"Enable Private Deposits",description:"When enabled, deposits are held for a privacy period before withdrawal. Provides timing privacy but delays fund availability.",inputType:"boolean"},deposit_company_token:{key:"deposit_company_token",label:"Platform Token",description:"The token that represents platform credits. Deposits are converted to this token. Common choices: USDC, SOL.",inputType:"select",presets:[{label:"USDC",value:"USDC"},{label:"USDT",value:"USDT"},{label:"SOL",value:"SOL"},{label:"EURC",value:"EURC"}]},deposit_micro_enabled:{key:"deposit_micro_enabled",label:"SOL Micro Payments",description:"Allow small SOL deposits (under $10) that are batched together for efficiency.",inputType:"boolean"},deposit_gasless_swap_enabled:{key:"deposit_gasless_swap_enabled",label:"Gasless Swap Payments",description:"Allow deposits via Jupiter swaps.",inputType:"boolean"},deposit_min_usd:{key:"deposit_min_usd",label:"Minimum Deposit",description:"Minimum deposit amount in USD equivalent.",inputType:"select",unit:"USD",presets:[{label:"$1",value:"1"},{label:"$5",value:"5"},{label:"$10",value:"10"},{label:"$25",value:"25"}]},deposit_max_usd:{key:"deposit_max_usd",label:"Maximum Deposit",description:"Maximum deposit amount per transaction in USD equivalent. Set to 0 for unlimited.",inputType:"select",unit:"USD",presets:[{label:"Unlimited",value:"0"},{label:"$1,000",value:"1000"},{label:"$10,000",value:"10000"},{label:"$100,000",value:"100000"}]},deposit_show_explainer:{key:"deposit_show_explainer",label:"Show Explainer Screen",description:"Show the introductory explainer screen at the start of the deposit flow.",inputType:"boolean"},deposit_quick_action_tokens:{key:"deposit_quick_action_tokens",label:"Quick Action Tokens",description:"Comma-separated token symbols shown as quick action buttons. First token is the default.",inputType:"tokenSymbolList"},deposit_custom_tokens:{key:"deposit_custom_tokens",label:"Custom Dropdown Tokens",description:'Comma-separated token symbols shown in the "Custom" dropdown. Leave empty to show all.',inputType:"tokenSymbolList"},deposit_custom_tokens_json:{key:"deposit_custom_tokens_json",label:"Custom Token Definitions",description:"Add tokens beyond the built-in list. Define symbol, mint address, decimals, and logo URL.",inputType:"tokenList"},deposit_fee_policy:{key:"deposit_fee_policy",label:"Fee Policy",description:"Who pays deposit fees: company absorbs all, or user pays swap/privacy/all fees.",inputType:"select",presets:[{label:"Company Pays All",value:"company_pays_all"},{label:"User Pays Swap Fees",value:"user_pays_swap"},{label:"User Pays Privacy Fees",value:"user_pays_privacy"},{label:"User Pays All Fees",value:"user_pays_all"}]},privacy_fee_fixed_lamports:{key:"privacy_fee_fixed_lamports",label:"Privacy Fixed Fee",description:"Fixed fee for Privacy Cash deposits in lamports. 1 SOL = 1,000,000,000 lamports.",inputType:"select",unit:"lamports",presets:[{label:"0 SOL",value:"0"},{label:"0.001 SOL",value:"1000000"},{label:"0.005 SOL",value:"5000000"},{label:"0.006 SOL (Default)",value:"6000000"},{label:"0.01 SOL",value:"10000000"}]},privacy_fee_percent_bps:{key:"privacy_fee_percent_bps",label:"Privacy Percentage Fee",description:"Percentage fee for Privacy Cash deposits in basis points. 100 bps = 1%.",inputType:"select",unit:"bps",presets:[{label:"0%",value:"0"},{label:"0.25%",value:"25"},{label:"0.35% (Default)",value:"35"},{label:"0.5%",value:"50"},{label:"1%",value:"100"}]},swap_fee_fixed_lamports:{key:"swap_fee_fixed_lamports",label:"Swap Fixed Fee",description:"Fixed fee for Jupiter swaps in lamports. Covers transaction costs.",inputType:"select",unit:"lamports",presets:[{label:"0 SOL",value:"0"},{label:"0.001 SOL (Default)",value:"1000000"},{label:"0.002 SOL",value:"2000000"},{label:"0.005 SOL",value:"5000000"}]},swap_fee_percent_bps:{key:"swap_fee_percent_bps",label:"Swap Percentage Fee",description:"Percentage fee for Jupiter swaps in basis points. 100 bps = 1%.",inputType:"select",unit:"bps",presets:[{label:"0%",value:"0"},{label:"0.1% (Default)",value:"10"},{label:"0.25%",value:"25"},{label:"0.5%",value:"50"}]},company_fee_fixed_lamports:{key:"company_fee_fixed_lamports",label:"Company Fixed Fee",description:"Additional fixed processing fee in lamports. Set to 0 to disable.",inputType:"select",unit:"lamports",presets:[{label:"Disabled",value:"0"},{label:"0.001 SOL",value:"1000000"},{label:"0.005 SOL",value:"5000000"},{label:"0.01 SOL",value:"10000000"}]},company_fee_percent_bps:{key:"company_fee_percent_bps",label:"Company Percentage Fee",description:"Additional percentage processing fee in basis points. 100 bps = 1%.",inputType:"select",unit:"bps",presets:[{label:"Disabled",value:"0"},{label:"0.1%",value:"10"},{label:"0.25%",value:"25"},{label:"0.5%",value:"50"},{label:"1%",value:"100"}]},micro_batch_threshold_usd:{key:"micro_batch_threshold_usd",label:"Batch Threshold",description:"Minimum accumulated USD value before triggering a batch swap. Jupiter requires ~$10 minimum.",inputType:"select",unit:"USD",presets:[{label:"$10 (Minimum)",value:"10"},{label:"$25",value:"25"},{label:"$50",value:"50"},{label:"$100",value:"100"}]},micro_batch_poll_secs:{key:"micro_batch_poll_secs",label:"Batch Poll Interval",description:"How often to check for batchable micro deposits. Lower values process faster but increase load.",inputType:"duration",min:60,presets:[{label:"1 minute",value:"60"},{label:"5 minutes (Default)",value:"300"},{label:"15 minutes",value:"900"},{label:"1 hour",value:"3600"}]},private_deposit_min_lamports:{key:"private_deposit_min_lamports",label:"Min Private Deposit",description:"Minimum amount for Privacy Cash deposits in lamports. Smaller deposits use micro batching.",inputType:"select",unit:"lamports",presets:[{label:"0.1 SOL",value:"100000000"},{label:"0.25 SOL (Default)",value:"250000000"},{label:"0.5 SOL",value:"500000000"},{label:"1 SOL",value:"1000000000"}]},withdrawal_min_lamports:{key:"withdrawal_min_lamports",label:"Min Withdrawal Amount",description:"Minimum amount to withdraw in lamports. Deposits below this remain pending. Fees are ~0.006 SOL + 0.35% + Jupiter.",inputType:"select",unit:"lamports",presets:[{label:"0.5 SOL",value:"500000000"},{label:"1 SOL (Default)",value:"1000000000"},{label:"2 SOL",value:"2000000000"},{label:"5 SOL",value:"5000000000"}],warningThreshold:{below:5e8,message:"Very small withdrawals may lose significant value to fees."}}},x=["SOL","USDC","USDT","EURC","USD1","PYUSD","USDH","CASH","BONK","ORE"];function f(t){const s=t.split(/(<a\s[^>]*>.*?<\/a>)/g);return s.length===1?t:s.map((a,n)=>{const l=a.match(/^<a\s+href="([^"]+)"[^>]*>([^<]+)<\/a>$/);return l?e.jsx("a",{href:l[1],target:"_blank",rel:"noopener noreferrer",children:l[2]},n):a})}function E({settings:t,edits:s,onChange:a,externalWarnings:n}){return e.jsx("div",{className:"cedros-settings-grid",children:t.map(l=>e.jsx(U,{setting:l,editValue:s[l.key],onChange:a,externalWarning:n?.[l.key]},l.key))})}function U({setting:t,editValue:s,onChange:a,externalWarning:n}){const l=O[t.key],i=s??t.value,p=s!==void 0&&s!==t.value,r=l?.inputType==="boolean",o=u.useMemo(()=>{if(n)return n;if(!l?.warningThreshold)return null;const c=parseInt(i,10);if(isNaN(c))return null;const{above:d,below:_,message:h}=l.warningThreshold;return d!==void 0&&c>d||_!==void 0&&c<_?h:null},[i,l?.warningThreshold,n]);return l?e.jsx("div",{className:`cedros-setting-row ${p?"cedros-setting-row-changed":""} ${o?"cedros-setting-row-warning":""} ${r?"cedros-setting-row-toggle":""}`,children:r?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"cedros-setting-control cedros-setting-control-toggle",children:[e.jsx(w,{meta:l,value:i,onChange:c=>a(t.key,c)}),o&&e.jsx("div",{className:"cedros-setting-warning",children:o})]}),e.jsxs("div",{className:"cedros-setting-label",children:[e.jsx("span",{className:"cedros-setting-name",children:l.label}),e.jsx("span",{className:"cedros-setting-description",children:f(l.description)})]})]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"cedros-setting-label",children:[e.jsx("span",{className:"cedros-setting-name",children:l.label}),e.jsx("span",{className:"cedros-setting-description",children:f(l.description)})]}),e.jsxs("div",{className:"cedros-setting-control",children:[e.jsx(w,{meta:l,value:i,onChange:c=>a(t.key,c)}),o&&e.jsx("div",{className:"cedros-setting-warning",children:o})]})]})}):e.jsxs("div",{className:`cedros-setting-row ${p?"cedros-setting-row-changed":""}`,children:[e.jsxs("div",{className:"cedros-setting-label",children:[e.jsx("span",{className:"cedros-setting-name",children:t.key}),t.description&&e.jsx("span",{className:"cedros-setting-description",children:t.description})]}),e.jsx("div",{className:"cedros-setting-input-wrapper",children:e.jsx("input",{type:"text",value:i,onChange:c=>a(t.key,c.target.value),className:"cedros-setting-input"})})]})}function w({meta:t,value:s,onChange:a}){switch(t.inputType){case"duration":return e.jsx(I,{value:s,onChange:a,presets:t.presets,min:t.min});case"percentage":return e.jsx(M,{value:s,onChange:a,min:t.min??1,max:t.max??100,step:t.step??5,presets:t.presets});case"select":return e.jsx(R,{value:s,onChange:a,presets:t.presets??[],unit:t.unit});case"number":return e.jsx(F,{value:s,onChange:a,min:t.min,max:t.max,unit:t.unit});case"tokenList":return e.jsx(W,{value:s,onChange:a});case"text":return e.jsx("input",{type:"text",value:s,onChange:n=>a(n.target.value),className:"cedros-setting-input",placeholder:t.label});case"boolean":return e.jsx(q,{value:s,onChange:a});case"secret":return e.jsx($,{value:s,onChange:a,multiline:t.multiline});case"tokenSymbolList":return e.jsx(H,{value:s,onChange:a});default:return e.jsx("input",{type:"text",value:s,onChange:n=>a(n.target.value),className:"cedros-setting-input"})}}function I({value:t,onChange:s,presets:a,min:n=0}){const l=parseInt(t,10)||0,i=A(l),p=u.useCallback(o=>{o.target.value&&s(o.target.value)},[s]),r=u.useCallback(o=>{const c=Math.max(n,parseInt(o.target.value,10)||0);s(String(c))},[s,n]);return e.jsxs("div",{className:"cedros-duration-input",children:[a&&a.length>0&&e.jsxs("select",{value:a.find(o=>o.value===t)?.value??"",onChange:p,className:"cedros-setting-select",children:[e.jsx("option",{value:"",children:"Custom..."}),a.map(o=>e.jsx("option",{value:o.value,children:o.label},o.value))]}),e.jsxs("div",{className:"cedros-duration-custom",children:[e.jsx("input",{type:"number",value:l,onChange:r,min:n,className:"cedros-setting-input cedros-setting-input-sm"}),e.jsx("span",{className:"cedros-setting-unit",children:"seconds"}),e.jsxs("span",{className:"cedros-duration-display",children:["= ",i]})]})]})}function M({value:t,onChange:s,min:a,max:n,step:l,presets:i}){const p=parseInt(t,10)||a,r=u.useCallback(c=>{s(c.target.value)},[s]),o=u.useCallback(c=>{s(c)},[s]);return e.jsxs("div",{className:"cedros-percentage-input",children:[e.jsxs("div",{className:"cedros-percentage-slider-row",children:[e.jsx("input",{type:"range",value:p,onChange:r,min:a,max:n,step:l,className:"cedros-percentage-slider"}),e.jsxs("span",{className:"cedros-percentage-value",children:[p,"%"]})]}),i&&i.length>0&&e.jsx("div",{className:"cedros-preset-buttons",children:i.map(c=>e.jsx("button",{type:"button",className:`cedros-preset-button ${c.value===t?"cedros-preset-button-active":""}`,onClick:()=>o(c.value),children:c.label},c.value))})]})}function R({value:t,onChange:s,presets:a,unit:n}){const l=!a.some(r=>r.value===t),i=u.useCallback(r=>{r.target.value!=="__custom__"&&s(r.target.value)},[s]),p=u.useCallback(r=>{s(r.target.value)},[s]);return e.jsxs("div",{className:"cedros-select-input",children:[e.jsxs("select",{value:l?"__custom__":t,onChange:i,className:"cedros-setting-select",children:[a.map(r=>e.jsx("option",{value:r.value,children:r.label},r.value)),e.jsx("option",{value:"__custom__",children:"Custom..."})]}),l&&e.jsxs("div",{className:"cedros-select-custom",children:[e.jsx("input",{type:"number",value:t,onChange:p,className:"cedros-setting-input cedros-setting-input-sm"}),n&&e.jsx("span",{className:"cedros-setting-unit",children:n})]})]})}function F({value:t,onChange:s,min:a,max:n,unit:l}){const i=u.useCallback(p=>{s(p.target.value)},[s]);return e.jsxs("div",{className:"cedros-number-input",children:[e.jsx("input",{type:"number",value:t,onChange:i,min:a,max:n,className:"cedros-setting-input"}),l&&e.jsx("span",{className:"cedros-setting-unit",children:l})]})}function q({value:t,onChange:s}){const a=t==="true",n=u.useCallback(()=>{s(a?"false":"true")},[a,s]);return e.jsxs("button",{type:"button",role:"switch","aria-checked":a,className:`cedros-toggle ${a?"cedros-toggle-on":"cedros-toggle-off"}`,onClick:n,children:[e.jsx("span",{className:"cedros-toggle-track",children:e.jsx("span",{className:"cedros-toggle-thumb"})}),e.jsx("span",{className:"cedros-toggle-label",children:a?"Enabled":"Disabled"})]})}function $({value:t,onChange:s,multiline:a}){const[n,l]=u.useState(!1),[i,p]=u.useState(!1),r=t&&t.length>0,o=u.useCallback(()=>{l(!0),p(!0)},[]),c=u.useCallback(()=>{l(!1),p(!1)},[]),d=u.useCallback(_=>{s(_.target.value)},[s]);return!n&&r?e.jsxs("div",{className:"cedros-secret-input cedros-secret-input-masked",children:[e.jsx("span",{className:"cedros-secret-masked",children:"•".repeat(Math.min(t.length,20))}),e.jsx("button",{type:"button",className:"cedros-secret-edit-btn",onClick:o,children:"Edit"})]}):e.jsxs("div",{className:"cedros-secret-input",children:[a?e.jsx("textarea",{value:t,onChange:d,className:"cedros-setting-input cedros-setting-textarea",placeholder:"Enter secret value...",rows:4}):e.jsx("input",{type:i?"text":"password",value:t,onChange:d,className:"cedros-setting-input",placeholder:"Enter secret value..."}),e.jsxs("div",{className:"cedros-secret-actions",children:[!a&&e.jsx("button",{type:"button",className:"cedros-secret-toggle-btn",onClick:()=>p(!i),children:i?"Hide":"Show"}),n&&e.jsx("button",{type:"button",className:"cedros-secret-done-btn",onClick:c,children:"Done"})]})]})}function W({value:t,onChange:s}){const a=u.useMemo(()=>{try{return JSON.parse(t||"[]")}catch{return[]}},[t]),n=u.useCallback(r=>{s(JSON.stringify(r))},[s]),l=u.useCallback(()=>{n([...a,{symbol:"",mint:"",decimals:6}])},[a,n]),i=u.useCallback((r,o,c)=>{const d=[...a];d[r]={...d[r],[o]:c},n(d)},[a,n]),p=u.useCallback(r=>{n(a.filter((o,c)=>c!==r))},[a,n]);return e.jsxs("div",{className:"cedros-token-list-input",children:[e.jsxs("div",{className:"cedros-token-presets",children:[e.jsx("span",{className:"cedros-token-presets-label",children:"Built-in tokens:"}),e.jsx("div",{className:"cedros-token-presets-list",children:x.map(r=>e.jsx("span",{className:"cedros-token-preset-chip",children:r},r))})]}),a.length===0&&e.jsx("p",{className:"cedros-token-list-empty",children:"No custom tokens added. Use the built-in tokens above or add your own."}),a.map((r,o)=>e.jsxs("div",{className:"cedros-token-row",children:[e.jsxs("div",{className:"cedros-token-row-fields",children:[e.jsx("input",{type:"text",placeholder:"Symbol",value:r.symbol,onChange:c=>i(o,"symbol",c.target.value.toUpperCase()),className:"cedros-setting-input cedros-token-input-symbol",maxLength:10}),e.jsx("input",{type:"text",placeholder:"Mint address",value:r.mint,onChange:c=>i(o,"mint",c.target.value),className:"cedros-setting-input cedros-token-input-mint"}),e.jsx("input",{type:"number",placeholder:"Decimals",value:r.decimals,onChange:c=>i(o,"decimals",parseInt(c.target.value,10)||0),className:"cedros-setting-input cedros-token-input-decimals",min:0,max:18}),e.jsx("input",{type:"text",placeholder:"Logo URL (optional)",value:r.logoUrl||"",onChange:c=>i(o,"logoUrl",c.target.value||void 0),className:"cedros-setting-input cedros-token-input-logo"})]}),e.jsx("button",{type:"button",className:"cedros-token-remove-btn",onClick:()=>p(o),title:"Remove token",children:"×"})]},o)),e.jsx("button",{type:"button",className:"cedros-token-add-btn",onClick:l,children:"+ Add Token"})]})}function H({value:t,onChange:s}){const a=u.useMemo(()=>t.split(",").map(i=>i.trim()).filter(Boolean),[t]),n=u.useCallback(i=>{if(!i||a.includes(i))return;const p=[...a,i].join(", ");s(p)},[a,s]),l=u.useCallback(i=>{const p=a.filter(r=>r!==i).join(", ");s(p)},[a,s]);return e.jsxs("div",{className:"cedros-token-symbol-list-input",children:[e.jsxs("div",{className:"cedros-token-presets",children:[e.jsx("span",{className:"cedros-token-presets-label",children:"Click to add:"}),e.jsx("div",{className:"cedros-token-presets-list",children:x.map(i=>{const p=a.includes(i);return e.jsxs("button",{type:"button",className:`cedros-token-preset-chip ${p?"cedros-token-preset-chip-selected":""}`,onClick:()=>p?l(i):n(i),title:p?`Remove ${i}`:`Add ${i}`,children:[i,p&&e.jsx("span",{className:"cedros-token-chip-check",children:"✓"})]},i)})})]}),e.jsx("input",{type:"text",value:t,onChange:i=>s(i.target.value),className:"cedros-setting-input",placeholder:"USDC, SOL, BONK..."})]})}function B({status:t,error:s}){return t==="idle"?null:e.jsxs("div",{className:`cedros-autosave-status cedros-autosave-status--${t}`,children:[t==="pending"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"cedros-autosave-dot"}),e.jsx("span",{children:"Unsaved changes"})]}),t==="saving"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"cedros-autosave-spinner"}),e.jsx("span",{children:"Saving..."})]}),t==="saved"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"cedros-autosave-check",children:"✓"}),e.jsx("span",{children:"Saved"})]}),t==="error"&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"cedros-autosave-error-icon",children:"!"}),e.jsx("span",{children:s||"Save failed"})]})]})}exports.AutosaveStatus=B;exports.SettingsSection=E;exports.useSettingsAutosave=L;