@shellui/core 0.0.13 → 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.
- package/package.json +11 -25
- package/src/components/ui/dialog.tsx +3 -1
- package/src/components/ui/sidebar.tsx +14 -2
- package/src/features/config/ConfigProvider.ts +1 -1
- package/src/features/config/useConfig.ts +7 -2
- package/src/features/layouts/DefaultLayout.tsx +6 -1
- package/src/index.ts +2 -2
- package/src/service-worker/register.ts +2 -1
- package/dist/ContentView-CZG-ro_B.js +0 -146
- package/dist/ContentView-CZG-ro_B.js.map +0 -1
- package/dist/CookiePreferencesView-Bb3hFqw1.js +0 -213
- package/dist/CookiePreferencesView-Bb3hFqw1.js.map +0 -1
- package/dist/DefaultLayout-D3IpgS4j.js +0 -406
- package/dist/DefaultLayout-D3IpgS4j.js.map +0 -1
- package/dist/FullscreenLayout-Do9vAfl8.js +0 -30
- package/dist/FullscreenLayout-Do9vAfl8.js.map +0 -1
- package/dist/HomeView-DwckTuxz.js +0 -21
- package/dist/HomeView-DwckTuxz.js.map +0 -1
- package/dist/NotFoundView-DD7azhz-.js +0 -52
- package/dist/NotFoundView-DD7azhz-.js.map +0 -1
- package/dist/OverlayShell-kDY56DaN.js +0 -642
- package/dist/OverlayShell-kDY56DaN.js.map +0 -1
- package/dist/SettingsView-Bt4I-KDT.js +0 -2207
- package/dist/SettingsView-Bt4I-KDT.js.map +0 -1
- package/dist/ViewRoute-ChSPabOy.js +0 -32
- package/dist/ViewRoute-ChSPabOy.js.map +0 -1
- package/dist/WindowsLayout-CEqkRKyk.js +0 -633
- package/dist/WindowsLayout-CEqkRKyk.js.map +0 -1
- package/dist/app.d.ts +0 -3
- package/dist/app.d.ts.map +0 -1
- package/dist/components/ContentView.d.ts +0 -10
- package/dist/components/ContentView.d.ts.map +0 -1
- package/dist/components/HomeView.d.ts +0 -2
- package/dist/components/HomeView.d.ts.map +0 -1
- package/dist/components/LoadingOverlay.d.ts +0 -2
- package/dist/components/LoadingOverlay.d.ts.map +0 -1
- package/dist/components/NotFoundView.d.ts +0 -2
- package/dist/components/NotFoundView.d.ts.map +0 -1
- package/dist/components/RouteErrorBoundary.d.ts +0 -2
- package/dist/components/RouteErrorBoundary.d.ts.map +0 -1
- package/dist/components/ViewRoute.d.ts +0 -7
- package/dist/components/ViewRoute.d.ts.map +0 -1
- package/dist/components/ui/alert-dialog.d.ts +0 -32
- package/dist/components/ui/alert-dialog.d.ts.map +0 -1
- package/dist/components/ui/breadcrumb.d.ts +0 -20
- package/dist/components/ui/breadcrumb.d.ts.map +0 -1
- package/dist/components/ui/button-group.d.ts +0 -7
- package/dist/components/ui/button-group.d.ts.map +0 -1
- package/dist/components/ui/button.d.ts +0 -12
- package/dist/components/ui/button.d.ts.map +0 -1
- package/dist/components/ui/dialog.d.ts +0 -24
- package/dist/components/ui/dialog.d.ts.map +0 -1
- package/dist/components/ui/drawer.d.ts +0 -38
- package/dist/components/ui/drawer.d.ts.map +0 -1
- package/dist/components/ui/select.d.ts +0 -5
- package/dist/components/ui/select.d.ts.map +0 -1
- package/dist/components/ui/sidebar.d.ts +0 -46
- package/dist/components/ui/sidebar.d.ts.map +0 -1
- package/dist/components/ui/sonner.d.ts +0 -6
- package/dist/components/ui/sonner.d.ts.map +0 -1
- package/dist/components/ui/switch.d.ts +0 -8
- package/dist/components/ui/switch.d.ts.map +0 -1
- package/dist/constants/urls.d.ts +0 -6
- package/dist/constants/urls.d.ts.map +0 -1
- package/dist/constants/urls.js +0 -8
- package/dist/constants/urls.js.map +0 -1
- package/dist/features/alertDialog/DialogContext.d.ts +0 -12
- package/dist/features/alertDialog/DialogContext.d.ts.map +0 -1
- package/dist/features/config/ConfigProvider.d.ts +0 -15
- package/dist/features/config/ConfigProvider.d.ts.map +0 -1
- package/dist/features/config/types.d.ts +0 -177
- package/dist/features/config/types.d.ts.map +0 -1
- package/dist/features/config/useConfig.d.ts +0 -8
- package/dist/features/config/useConfig.d.ts.map +0 -1
- package/dist/features/cookieConsent/CookieConsentModal.d.ts +0 -6
- package/dist/features/cookieConsent/CookieConsentModal.d.ts.map +0 -1
- package/dist/features/cookieConsent/CookiePreferencesView.d.ts +0 -2
- package/dist/features/cookieConsent/CookiePreferencesView.d.ts.map +0 -1
- package/dist/features/cookieConsent/cookieConsent.d.ts +0 -22
- package/dist/features/cookieConsent/cookieConsent.d.ts.map +0 -1
- package/dist/features/cookieConsent/useCookieConsent.d.ts +0 -15
- package/dist/features/cookieConsent/useCookieConsent.d.ts.map +0 -1
- package/dist/features/drawer/DrawerContext.d.ts +0 -24
- package/dist/features/drawer/DrawerContext.d.ts.map +0 -1
- package/dist/features/layouts/AppLayout.d.ts +0 -12
- package/dist/features/layouts/AppLayout.d.ts.map +0 -1
- package/dist/features/layouts/DefaultLayout.d.ts +0 -10
- package/dist/features/layouts/DefaultLayout.d.ts.map +0 -1
- package/dist/features/layouts/FullscreenLayout.d.ts +0 -9
- package/dist/features/layouts/FullscreenLayout.d.ts.map +0 -1
- package/dist/features/layouts/LayoutProviders.d.ts +0 -9
- package/dist/features/layouts/LayoutProviders.d.ts.map +0 -1
- package/dist/features/layouts/OverlayShell.d.ts +0 -10
- package/dist/features/layouts/OverlayShell.d.ts.map +0 -1
- package/dist/features/layouts/WindowsLayout.d.ts +0 -24
- package/dist/features/layouts/WindowsLayout.d.ts.map +0 -1
- package/dist/features/layouts/utils.d.ts +0 -16
- package/dist/features/layouts/utils.d.ts.map +0 -1
- package/dist/features/modal/ModalContext.d.ts +0 -20
- package/dist/features/modal/ModalContext.d.ts.map +0 -1
- package/dist/features/sentry/initSentry.d.ts +0 -14
- package/dist/features/sentry/initSentry.d.ts.map +0 -1
- package/dist/features/settings/SettingsContext.d.ts +0 -10
- package/dist/features/settings/SettingsContext.d.ts.map +0 -1
- package/dist/features/settings/SettingsIcons.d.ts +0 -22
- package/dist/features/settings/SettingsIcons.d.ts.map +0 -1
- package/dist/features/settings/SettingsProvider.d.ts +0 -5
- package/dist/features/settings/SettingsProvider.d.ts.map +0 -1
- package/dist/features/settings/SettingsRoutes.d.ts +0 -7
- package/dist/features/settings/SettingsRoutes.d.ts.map +0 -1
- package/dist/features/settings/SettingsView.d.ts +0 -2
- package/dist/features/settings/SettingsView.d.ts.map +0 -1
- package/dist/features/settings/components/Advanced.d.ts +0 -2
- package/dist/features/settings/components/Advanced.d.ts.map +0 -1
- package/dist/features/settings/components/Appearance.d.ts +0 -2
- package/dist/features/settings/components/Appearance.d.ts.map +0 -1
- package/dist/features/settings/components/DataPrivacy.d.ts +0 -2
- package/dist/features/settings/components/DataPrivacy.d.ts.map +0 -1
- package/dist/features/settings/components/Develop.d.ts +0 -2
- package/dist/features/settings/components/Develop.d.ts.map +0 -1
- package/dist/features/settings/components/LanguageAndRegion.d.ts +0 -2
- package/dist/features/settings/components/LanguageAndRegion.d.ts.map +0 -1
- package/dist/features/settings/components/ServiceWorker.d.ts +0 -2
- package/dist/features/settings/components/ServiceWorker.d.ts.map +0 -1
- package/dist/features/settings/components/UpdateApp.d.ts +0 -2
- package/dist/features/settings/components/UpdateApp.d.ts.map +0 -1
- package/dist/features/settings/components/develop/DialogTestButtons.d.ts +0 -2
- package/dist/features/settings/components/develop/DialogTestButtons.d.ts.map +0 -1
- package/dist/features/settings/components/develop/DrawerTestButtons.d.ts +0 -2
- package/dist/features/settings/components/develop/DrawerTestButtons.d.ts.map +0 -1
- package/dist/features/settings/components/develop/ModalTestButtons.d.ts +0 -2
- package/dist/features/settings/components/develop/ModalTestButtons.d.ts.map +0 -1
- package/dist/features/settings/components/develop/ToastTestButtons.d.ts +0 -2
- package/dist/features/settings/components/develop/ToastTestButtons.d.ts.map +0 -1
- package/dist/features/settings/hooks/useSettings.d.ts +0 -2
- package/dist/features/settings/hooks/useSettings.d.ts.map +0 -1
- package/dist/features/sonner/SonnerContext.d.ts +0 -29
- package/dist/features/sonner/SonnerContext.d.ts.map +0 -1
- package/dist/features/theme/ThemeProvider.d.ts +0 -11
- package/dist/features/theme/ThemeProvider.d.ts.map +0 -1
- package/dist/features/theme/themes.d.ts +0 -114
- package/dist/features/theme/themes.d.ts.map +0 -1
- package/dist/features/theme/useTheme.d.ts +0 -10
- package/dist/features/theme/useTheme.d.ts.map +0 -1
- package/dist/i18n/I18nProvider.d.ts +0 -9
- package/dist/i18n/I18nProvider.d.ts.map +0 -1
- package/dist/i18n/config.d.ts +0 -23
- package/dist/i18n/config.d.ts.map +0 -1
- package/dist/i18n/translations/en/common.json.d.ts +0 -19
- package/dist/i18n/translations/en/cookieConsent.json.d.ts +0 -53
- package/dist/i18n/translations/en/settings.json.d.ts +0 -358
- package/dist/i18n/translations/fr/common.json.d.ts +0 -19
- package/dist/i18n/translations/fr/cookieConsent.json.d.ts +0 -53
- package/dist/i18n/translations/fr/settings.json.d.ts +0 -358
- package/dist/index-CfvdAI_Y.js +0 -2168
- package/dist/index-CfvdAI_Y.js.map +0 -1
- package/dist/index.d.ts +0 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -12
- package/dist/index.js.map +0 -1
- package/dist/lib/utils.d.ts +0 -3
- package/dist/lib/utils.d.ts.map +0 -1
- package/dist/lib/z-index.d.ts +0 -29
- package/dist/lib/z-index.d.ts.map +0 -1
- package/dist/router/router.d.ts +0 -3
- package/dist/router/router.d.ts.map +0 -1
- package/dist/router/routes.d.ts +0 -4
- package/dist/router/routes.d.ts.map +0 -1
- package/dist/sidebar-Dt-gibIZ.js +0 -336
- package/dist/sidebar-Dt-gibIZ.js.map +0 -1
- package/dist/style.css +0 -1
- package/dist/switch-CuKXfl3x.js +0 -44
- package/dist/switch-CuKXfl3x.js.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-CfvdAI_Y.js","sources":["../src/features/config/ConfigProvider.ts","../src/features/config/useConfig.ts","../src/lib/utils.ts","../src/components/ui/button.tsx","../src/components/RouteErrorBoundary.tsx","../src/features/settings/SettingsContext.tsx","../src/features/layouts/AppLayout.tsx","../src/features/layouts/utils.ts","../src/router/routes.tsx","../src/router/router.tsx","../src/features/settings/SettingsProvider.tsx","../src/features/settings/hooks/useSettings.tsx","../src/features/theme/themes.ts","../src/features/theme/useTheme.tsx","../src/features/theme/ThemeProvider.tsx","../src/i18n/config.ts","../src/i18n/I18nProvider.tsx","../src/lib/z-index.ts","../src/components/ui/alert-dialog.tsx","../src/features/alertDialog/DialogContext.tsx","../src/features/cookieConsent/CookieConsentModal.tsx","../src/features/cookieConsent/cookieConsent.ts","../src/features/sentry/initSentry.ts","../src/service-worker/register.ts","../src/app.tsx","../src/features/cookieConsent/useCookieConsent.ts"],"sourcesContent":["import { createContext, useState, createElement, type ReactNode } from 'react';\nimport { getLogger } from '@shellui/sdk';\nimport type { ShellUIConfig } from './types';\n\nconst logger = getLogger('shellcore');\n\nexport interface ConfigContextValue {\n config: ShellUIConfig;\n}\n\nexport const ConfigContext = createContext<ConfigContextValue | null>(null);\n\nexport interface ConfigProviderProps {\n children: ReactNode;\n}\n\n// Track if config has been logged to prevent duplicate logs in dev mode\n// (can happen with React StrictMode or when app renders in multiple contexts)\nlet configLogged = false;\n\n/**\n * Loads ShellUI config from __SHELLUI_CONFIG__ (injected by Vite at build time)\n * and provides it via context. Children can use useConfig() to read config.\n */\n\nexport function ConfigProvider(props: ConfigProviderProps): ReturnType<typeof createElement> {\n const [config] = useState<ShellUIConfig>(() => {\n try {\n // __SHELLUI_CONFIG__ is replaced by Vite at build time via define\n // After replacement, it will be a JSON string like: \"{\\\"title\\\":\\\"shellui\\\",...}\"\n // Vite's define inserts the string value directly, so we only need to parse once\n // Access it directly (no typeof check) so Vite can statically analyze and replace it\n // @ts-expect-error - __SHELLUI_CONFIG__ is injected by Vite at build time\n let configValue: unknown = __SHELLUI_CONFIG__;\n \n // In development, if __SHELLUI_CONFIG__ is undefined, it might not have been replaced by Vite\n // This can happen if the Vite define configuration isn't working properly\n if (configValue === undefined && typeof window !== 'undefined') {\n // Try to get it from window (fallback for dev mode issues)\n const g = window as unknown as { __SHELLUI_CONFIG__?: unknown };\n if (g.__SHELLUI_CONFIG__ !== undefined) {\n configValue = g.__SHELLUI_CONFIG__;\n }\n }\n\n // After Vite replacement, configValue will be a JSON string\n // Example: \"{\\\"title\\\":\\\"shellui\\\"}\" -> parse -> {title: \"shellui\"}\n if (configValue !== undefined && configValue !== null && typeof configValue === 'string') {\n try {\n // Parse the JSON string to get the config object\n const parsedConfig: ShellUIConfig = JSON.parse(configValue);\n if (typeof window !== 'undefined' && parsedConfig.runtime === 'tauri') {\n (window as Window & { __SHELLUI_TAURI__?: boolean }).__SHELLUI_TAURI__ = true;\n }\n\n // Log in dev mode to help debug (only once per page load)\n if (process.env.NODE_ENV === 'development' && !configLogged) {\n configLogged = true;\n logger.info('Config loaded from __SHELLUI_CONFIG__', {\n hasNavigation: !!parsedConfig.navigation,\n navigationItems: parsedConfig.navigation?.length || 0,\n });\n }\n\n return parsedConfig;\n } catch (parseError) {\n logger.error('Failed to parse config JSON:', { error: parseError });\n logger.error('Config value (first 200 chars):', { value: configValue.substring(0, 200) });\n // Fall through to return empty config\n }\n }\n\n // Fallback: try to read from globalThis (for edge cases or if define didn't work)\n // This handles cases where Vite's define didn't work or config needs to be injected at runtime\n const g = globalThis as unknown as { __SHELLUI_CONFIG__?: unknown };\n if (typeof g.__SHELLUI_CONFIG__ !== 'undefined' && configValue === undefined) {\n const fallbackValue = g.__SHELLUI_CONFIG__;\n const parsedConfig: ShellUIConfig =\n typeof fallbackValue === 'string'\n ? JSON.parse(fallbackValue)\n : (fallbackValue as ShellUIConfig);\n if (typeof window !== 'undefined' && parsedConfig.runtime === 'tauri') {\n (window as Window & { __SHELLUI_TAURI__?: boolean }).__SHELLUI_TAURI__ = true;\n }\n\n if (process.env.NODE_ENV === 'development') {\n logger.warn('Config loaded from globalThis fallback (define may not have worked)');\n }\n\n return parsedConfig;\n }\n\n // Return empty config if __SHELLUI_CONFIG__ is undefined (fallback for edge cases)\n // This ensures the provider always provides a value, preventing \"useConfig must be used within ConfigProvider\" errors\n if (process.env.NODE_ENV === 'development') {\n logger.warn(\n 'Config not found. Using empty config. Make sure shellui.config.ts is properly loaded and Vite define is configured correctly.',\n );\n }\n return {} as ShellUIConfig;\n } catch (err) {\n logger.error('Failed to load ShellUI config:', { error: err });\n // Don't throw - return empty config instead to prevent app crash\n return {} as ShellUIConfig;\n }\n });\n\n // Always provide a value - never null - to prevent \"useConfig must be used within ConfigProvider\" errors\n const value: ConfigContextValue = { config };\n return createElement(ConfigContext.Provider, { value }, props.children);\n}\n","import { useContext } from 'react';\nimport { ConfigContext, type ConfigContextValue } from './ConfigProvider';\n\n/**\n * Hook to access ShellUI configuration from ConfigProvider context.\n * Must be used within a ConfigProvider.\n * @returns {ConfigContextValue} Configuration object and loading state\n */\nexport function useConfig(): ConfigContextValue {\n const context = useContext(ConfigContext);\n if (context === null) {\n // This error should never happen if ConfigProvider is properly wrapping the app\n // If you see this error, check that:\n // 1. Your component is rendered inside a <ConfigProvider> tree\n // 2. The ConfigProvider is mounted before components that use useConfig()\n // 3. Vite's define configuration is working correctly (check __SHELLUI_CONFIG__)\n const error = new Error(\n 'useConfig must be used within a ConfigProvider. ' +\n 'Make sure your app is wrapped with <ConfigProvider> and that Vite define is configured correctly.'\n );\n if (typeof window !== 'undefined' && process.env.NODE_ENV === 'development') {\n console.error('[ShellUI] ConfigProvider error:', error);\n console.error('[ShellUI] Check that __SHELLUI_CONFIG__ is defined:', typeof (window as any).__SHELLUI_CONFIG__);\n }\n throw error;\n }\n return context;\n}\n","import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { forwardRef, type ButtonHTMLAttributes } from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '@/lib/utils';\n\nconst buttonVariants = cva(\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 cursor-pointer disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground hover:bg-primary/90',\n destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',\n outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',\n secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',\n ghost: 'hover:bg-accent hover:text-accent-foreground',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'h-9 rounded-md px-3',\n lg: 'h-11 rounded-md px-8',\n icon: 'h-10 w-10',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nexport interface ButtonProps\n extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n}\n\nconst Button = forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, ...props }, ref) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n {...props}\n />\n );\n },\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n","import { useRouteError, isRouteErrorResponse } from 'react-router';\nimport { useTranslation } from 'react-i18next';\nimport { shellui } from '@shellui/sdk';\nimport { Button } from '@/components/ui/button';\n\nfunction isChunkLoadError(error: unknown): boolean {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n return (\n msg.includes('loading dynamically imported module') ||\n msg.includes('chunk') ||\n msg.includes('failed to fetch dynamically imported module')\n );\n }\n return false;\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (isRouteErrorResponse(error)) {\n return error.data?.message ?? error.statusText ?? 'Something went wrong';\n }\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n}\n\nfunction getErrorStack(error: unknown): string | null {\n if (error instanceof Error && error.stack) {\n return error.stack;\n }\n return null;\n}\n\nfunction getErrorDetailsText(error: unknown): string {\n const message = getErrorMessage(error);\n const stack = getErrorStack(error);\n if (stack) {\n return `Message:\\n${message}\\n\\nStack:\\n${stack}`;\n }\n return message;\n}\n\nexport function RouteErrorBoundary() {\n const error = useRouteError();\n const { t } = useTranslation('common');\n const isChunkError = isChunkLoadError(error);\n const detailsText = getErrorDetailsText(error);\n\n return (\n <div\n className=\"flex min-h-screen flex-col items-center justify-center bg-background px-4 py-12\"\n style={{ fontFamily: 'var(--heading-font-family, system-ui, sans-serif)' }}\n >\n <div className=\"w-full max-w-md space-y-6 text-center\">\n <div className=\"space-y-2\">\n <h1 className=\"text-xl font-semibold text-foreground\">\n {isChunkError ? t('errorBoundary.titleChunk') : t('errorBoundary.titleGeneric')}\n </h1>\n <p className=\"text-sm text-muted-foreground\">\n {isChunkError\n ? t('errorBoundary.descriptionChunk')\n : t('errorBoundary.descriptionGeneric')}\n </p>\n </div>\n\n <div className=\"flex flex-col gap-3 sm:flex-row sm:justify-center\">\n <Button\n variant=\"default\"\n onClick={() => window.location.reload()}\n className=\"shrink-0\"\n >\n {t('errorBoundary.tryAgain')}\n </Button>\n <Button\n variant=\"outline\"\n onClick={() => shellui.navigate('/')}\n className=\"shrink-0\"\n >\n {t('errorBoundary.goToHome')}\n </Button>\n </div>\n\n <details className=\"rounded-lg border border-border bg-muted/30 text-left\">\n <summary className=\"cursor-pointer px-4 py-3 text-xs font-medium text-muted-foreground hover:text-foreground\">\n {t('errorBoundary.errorDetails')}\n </summary>\n <pre className=\"max-h-64 overflow-auto whitespace-pre-wrap break-all px-4 pb-3 pt-1 text-xs text-muted-foreground font-mono\">\n {detailsText}\n </pre>\n </details>\n </div>\n </div>\n );\n}\n","import { useContext, createContext } from 'react';\nimport type { Settings } from '@shellui/sdk';\n\nexport interface SettingsContextValue {\n settings: Settings;\n updateSettings: (updates: Partial<Settings>) => void;\n updateSetting: <K extends keyof Settings>(key: K, updates: Partial<Settings[K]>) => void;\n resetAllData: () => void;\n}\n\nexport const SettingsContext = createContext<SettingsContextValue | undefined>(undefined);\n\nexport function useSettings() {\n const context = useContext(SettingsContext);\n if (context === undefined) {\n throw new Error('useSettings must be used within a SettingsProvider');\n }\n return context;\n}\n","import { lazy, Suspense, type LazyExoticComponent, type ComponentType } from 'react';\nimport type { LayoutType, NavigationItem, NavigationGroup } from '../config/types';\nimport { useSettings } from '../settings/SettingsContext';\n\nconst DefaultLayout = lazy(() =>\n import('./DefaultLayout').then((m) => ({ default: m.DefaultLayout })),\n);\nconst FullscreenLayout = lazy(() =>\n import('./FullscreenLayout').then((m) => ({ default: m.FullscreenLayout })),\n);\nconst WindowsLayout = lazy(() =>\n import('./WindowsLayout').then((m) => ({ default: m.WindowsLayout })),\n);\n\ninterface AppLayoutProps {\n layout?: LayoutType;\n title?: string;\n appIcon?: string;\n logo?: string;\n navigation: (NavigationItem | NavigationGroup)[];\n}\n\nfunction LayoutFallback() {\n return (\n <div\n className=\"min-h-screen bg-background\"\n aria-hidden\n />\n );\n}\n\n/** Renders the layout based on settings.layout (override) or config.layout: 'sidebar' (default), 'fullscreen', or 'windows'. Lazy-loads only the active layout. */\nexport function AppLayout({\n layout = 'sidebar',\n title,\n appIcon,\n logo,\n navigation,\n}: AppLayoutProps) {\n const { settings } = useSettings();\n const effectiveLayout: LayoutType = settings.layout ?? layout;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let LayoutComponent: LazyExoticComponent<ComponentType<any>>;\n let layoutProps: Record<string, unknown>;\n\n if (effectiveLayout === 'fullscreen') {\n LayoutComponent = FullscreenLayout;\n layoutProps = { title, navigation };\n } else if (effectiveLayout === 'windows') {\n LayoutComponent = WindowsLayout;\n layoutProps = { title, appIcon, logo, navigation };\n } else {\n LayoutComponent = DefaultLayout;\n layoutProps = { title, appIcon, logo, navigation };\n }\n\n return (\n <Suspense fallback={<LayoutFallback />}>\n <LayoutComponent {...layoutProps} />\n </Suspense>\n );\n}\n","import type { NavigationItem, NavigationGroup, LocalizedString } from '../config/types';\n\n/** Resolve a localized string to a single string for the given language. */\nexport function resolveLocalizedString(value: LocalizedString | undefined, lang: string): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string') return value;\n return value[lang] || value.en || value.fr || Object.values(value)[0] || '';\n}\n\n/** Flatten navigation items from groups or flat array. */\nexport function flattenNavigationItems(\n navigation: (NavigationItem | NavigationGroup)[],\n): NavigationItem[] {\n if (navigation.length === 0) {\n return [];\n }\n return navigation.flatMap((item) => {\n if ('title' in item && 'items' in item) {\n return (item as NavigationGroup).items;\n }\n return item as NavigationItem;\n });\n}\n\nexport type Viewport = 'mobile' | 'desktop';\n\n/** Filter navigation by viewport: remove hidden and viewport-specific hidden items (and empty groups). */\nexport function filterNavigationByViewport(\n navigation: (NavigationItem | NavigationGroup)[],\n viewport: Viewport,\n): (NavigationItem | NavigationGroup)[] {\n if (navigation.length === 0) return [];\n const hideOnMobile = viewport === 'mobile';\n const hideOnDesktop = viewport === 'desktop';\n return navigation\n .map((item) => {\n if ('title' in item && 'items' in item) {\n const group = item as NavigationGroup;\n const visibleItems = group.items.filter((navItem) => {\n if (navItem.hidden) return false;\n if (hideOnMobile && navItem.hiddenOnMobile) return false;\n if (hideOnDesktop && navItem.hiddenOnDesktop) return false;\n return true;\n });\n if (visibleItems.length === 0) return null;\n return { ...group, items: visibleItems };\n }\n const navItem = item as NavigationItem;\n if (navItem.hidden) return null;\n if (hideOnMobile && navItem.hiddenOnMobile) return null;\n if (hideOnDesktop && navItem.hiddenOnDesktop) return null;\n return item;\n })\n .filter((item): item is NavigationItem | NavigationGroup => item !== null);\n}\n\n/** Filter navigation for sidebar: remove hidden items and groups that become empty. */\nexport function filterNavigationForSidebar(\n navigation: (NavigationItem | NavigationGroup)[],\n): (NavigationItem | NavigationGroup)[] {\n if (navigation.length === 0) return [];\n return navigation\n .map((item) => {\n if ('title' in item && 'items' in item) {\n const group = item as NavigationGroup;\n const visibleItems = group.items.filter((navItem) => !navItem.hidden);\n if (visibleItems.length === 0) return null;\n return { ...group, items: visibleItems };\n }\n const navItem = item as NavigationItem;\n if (navItem.hidden) return null;\n return item;\n })\n .filter((item): item is NavigationItem | NavigationGroup => item !== null);\n}\n\n/** Split navigation by position: start (main content) and end (footer). */\nexport function splitNavigationByPosition(navigation: (NavigationItem | NavigationGroup)[]): {\n start: (NavigationItem | NavigationGroup)[];\n end: NavigationItem[];\n} {\n const start: (NavigationItem | NavigationGroup)[] = [];\n const end: NavigationItem[] = [];\n for (const item of navigation) {\n const position = 'position' in item ? (item.position ?? 'start') : 'start';\n if (position === 'end') {\n if ('title' in item && 'items' in item) {\n const group = item as NavigationGroup;\n end.push(...group.items.filter((navItem) => !navItem.hidden));\n } else {\n const navItem = item as NavigationItem;\n if (!navItem.hidden) end.push(navItem);\n }\n } else {\n start.push(item);\n }\n }\n return { start, end };\n}\n","import { lazy, Suspense } from 'react';\nimport { Outlet, type RouteObject } from 'react-router';\nimport type { ShellUIConfig } from '../features/config/types';\nimport { RouteErrorBoundary } from '../components/RouteErrorBoundary';\nimport { AppLayout } from '../features/layouts/AppLayout';\nimport { flattenNavigationItems } from '../features/layouts/utils';\nimport urls from '../constants/urls';\n\n// Lazy load route components\nconst HomeView = lazy(() =>\n import('../components/HomeView').then((m) => ({ default: m.HomeView })),\n);\nconst SettingsView = lazy(() =>\n import('../features/settings/SettingsView').then((m) => ({ default: m.SettingsView })),\n);\nconst CookiePreferencesView = lazy(() =>\n import('../features/cookieConsent/CookiePreferencesView').then((m) => ({\n default: m.CookiePreferencesView,\n })),\n);\nconst ViewRoute = lazy(() =>\n import('../components/ViewRoute').then((m) => ({ default: m.ViewRoute })),\n);\nconst NotFoundView = lazy(() =>\n import('../components/NotFoundView').then((m) => ({ default: m.NotFoundView })),\n);\n\nfunction RouteFallback() {\n return (\n <div\n className=\"min-h-screen bg-background\"\n aria-hidden\n />\n );\n}\n\nexport const createRoutes = (config: ShellUIConfig): RouteObject[] => {\n const routes: RouteObject[] = [\n {\n path: '/',\n element: <Outlet />,\n errorElement: <RouteErrorBoundary />,\n children: [\n {\n // Settings route (if configured)\n path: `${urls.settings.replace(/^\\//, '')}/*`,\n element: (\n <Suspense fallback={<RouteFallback />}>\n <SettingsView />\n </Suspense>\n ),\n },\n {\n // Cookie preferences route\n path: urls.cookiePreferences.replace(/^\\//, ''),\n element: (\n <Suspense fallback={<RouteFallback />}>\n <CookiePreferencesView />\n </Suspense>\n ),\n },\n {\n // Catch-all route\n path: '*',\n element: (\n <Suspense fallback={<RouteFallback />}>\n <NotFoundView />\n </Suspense>\n ),\n },\n ],\n },\n ];\n\n // Main layout route with nested routes\n const layoutRoute: RouteObject = {\n element: (\n <AppLayout\n layout={config.layout}\n title={config.title}\n appIcon={config.appIcon}\n logo={config.logo}\n navigation={config.navigation || []}\n />\n ),\n children: [\n {\n path: '/',\n element: (\n <Suspense fallback={<RouteFallback />}>\n <HomeView />\n </Suspense>\n ),\n },\n ],\n };\n\n // Add navigation routes\n if (config.navigation && config.navigation.length > 0) {\n const navigationItems = flattenNavigationItems(config.navigation);\n navigationItems.forEach((item) => {\n (layoutRoute.children as RouteObject[]).push({\n path: `/${item.path}/*`,\n element: (\n <Suspense fallback={<RouteFallback />}>\n <ViewRoute navigation={navigationItems} />\n </Suspense>\n ),\n });\n });\n }\n (routes[0].children as RouteObject[]).push(layoutRoute);\n\n return routes;\n};\n","import { createBrowserRouter } from 'react-router';\nimport type { ShellUIConfig } from '../features/config/types';\nimport { createRoutes } from './routes';\n\nexport const createAppRouter = (config: ShellUIConfig) => {\n const routes = createRoutes(config);\n return createBrowserRouter(routes);\n};\n","import { useRef, useState, useEffect, useCallback, useMemo, type ReactNode } from 'react';\nimport {\n getLogger,\n shellui,\n type ShellUIMessage,\n type Settings,\n type SettingsNavigationItem,\n} from '@shellui/sdk';\nimport { SettingsContext } from './SettingsContext';\nimport { useConfig } from '../config/useConfig';\nimport { useTranslation } from 'react-i18next';\nimport type { NavigationItem, NavigationGroup } from '../config/types';\n\nconst logger = getLogger('shellcore');\n\nfunction flattenNavigationItems(\n navigation: (NavigationItem | NavigationGroup)[],\n): NavigationItem[] {\n if (navigation.length === 0) return [];\n return navigation.flatMap((item) => {\n if ('title' in item && 'items' in item) return (item as NavigationGroup).items;\n return [item as NavigationItem];\n });\n}\n\nfunction resolveLabel(\n value: string | { en: string; fr: string; [key: string]: string },\n lang: string,\n): string {\n if (typeof value === 'string') return value;\n return value[lang] || value.en || value.fr || Object.values(value)[0] || '';\n}\n\nfunction buildSettingsWithNavigation(\n settings: Settings,\n navigation: (NavigationItem | NavigationGroup)[] | undefined,\n lang: string,\n): Settings {\n if (!navigation?.length) return settings;\n const items: SettingsNavigationItem[] = flattenNavigationItems(navigation).map((item) => ({\n path: item.path,\n url: item.url,\n label: resolveLabel(item.label, lang),\n }));\n return { ...settings, navigation: { items } };\n}\n\nconst STORAGE_KEY = 'shellui:settings';\n\n// Get browser's timezone as default\nconst getBrowserTimezone = (): string => {\n if (typeof window !== 'undefined' && Intl) {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n }\n return 'UTC';\n};\n\nconst defaultSettings: Settings = {\n developerFeatures: {\n enabled: false,\n },\n errorReporting: {\n enabled: true,\n },\n logging: {\n namespaces: {\n shellsdk: false,\n shellcore: false,\n },\n },\n appearance: {\n theme: 'system',\n themeName: 'default',\n },\n language: {\n code: 'en',\n },\n region: {\n timezone: getBrowserTimezone(),\n },\n cookieConsent: {\n acceptedHosts: [],\n consentedCookieHosts: [],\n },\n serviceWorker: {\n enabled: true,\n },\n};\n\nexport function SettingsProvider({ children }: { children: ReactNode }) {\n const { config } = useConfig();\n const { i18n } = useTranslation();\n // Use a ref to always have current settings for message listeners (avoids closure issues)\n const settingsRef = useRef<Settings | null>(null);\n const [settings, setSettings] = useState<Settings>(() => {\n let initialSettings: Settings;\n\n if (shellui.initialSettings) {\n initialSettings = shellui.initialSettings;\n settingsRef.current = initialSettings;\n return initialSettings;\n }\n\n // Initialize from localStorage\n if (typeof window !== 'undefined') {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) {\n const parsed = JSON.parse(stored);\n // Deep merge with defaults to handle new settings\n initialSettings = {\n ...defaultSettings,\n ...parsed,\n errorReporting: {\n enabled: parsed.errorReporting?.enabled ?? defaultSettings.errorReporting.enabled,\n },\n logging: {\n namespaces: {\n ...defaultSettings.logging.namespaces,\n ...parsed.logging?.namespaces,\n },\n },\n appearance: {\n theme: parsed.appearance?.theme || defaultSettings.appearance.theme,\n themeName: parsed.appearance?.themeName || defaultSettings.appearance.themeName,\n },\n language: {\n code: parsed.language?.code || defaultSettings.language.code,\n },\n region: {\n // Only use stored timezone if it exists, otherwise use browser's current timezone\n timezone: parsed.region?.timezone || getBrowserTimezone(),\n },\n cookieConsent: {\n acceptedHosts: Array.isArray(parsed.cookieConsent?.acceptedHosts)\n ? parsed.cookieConsent.acceptedHosts\n : (defaultSettings.cookieConsent?.acceptedHosts ?? []),\n consentedCookieHosts: Array.isArray(parsed.cookieConsent?.consentedCookieHosts)\n ? parsed.cookieConsent.consentedCookieHosts\n : (defaultSettings.cookieConsent?.consentedCookieHosts ?? []),\n },\n serviceWorker: {\n // Migrate from legacy \"caching\" key if present\n enabled: parsed.serviceWorker?.enabled ?? parsed.caching?.enabled ?? true,\n },\n };\n settingsRef.current = initialSettings;\n return initialSettings;\n }\n } catch (error) {\n logger.error('Failed to load settings from localStorage:', { error });\n }\n }\n settingsRef.current = defaultSettings;\n return defaultSettings;\n });\n\n // Keep ref in sync with state for message listeners\n useEffect(() => {\n settingsRef.current = settings;\n }, [settings]);\n\n // Listen for settings updates from parent/other nodes\n useEffect(() => {\n if (typeof window === 'undefined') {\n return;\n }\n\n const cleanup = shellui.addMessageListener(\n 'SHELLUI_SETTINGS_UPDATED',\n (message: ShellUIMessage) => {\n const payload = message.payload as { settings: Settings };\n const newSettings = payload.settings;\n if (newSettings) {\n // Update localStorage with new settings value\n setSettings(newSettings);\n if (window.parent === window) {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(newSettings));\n // Confirm: root updated localStorage; re-inject navigation when propagating\n const settingsToPropagate = buildSettingsWithNavigation(\n newSettings,\n config?.navigation,\n i18n.language || 'en',\n );\n logger.info('Root Parent received settings update', { message });\n shellui.propagateMessage({\n type: 'SHELLUI_SETTINGS',\n payload: { settings: settingsToPropagate },\n });\n } catch (error) {\n logger.error('Failed to update settings from message:', { error });\n }\n }\n }\n },\n );\n\n const cleanupSettingsRequested = shellui.addMessageListener(\n 'SHELLUI_SETTINGS_REQUESTED',\n () => {\n // Use ref to always get current settings (avoids stale closure)\n const currentSettings = settingsRef.current ?? defaultSettings;\n const settingsWithNav = buildSettingsWithNavigation(\n currentSettings,\n config?.navigation,\n i18n.language || 'en',\n );\n shellui.propagateMessage({\n type: 'SHELLUI_SETTINGS',\n payload: { settings: settingsWithNav },\n });\n },\n );\n\n const cleanupSettings = shellui.addMessageListener(\n 'SHELLUI_SETTINGS',\n (data: ShellUIMessage) => {\n const message = data as ShellUIMessage;\n const payload = message.payload as { settings: Settings };\n const newSettings = payload.settings;\n if (newSettings) {\n setSettings(newSettings);\n }\n },\n );\n\n return () => {\n cleanup();\n cleanupSettings();\n cleanupSettingsRequested();\n };\n }, [settings, config?.navigation, i18n.language]);\n\n // ACTIONS\n const updateSettings = useCallback(\n (updates: Partial<Settings>) => {\n const newSettings = { ...settings, ...updates };\n\n // Update localStorage and propagate to children if we're in the root window\n if (typeof window !== 'undefined' && window.parent === window) {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(newSettings));\n setSettings(newSettings);\n // Propagate to child iframes (sendMessageToParent does nothing in root)\n const settingsWithNav = buildSettingsWithNavigation(\n newSettings,\n config?.navigation,\n i18n.language || 'en',\n );\n shellui.propagateMessage({\n type: 'SHELLUI_SETTINGS',\n payload: { settings: settingsWithNav },\n });\n } catch (error) {\n logger.error('Failed to update settings in localStorage:', { error });\n }\n }\n\n // For child iframes, send to parent (parent will propagate to siblings)\n shellui.sendMessageToParent({\n type: 'SHELLUI_SETTINGS_UPDATED',\n payload: { settings: newSettings },\n });\n },\n [settings, config?.navigation, i18n.language],\n );\n\n const updateSetting = useCallback(\n <K extends keyof Settings>(key: K, updates: Partial<Settings[K]>) => {\n // Deep merge: preserve existing nested properties\n const currentValue = settings[key];\n const mergedValue =\n typeof currentValue === 'object' && currentValue !== null && !Array.isArray(currentValue)\n ? { ...currentValue, ...updates }\n : updates;\n updateSettings({ [key]: mergedValue } as Partial<Settings>);\n },\n [settings, updateSettings],\n );\n\n const resetAllData = useCallback(() => {\n // Clear all localStorage data\n if (typeof window !== 'undefined') {\n try {\n // Clear settings\n localStorage.removeItem(STORAGE_KEY);\n\n // Clear all other localStorage items that start with shellui:\n const keysToRemove: string[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (key && key.startsWith('shellui:')) {\n keysToRemove.push(key);\n }\n }\n keysToRemove.forEach((key) => localStorage.removeItem(key));\n\n // Reset settings to defaults\n const newSettings = defaultSettings;\n setSettings(newSettings);\n\n // If we're in the root window, update localStorage with defaults\n if (window.parent === window) {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(newSettings));\n const settingsToPropagate = buildSettingsWithNavigation(\n newSettings,\n config?.navigation,\n i18n.language || 'en',\n );\n shellui.propagateMessage({\n type: 'SHELLUI_SETTINGS',\n payload: { settings: settingsToPropagate },\n });\n }\n\n // Notify parent about reset\n shellui.sendMessageToParent({\n type: 'SHELLUI_SETTINGS_UPDATED',\n payload: { settings: newSettings },\n });\n\n logger.info('All app data has been reset');\n } catch (error) {\n logger.error('Failed to reset all data:', { error });\n }\n }\n }, [config?.navigation, i18n.language]);\n\n const value = useMemo(\n () => ({\n settings,\n updateSettings,\n updateSetting,\n resetAllData,\n }),\n [settings, updateSettings, updateSetting, resetAllData],\n );\n\n return <SettingsContext.Provider value={value}>{children}</SettingsContext.Provider>;\n}\n","import { useContext } from 'react';\nimport { SettingsContext } from '../SettingsContext';\n\nexport function useSettings() {\n const context = useContext(SettingsContext);\n if (context === undefined) {\n throw new Error('useSettings must be used within a SettingsProvider');\n }\n return context;\n}\n","/* eslint-disable no-console */\n/**\n * Theme color definitions following shadcn/ui CSS variable structure\n * Each theme has light and dark mode variants\n * Colors are stored in hex format (e.g., \"#4CAF50\" or \"4CAF50\")\n * and converted to HSL when applied to CSS variables\n */\n\n/**\n * Convert hex color (format: \"#RRGGBB\" or \"RRGGBB\") to HSL string (format: \"H S% L%\")\n */\nfunction hexToHsl(hexString: string): string {\n // Handle non-color values like radius\n if (!hexString || typeof hexString !== 'string') {\n return hexString;\n }\n\n // Check if it's a hex color\n if (!hexString.match(/^#?[0-9A-Fa-f]{6}$/)) {\n // If it's not a hex color, return as-is (might be radius or other value)\n return hexString;\n }\n\n // Remove # if present\n const hex = hexString.replace('#', '');\n\n // Parse RGB values\n const r = parseInt(hex.substring(0, 2), 16);\n const g = parseInt(hex.substring(2, 4), 16);\n const b = parseInt(hex.substring(4, 6), 16);\n\n // Validate parsed values\n if (isNaN(r) || isNaN(g) || isNaN(b)) {\n console.warn(`[Theme] Invalid hex color: ${hexString}`);\n return hexString;\n }\n\n // Normalize RGB values to 0-1\n const rNorm = r / 255;\n const gNorm = g / 255;\n const bNorm = b / 255;\n\n const max = Math.max(rNorm, gNorm, bNorm);\n const min = Math.min(rNorm, gNorm, bNorm);\n let h = 0;\n let s = 0;\n const l = (max + min) / 2;\n\n if (max !== min) {\n const d = max - min;\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\n\n switch (max) {\n case rNorm:\n h = ((gNorm - bNorm) / d + (gNorm < bNorm ? 6 : 0)) / 6;\n break;\n case gNorm:\n h = ((bNorm - rNorm) / d + 2) / 6;\n break;\n case bNorm:\n h = ((rNorm - gNorm) / d + 4) / 6;\n break;\n }\n }\n\n // Convert to degrees and percentages\n const hDeg = Math.round(h * 360 * 10) / 10; // Keep one decimal for precision\n const sPercent = Math.round(s * 100 * 10) / 10;\n const lPercent = Math.round(l * 100 * 10) / 10;\n\n const result = `${hDeg} ${sPercent}% ${lPercent}%`;\n\n // Validate result\n if (!result.match(/^\\d+(\\.\\d+)?\\s+\\d+(\\.\\d+)?%\\s+\\d+(\\.\\d+)?%$/)) {\n console.warn(`[Theme] Invalid HSL conversion result for ${hexString}: ${result}`);\n return hexString;\n }\n\n return result;\n}\n\nexport interface ThemeColors {\n light: {\n background: string;\n foreground: string;\n card: string;\n cardForeground: string;\n popover: string;\n popoverForeground: string;\n primary: string;\n primaryForeground: string;\n secondary: string;\n secondaryForeground: string;\n muted: string;\n mutedForeground: string;\n accent: string;\n accentForeground: string;\n destructive: string;\n destructiveForeground: string;\n border: string;\n input: string;\n ring: string;\n radius: string;\n sidebarBackground: string;\n sidebarForeground: string;\n sidebarPrimary: string;\n sidebarPrimaryForeground: string;\n sidebarAccent: string;\n sidebarAccentForeground: string;\n sidebarBorder: string;\n sidebarRing: string;\n };\n dark: {\n background: string;\n foreground: string;\n card: string;\n cardForeground: string;\n popover: string;\n popoverForeground: string;\n primary: string;\n primaryForeground: string;\n secondary: string;\n secondaryForeground: string;\n muted: string;\n mutedForeground: string;\n accent: string;\n accentForeground: string;\n destructive: string;\n destructiveForeground: string;\n border: string;\n input: string;\n ring: string;\n radius: string;\n sidebarBackground: string;\n sidebarForeground: string;\n sidebarPrimary: string;\n sidebarPrimaryForeground: string;\n sidebarAccent: string;\n sidebarAccentForeground: string;\n sidebarBorder: string;\n sidebarRing: string;\n };\n}\n\nexport interface ThemeDefinition {\n name: string;\n displayName: string;\n colors: ThemeColors;\n fontFamily?: string; // Optional custom font family (backward compatible)\n headingFontFamily?: string; // Optional font family for headings (h1-h6)\n bodyFontFamily?: string; // Optional font family for body text\n fontFiles?: string[]; // Optional array of font file URLs or paths to load (e.g., Google Fonts links or local paths)\n letterSpacing?: string; // Optional custom letter spacing (e.g., \"0.02em\")\n textShadow?: string; // Optional custom text shadow (e.g., \"1px 1px 2px rgba(0, 0, 0, 0.1)\")\n lineHeight?: string; // Optional custom line height (e.g., \"1.6\")\n}\n\n/**\n * Default theme - Green (current ShellUI theme)\n * Colors are in hex format (e.g., \"#FFFFFF\" or \"FFFFFF\" for white)\n */\nexport const defaultTheme: ThemeDefinition = {\n name: 'default',\n displayName: 'Default',\n colors: {\n light: {\n background: '#FFFFFF', // White\n foreground: '#020617', // Very dark blue-gray\n card: '#FFFFFF', // White\n cardForeground: '#020617', // Very dark blue-gray\n popover: '#FFFFFF', // White\n popoverForeground: '#020617', // Very dark blue-gray\n primary: '#22C55E', // Green\n primaryForeground: '#FFFFFF', // White\n secondary: '#F1F5F9', // Light gray-blue\n secondaryForeground: '#0F172A', // Dark blue-gray\n muted: '#F1F5F9', // Light gray-blue\n mutedForeground: '#64748B', // Medium gray-blue\n accent: '#F1F5F9', // Light gray-blue\n accentForeground: '#0F172A', // Dark blue-gray\n destructive: '#EF4444', // Red\n destructiveForeground: '#F8FAFC', // Off-white\n border: '#E2E8F0', // Light gray\n input: '#E2E8F0', // Light gray\n ring: '#020617', // Very dark blue-gray\n radius: '0.5rem',\n sidebarBackground: '#FAFAFA', // Off-white\n sidebarForeground: '#334155', // Dark gray-blue\n sidebarPrimary: '#0F172A', // Very dark blue-gray\n sidebarPrimaryForeground: '#FAFAFA', // Off-white\n sidebarAccent: '#F4F4F5', // Light gray\n sidebarAccentForeground: '#0F172A', // Very dark blue-gray\n sidebarBorder: '#E2E8F0', // Light gray\n sidebarRing: '#3B82F6', // Blue\n },\n dark: {\n background: '#020617', // Very dark blue-gray\n foreground: '#F8FAFC', // Off-white\n card: '#020617', // Very dark blue-gray\n cardForeground: '#F8FAFC', // Off-white\n popover: '#020617', // Very dark blue-gray\n popoverForeground: '#F8FAFC', // Off-white\n primary: '#4ADE80', // Bright green\n primaryForeground: '#FFFFFF', // White\n secondary: '#1E293B', // Dark blue-gray\n secondaryForeground: '#F8FAFC', // Off-white\n muted: '#1E293B', // Dark blue-gray\n mutedForeground: '#94A3B8', // Medium gray-blue\n accent: '#1E293B', // Dark blue-gray\n accentForeground: '#F8FAFC', // Off-white\n destructive: '#991B1B', // Dark red\n destructiveForeground: '#F8FAFC', // Off-white\n border: '#1E293B', // Dark blue-gray\n input: '#1E293B', // Dark blue-gray\n ring: '#CBD5E1', // Light gray-blue\n radius: '0.5rem',\n sidebarBackground: '#0F172A', // Very dark blue-gray\n sidebarForeground: '#F1F5F9', // Light gray-blue\n sidebarPrimary: '#E0E7FF', // Very light blue\n sidebarPrimaryForeground: '#0F172A', // Very dark blue-gray\n sidebarAccent: '#18181B', // Very dark gray\n sidebarAccentForeground: '#F1F5F9', // Light gray-blue\n sidebarBorder: '#18181B', // Very dark gray\n sidebarRing: '#3B82F6', // Blue\n },\n },\n};\n\n/**\n * Blue theme\n * Colors are in hex format (e.g., \"#FFFFFF\" or \"FFFFFF\" for white)\n */\nexport const blueTheme: ThemeDefinition = {\n name: 'blue',\n displayName: 'Blue',\n colors: {\n light: {\n background: '#FFFFFF', // White\n foreground: '#020617', // Very dark blue-gray\n card: '#FFFFFF', // White\n cardForeground: '#020617', // Very dark blue-gray\n popover: '#FFFFFF', // White\n popoverForeground: '#020617', // Very dark blue-gray\n primary: '#3B82F6', // Blue\n primaryForeground: '#FFFFFF', // White\n secondary: '#F1F5F9', // Light gray-blue\n secondaryForeground: '#0F172A', // Dark blue-gray\n muted: '#F1F5F9', // Light gray-blue\n mutedForeground: '#64748B', // Medium gray-blue\n accent: '#F1F5F9', // Light gray-blue\n accentForeground: '#0F172A', // Dark blue-gray\n destructive: '#EF4444', // Red\n destructiveForeground: '#F8FAFC', // Off-white\n border: '#E2E8F0', // Light gray\n input: '#E2E8F0', // Light gray\n ring: '#3B82F6', // Blue\n radius: '0.5rem',\n sidebarBackground: '#FAFAFA', // Off-white\n sidebarForeground: '#334155', // Dark gray-blue\n sidebarPrimary: '#3B82F6', // Blue\n sidebarPrimaryForeground: '#FFFFFF', // White\n sidebarAccent: '#F4F4F5', // Light gray\n sidebarAccentForeground: '#0F172A', // Very dark blue-gray\n sidebarBorder: '#E2E8F0', // Light gray\n sidebarRing: '#3B82F6', // Blue\n },\n dark: {\n background: '#020617', // Very dark blue-gray\n foreground: '#F8FAFC', // Off-white\n card: '#020617', // Very dark blue-gray\n cardForeground: '#F8FAFC', // Off-white\n popover: '#020617', // Very dark blue-gray\n popoverForeground: '#F8FAFC', // Off-white\n primary: '#3B82F6', // Blue\n primaryForeground: '#FFFFFF', // White\n secondary: '#1E293B', // Dark blue-gray\n secondaryForeground: '#F8FAFC', // Off-white\n muted: '#1E293B', // Dark blue-gray\n mutedForeground: '#94A3B8', // Medium gray-blue\n accent: '#1E293B', // Dark blue-gray\n accentForeground: '#F8FAFC', // Off-white\n destructive: '#991B1B', // Dark red\n destructiveForeground: '#F8FAFC', // Off-white\n border: '#1E293B', // Dark blue-gray\n input: '#1E293B', // Dark blue-gray\n ring: '#3B82F6', // Blue\n radius: '0.5rem',\n sidebarBackground: '#0F172A', // Very dark blue-gray\n sidebarForeground: '#F1F5F9', // Light gray-blue\n sidebarPrimary: '#3B82F6', // Blue\n sidebarPrimaryForeground: '#0F172A', // Dark blue-gray\n sidebarAccent: '#18181B', // Very dark gray\n sidebarAccentForeground: '#F1F5F9', // Light gray-blue\n sidebarBorder: '#18181B', // Very dark gray\n sidebarRing: '#3B82F6', // Blue\n },\n },\n};\n\n/**\n * Warm Yellow theme - Custom yellowish theme with warm tones\n * Colors are in hex format (e.g., \"#FFFFFF\" or \"FFFFFF\" for white)\n */\nexport const warmYellowTheme: ThemeDefinition = {\n name: 'warm-yellow',\n displayName: 'Warm Yellow',\n fontFamily: '\"Comic Sans MS\", \"Comic Sans\", \"Chalkboard SE\", \"Comic Neue\", cursive, sans-serif',\n letterSpacing: '0.02em',\n textShadow: '1px 1px 2px rgba(0, 0, 0, 0.1)',\n lineHeight: '1.6',\n colors: {\n light: {\n background: '#FFF8E7', // Warm cream/yellowish\n foreground: '#3E2723', // Warm dark brown\n card: '#FFFEF5', // Slightly off-white cream\n cardForeground: '#3E2723', // Warm dark brown\n popover: '#FFFEF5', // Slightly off-white cream\n popoverForeground: '#3E2723', // Warm dark brown\n primary: '#F59E0B', // Warm golden amber (complements yellow)\n primaryForeground: '#FFFFFF', // White\n secondary: '#F5E6D3', // Warm beige\n secondaryForeground: '#3E2723', // Warm dark brown\n muted: '#F5E6D3', // Warm beige\n mutedForeground: '#6D4C41', // Medium warm brown\n accent: '#FFE082', // Light warm yellow\n accentForeground: '#3E2723', // Warm dark brown\n destructive: '#E57373', // Soft red (works with warm tones)\n destructiveForeground: '#FFFFFF', // White\n border: '#E8D5B7', // Warm tan border\n input: '#E8D5B7', // Warm tan input border\n ring: '#F59E0B', // Warm golden amber ring\n radius: '0.5rem',\n sidebarBackground: '#FFF5E1', // Slightly warmer cream (subtle contrast with main background)\n sidebarForeground: '#5D4037', // Medium warm brown\n sidebarPrimary: '#F59E0B', // Warm golden amber\n sidebarPrimaryForeground: '#FFFFFF', // White\n sidebarAccent: '#F5E6D3', // Warm beige\n sidebarAccentForeground: '#3E2723', // Warm dark brown\n sidebarBorder: '#E8D5B7', // Warm tan\n sidebarRing: '#F59E0B', // Warm golden amber\n },\n dark: {\n background: '#2E2419', // Dark warm brown\n foreground: '#FFF8E7', // Warm cream (inverted)\n card: '#3E2723', // Dark warm brown\n cardForeground: '#FFF8E7', // Warm cream\n popover: '#3E2723', // Dark warm brown\n popoverForeground: '#FFF8E7', // Warm cream\n primary: '#FBBF24', // Bright golden amber (lighter for dark mode)\n primaryForeground: '#FFFFFF', // White for better contrast\n secondary: '#4E342E', // Medium dark warm brown\n secondaryForeground: '#FFF8E7', // Warm cream\n muted: '#4E342E', // Medium dark warm brown\n mutedForeground: '#D7CCC8', // Light warm gray\n accent: '#FFB74D', // Warm orange accent\n accentForeground: '#2E2419', // Dark warm brown for better contrast\n destructive: '#EF5350', // Softer red for dark mode\n destructiveForeground: '#FFF8E7', // Warm cream\n border: '#5D4037', // Medium warm brown border\n input: '#5D4037', // Medium warm brown input border\n ring: '#FBBF24', // Bright golden amber ring\n radius: '0.5rem',\n sidebarBackground: '#35281F', // Slightly warmer dark brown (subtle contrast with main background)\n sidebarForeground: '#D7CCC8', // Light warm gray\n sidebarPrimary: '#FBBF24', // Bright golden amber\n sidebarPrimaryForeground: '#2E2419', // Dark warm brown for better contrast\n sidebarAccent: '#4E342E', // Medium dark warm brown\n sidebarAccentForeground: '#FFF8E7', // Warm cream\n sidebarBorder: '#5D4037', // Medium warm brown\n sidebarRing: '#FBBF24', // Bright golden amber\n },\n },\n};\n\n/**\n * Registry of all available themes\n */\nconst themeRegistry = new Map<string, ThemeDefinition>([\n ['default', defaultTheme],\n ['blue', blueTheme],\n ['warm-yellow', warmYellowTheme],\n]);\n\n/**\n * Register a custom theme\n */\nexport function registerTheme(theme: ThemeDefinition): void {\n themeRegistry.set(theme.name, theme);\n}\n\n/**\n * Get a theme by name\n */\nexport function getTheme(name: string): ThemeDefinition | undefined {\n return themeRegistry.get(name);\n}\n\n/**\n * Get all available themes\n */\nexport function getAllThemes(): ThemeDefinition[] {\n return Array.from(themeRegistry.values());\n}\n\n/**\n * Apply theme colors to the document\n * Converts hex format colors to HSL format for CSS variables\n * Sets variables directly on :root to ensure they override CSS defaults\n */\nexport function applyTheme(theme: ThemeDefinition, isDark: boolean): void {\n if (typeof document === 'undefined') {\n return;\n }\n\n const root = document.documentElement;\n const colors = isDark ? theme.colors.dark : theme.colors.light;\n\n // Convert hex to HSL for all colors\n const primaryHsl = hexToHsl(colors.primary);\n\n // Apply CSS variables directly on :root element\n // Inline styles have the highest specificity and will override CSS defaults\n // Format: HSL values without hsl() wrapper (e.g., \"142 71% 45%\")\n root.style.setProperty('--background', hexToHsl(colors.background));\n root.style.setProperty('--foreground', hexToHsl(colors.foreground));\n root.style.setProperty('--card', hexToHsl(colors.card));\n root.style.setProperty('--card-foreground', hexToHsl(colors.cardForeground));\n root.style.setProperty('--popover', hexToHsl(colors.popover));\n root.style.setProperty('--popover-foreground', hexToHsl(colors.popoverForeground));\n root.style.setProperty('--primary', primaryHsl);\n root.style.setProperty('--primary-foreground', hexToHsl(colors.primaryForeground));\n root.style.setProperty('--secondary', hexToHsl(colors.secondary));\n root.style.setProperty('--secondary-foreground', hexToHsl(colors.secondaryForeground));\n root.style.setProperty('--muted', hexToHsl(colors.muted));\n root.style.setProperty('--muted-foreground', hexToHsl(colors.mutedForeground));\n root.style.setProperty('--accent', hexToHsl(colors.accent));\n root.style.setProperty('--accent-foreground', hexToHsl(colors.accentForeground));\n root.style.setProperty('--destructive', hexToHsl(colors.destructive));\n root.style.setProperty('--destructive-foreground', hexToHsl(colors.destructiveForeground));\n root.style.setProperty('--border', hexToHsl(colors.border));\n root.style.setProperty('--input', hexToHsl(colors.input));\n root.style.setProperty('--ring', hexToHsl(colors.ring));\n root.style.setProperty('--radius', colors.radius); // radius is not a color\n root.style.setProperty('--sidebar-background', hexToHsl(colors.sidebarBackground));\n root.style.setProperty('--sidebar-foreground', hexToHsl(colors.sidebarForeground));\n root.style.setProperty('--sidebar-primary', hexToHsl(colors.sidebarPrimary));\n root.style.setProperty('--sidebar-primary-foreground', hexToHsl(colors.sidebarPrimaryForeground));\n root.style.setProperty('--sidebar-accent', hexToHsl(colors.sidebarAccent));\n root.style.setProperty('--sidebar-accent-foreground', hexToHsl(colors.sidebarAccentForeground));\n root.style.setProperty('--sidebar-border', hexToHsl(colors.sidebarBorder));\n root.style.setProperty('--sidebar-ring', hexToHsl(colors.sidebarRing));\n\n // Load custom font files if provided\n // Always clean up existing theme fonts first (for theme switching)\n const head = document.head || document.getElementsByTagName('head')[0];\n const existingFontLinks = head.querySelectorAll('link[data-theme-font], style[data-theme-font]');\n existingFontLinks.forEach((link) => link.remove());\n\n if (theme.fontFiles && theme.fontFiles.length > 0) {\n theme.fontFiles.forEach((fontFile, index) => {\n // Check if it's a Google Fonts link or a regular stylesheet\n if (fontFile.includes('fonts.googleapis.com') || fontFile.endsWith('.css')) {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = fontFile;\n link.setAttribute('data-theme-font', theme.name);\n head.appendChild(link);\n } else {\n // Assume it's a font file URL - create @font-face rule\n const style = document.createElement('style');\n style.setAttribute('data-theme-font', theme.name);\n // Extract font name from URL or use a generic name\n const fontName = `ThemeFont-${theme.name}-${index}`;\n style.textContent = `\n @font-face {\n font-family: '${fontName}';\n src: url('${fontFile}') format('woff2');\n }\n `;\n head.appendChild(style);\n }\n });\n }\n\n // Apply custom font families\n // Priority: headingFontFamily/bodyFontFamily > fontFamily (backward compatible)\n const bodyFont = theme.bodyFontFamily || theme.fontFamily;\n const headingFont = theme.headingFontFamily || theme.fontFamily || bodyFont;\n\n if (bodyFont) {\n root.style.setProperty('--body-font-family', bodyFont);\n root.style.setProperty('--font-family', bodyFont); // Backward compatibility\n document.body.style.fontFamily = bodyFont;\n } else {\n root.style.removeProperty('--body-font-family');\n root.style.removeProperty('--font-family');\n document.body.style.fontFamily = '';\n }\n\n if (headingFont) {\n root.style.setProperty('--heading-font-family', headingFont);\n // Apply to headings via CSS variable (will be used in CSS)\n } else {\n root.style.removeProperty('--heading-font-family');\n }\n\n // Apply optional font styling properties generically\n if (theme.letterSpacing) {\n root.style.setProperty('--letter-spacing', theme.letterSpacing);\n root.style.letterSpacing = theme.letterSpacing;\n } else {\n root.style.removeProperty('--letter-spacing');\n root.style.letterSpacing = '';\n }\n\n if (theme.textShadow) {\n root.style.setProperty('--text-shadow', theme.textShadow);\n // Apply slightly lighter shadow to body for better readability\n const bodyShadow = theme.textShadow.replace(/rgba\\(([^)]+)\\)/, (match, rgba) => {\n // Reduce opacity by ~20% for body text\n const values = rgba.split(',').map((v: string) => v.trim());\n if (values.length === 4) {\n const opacity = parseFloat(values[3]);\n return `rgba(${values[0]}, ${values[1]}, ${values[2]}, ${Math.max(0, opacity * 0.8)})`;\n }\n return match;\n });\n document.body.style.textShadow = bodyShadow;\n } else {\n root.style.removeProperty('--text-shadow');\n document.body.style.textShadow = '';\n }\n\n if (theme.lineHeight) {\n root.style.setProperty('--line-height', theme.lineHeight);\n document.body.style.lineHeight = theme.lineHeight;\n } else {\n root.style.removeProperty('--line-height');\n document.body.style.lineHeight = '';\n }\n\n // Verify primary color is set (for debugging)\n const actualPrimary = root.style.getPropertyValue('--primary');\n\n // Validate HSL format (should be \"H S% L%\" like \"142 71% 45%\")\n const hslFormat = /^\\d+(\\.\\d+)?\\s+\\d+(\\.\\d+)?%\\s+\\d+(\\.\\d+)?%$/;\n\n if (!actualPrimary || actualPrimary.trim() === '') {\n console.error(\n `[Theme] Failed to set --primary CSS variable. Expected HSL from ${colors.primary}, got: \"${actualPrimary}\"`,\n );\n } else if (!hslFormat.test(actualPrimary.trim())) {\n console.error(\n `[Theme] Invalid HSL format for --primary: \"${actualPrimary}\". Expected format: \"H S% L%\"`,\n );\n }\n\n // Force a reflow to ensure Tailwind picks up the changes\n // This is sometimes needed for Tailwind v4 to recognize CSS variable changes\n void root.offsetHeight;\n}\n","/* eslint-disable no-console */\nimport { useLayoutEffect } from 'react';\nimport { useSettings } from '../settings/hooks/useSettings';\nimport { useConfig } from '../config/useConfig';\nimport { getTheme, registerTheme, applyTheme, type ThemeDefinition } from './themes';\n\n/**\n * Apply theme to document element\n */\nfunction applyThemeToDocument(isDark: boolean) {\n const root = document.documentElement;\n if (isDark) {\n root.classList.add('dark');\n } else {\n root.classList.remove('dark');\n }\n}\n\n/**\n * Hook to apply theme based on settings\n * Applies 'dark' class to document.documentElement based on:\n * - 'light': removes dark class\n * - 'dark': adds dark class\n * - 'system': follows prefers-color-scheme media query\n * Also applies theme colors based on themeName setting\n */\nexport function useTheme() {\n const { settings } = useSettings();\n const { config } = useConfig();\n const theme = settings.appearance?.theme || 'system';\n const themeName = settings.appearance?.themeName || 'default';\n\n // Apply theme immediately on mount (synchronously) to prevent empty colors\n // This ensures CSS variables are set before first render\n useLayoutEffect(() => {\n // Get the effective theme name (from settings or config)\n // Use themeName from settings first, then config defaultTheme, then 'default'\n const effectiveThemeName = themeName || config?.defaultTheme || 'default';\n\n if (config?.themes) {\n config.themes.forEach((themeDef: ThemeDefinition) => {\n registerTheme(themeDef);\n });\n }\n\n const themeDefinition = getTheme(effectiveThemeName) || getTheme('default');\n\n if (themeDefinition) {\n const determineIsDark = () => {\n if (theme === 'system') {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n return mediaQuery.matches;\n }\n return theme === 'dark';\n };\n const isDark = determineIsDark();\n applyThemeToDocument(isDark);\n applyTheme(themeDefinition, isDark);\n } else {\n console.error('[Theme] No theme definition found, using fallback');\n // Fallback: at least set primary color from default theme\n const defaultTheme = getTheme('default');\n if (defaultTheme) {\n const isDark =\n theme === 'dark' ||\n (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);\n applyTheme(defaultTheme, isDark);\n }\n }\n }, [theme, themeName, config]); // Run when theme, themeName, or config changes\n}\n","import type { ReactNode } from 'react';\nimport { useTheme } from './useTheme';\n\nexport interface ThemeProviderProps {\n children: ReactNode;\n}\n\n/**\n * Provider that applies theme (light/dark/system and theme colors) from settings.\n * Must be rendered inside SettingsProvider so useTheme can read appearance settings.\n * Applies theme to document.documentElement and listens to system preference changes.\n */\nexport function ThemeProvider({ children }: ThemeProviderProps) {\n useTheme();\n return <>{children}</>;\n}\n","import i18n from 'i18next';\nimport { initReactI18next } from 'react-i18next';\nimport enCommon from './translations/en/common.json';\nimport enSettings from './translations/en/settings.json';\nimport enCookieConsent from './translations/en/cookieConsent.json';\nimport frCommon from './translations/fr/common.json';\nimport frSettings from './translations/fr/settings.json';\nimport frCookieConsent from './translations/fr/cookieConsent.json';\n\nexport const allSupportedLanguages = [\n { code: 'en', name: 'English', nativeName: 'English' },\n { code: 'fr', name: 'French', nativeName: 'Français' },\n] as const;\n\nexport type SupportedLanguage = (typeof allSupportedLanguages)[number]['code'];\n\nconst resources = {\n en: {\n common: enCommon,\n settings: enSettings,\n cookieConsent: enCookieConsent,\n },\n fr: {\n common: frCommon,\n settings: frSettings,\n cookieConsent: frCookieConsent,\n },\n};\n\n// Get initial language from localStorage if available\nconst getInitialLanguage = (enabledLanguages: string[]): SupportedLanguage => {\n if (typeof window !== 'undefined') {\n try {\n const stored = localStorage.getItem('shellui:settings');\n if (stored) {\n const parsed = JSON.parse(stored);\n const languageCode = parsed.language?.code;\n // Only use stored language if it's in the enabled languages list\n if (languageCode && enabledLanguages.includes(languageCode)) {\n return languageCode as SupportedLanguage;\n }\n }\n } catch (_error) {\n // Ignore errors, fall back to default\n }\n }\n // Fallback to first enabled language or 'en'\n return (enabledLanguages[0] || 'en') as SupportedLanguage;\n};\n\n// Initialize i18n with default settings (will be updated when config loads)\nlet isInitialized = false;\n\nexport const initializeI18n = (enabledLanguages?: string | string[]) => {\n // Normalize to array\n const enabledLangs = enabledLanguages\n ? Array.isArray(enabledLanguages)\n ? enabledLanguages\n : [enabledLanguages]\n : allSupportedLanguages.map((lang) => lang.code);\n\n // Filter to only include languages we have translations for\n const validLangs = enabledLangs.filter((lang) =>\n allSupportedLanguages.some((supported) => supported.code === lang),\n );\n\n // Ensure at least 'en' is available\n const finalLangs = validLangs.length > 0 ? validLangs : ['en'];\n const initialLang = getInitialLanguage(finalLangs);\n\n if (!isInitialized) {\n i18n.use(initReactI18next).init({\n resources,\n defaultNS: 'common',\n lng: initialLang,\n fallbackLng: 'en',\n supportedLngs: finalLangs,\n interpolation: {\n escapeValue: false, // React already escapes values\n },\n react: {\n useSuspense: false, // Disable suspense for better PWA compatibility\n },\n });\n isInitialized = true;\n } else {\n // Update supported languages if config changes\n i18n.changeLanguage(initialLang);\n }\n\n return finalLangs;\n};\n\n// Initialize with all languages by default (will be filtered when config loads)\ninitializeI18n();\n\nexport const getSupportedLanguages = (enabledLanguages?: string | string[]) => {\n const enabledLangs = enabledLanguages\n ? Array.isArray(enabledLanguages)\n ? enabledLanguages\n : [enabledLanguages]\n : allSupportedLanguages.map((lang) => lang.code);\n\n return allSupportedLanguages.filter((lang) => enabledLangs.includes(lang.code));\n};\n\nexport default i18n;\n","import { useEffect, type ReactNode } from 'react';\nimport { useSettings } from '../features/settings/hooks/useSettings';\nimport i18n, { initializeI18n } from './config';\nimport type { ShellUIConfig } from '../features/config/types';\nimport { useConfig } from '../features/config/useConfig';\n\ninterface I18nProviderProps {\n children: ReactNode;\n config?: ShellUIConfig;\n}\n\nexport function I18nProvider({ children }: I18nProviderProps) {\n const { settings } = useSettings();\n const { config } = useConfig();\n const currentLanguage = settings.language?.code || 'en';\n\n // Initialize i18n with enabled languages from config\n useEffect(() => {\n if (config?.language) {\n initializeI18n(config.language);\n }\n }, [config?.language]);\n\n // Sync i18n language with settings changes\n useEffect(() => {\n if (i18n.language !== currentLanguage) {\n i18n.changeLanguage(currentLanguage);\n }\n }, [currentLanguage]);\n\n return <>{children}</>;\n}\n","/**\n * Central z-index scale for overlay layers.\n * Order (bottom to top): modal/drawer → toast → alert-dialog.\n * Use these constants everywhere so stacking stays consistent.\n */\nexport const Z_INDEX = {\n /** Sidebar trigger (above main content, below modals) */\n SIDEBAR_TRIGGER: 9999,\n /** Modal overlay and content (settings panel, etc.) */\n MODAL_OVERLAY: 10000,\n MODAL_CONTENT: 10001,\n /** Drawer overlay and content (slide-out panels; same level as modal) */\n DRAWER_OVERLAY: 10000,\n DRAWER_CONTENT: 10001,\n /** Toasts (above modals so they stay clickable when modal is open) */\n TOAST: 10100,\n /** Alert dialog overlay and content (confirmations; above toasts) */\n ALERT_DIALOG_OVERLAY: 10200,\n ALERT_DIALOG_CONTENT: 10201,\n /** Cookie consent (above everything to ensure visibility) */\n COOKIE_CONSENT_OVERLAY: 10300,\n COOKIE_CONSENT_CONTENT: 10301,\n /** Windows layout: taskbar (below windows), windows use dynamic z-index above this */\n WINDOWS_TASKBAR: 9000,\n /** Base z-index for windows; each window gets base + order */\n WINDOWS_WINDOW_BASE: 9001,\n} as const;\n\nexport type ZIndexLayer = keyof typeof Z_INDEX;\n","import {\n forwardRef,\n type ElementRef,\n type ComponentPropsWithoutRef,\n type HTMLAttributes,\n} from 'react';\nimport * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '@/lib/utils';\nimport { Z_INDEX } from '@/lib/z-index';\nimport { Button, type ButtonProps } from '@/components/ui/button';\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = forwardRef<\n ElementRef<typeof AlertDialogPrimitive.Overlay>,\n ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n ref={ref}\n data-dialog-overlay\n className={cn('fixed inset-0 bg-[hsl(var(--background)/0.8)] backdrop-blur-[1px]', className)}\n style={{ zIndex: Z_INDEX.ALERT_DIALOG_OVERLAY }}\n {...props}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst alertDialogContentVariants = cva(\n 'fixed left-[50%] top-[50%] grid w-full min-w-0 max-w-[calc(100vw-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background py-6 shadow-lg box-border overflow-hidden sm:rounded-lg',\n {\n variants: {\n size: {\n default: 'max-w-lg',\n sm: 'max-w-sm',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n },\n);\n\ninterface AlertDialogContentProps\n extends\n ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>,\n VariantProps<typeof alertDialogContentVariants> {}\n\nconst AlertDialogContent = forwardRef<\n ElementRef<typeof AlertDialogPrimitive.Content>,\n AlertDialogContentProps\n>(({ className, size = 'default', children, style, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n data-dialog-content\n className={cn(alertDialogContentVariants({ size }), 'group', className)}\n data-size={size}\n style={{ zIndex: Z_INDEX.ALERT_DIALOG_CONTENT, ...style }}\n {...props}\n >\n {children}\n </AlertDialogPrimitive.Content>\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex flex-col px-6 space-y-2 text-left group-data-[size=sm]:items-center group-data-[size=sm]:text-center',\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = 'AlertDialogHeader';\n\nconst AlertDialogMedia = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex size-10 shrink-0 items-center justify-center rounded-lg mb-4 [&>svg]:size-5',\n className,\n )}\n {...props}\n />\n);\nAlertDialogMedia.displayName = 'AlertDialogMedia';\n\nconst AlertDialogFooter = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n 'flex w-full min-w-full flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',\n '-mb-6 mt-2 border-t border-border bg-muted/50 px-6 py-3 sm:rounded-b-lg',\n '[&_button]:h-8 [&_button]:text-xs [&_button]:px-3',\n 'group-data-[size=sm]:flex-row group-data-[size=sm]:gap-2',\n 'group-data-[size=sm]:[&>*:not(:only-child)]:min-w-0 group-data-[size=sm]:[&>*:not(:only-child)]:flex-1',\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = 'AlertDialogFooter';\n\nconst AlertDialogTitle = forwardRef<\n ElementRef<typeof AlertDialogPrimitive.Title>,\n ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn('text-lg font-semibold leading-none tracking-tight', className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = forwardRef<\n ElementRef<typeof AlertDialogPrimitive.Description>,\n ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = forwardRef<\n ElementRef<typeof AlertDialogPrimitive.Action>,\n ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action> &\n Pick<ButtonProps, 'variant' | 'size'>\n>(({ className, variant, size, ...props }, ref) => (\n <AlertDialogPrimitive.Action asChild>\n <Button\n ref={ref}\n variant={variant}\n size={size}\n className={className}\n {...props}\n />\n </AlertDialogPrimitive.Action>\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = forwardRef<\n ElementRef<typeof AlertDialogPrimitive.Cancel>,\n ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel> &\n Pick<ButtonProps, 'variant' | 'size'>\n>(({ className, variant, size, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel asChild>\n <Button\n ref={ref}\n variant={variant}\n size={size}\n className={className}\n {...props}\n />\n </AlertDialogPrimitive.Cancel>\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogMedia,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n","import { shellui, type ShellUIMessage, type DialogOptions } from '@shellui/sdk';\nimport {\n createContext,\n useContext,\n useCallback,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { Button } from '@/components/ui/button';\nimport { Z_INDEX } from '@/lib/z-index';\n\n/** Match exit animation duration in index.css (overlay + content ~0.1s + buffer) */\nconst DIALOG_EXIT_ANIMATION_MS = 200;\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogMedia,\n AlertDialogTitle,\n AlertDialogOverlay,\n AlertDialogPortal,\n} from '@/components/ui/alert-dialog';\nimport * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';\n\n/** Trash icon (matches lucide trash-2) */\nconst TrashIcon = () => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <path d=\"M3 6h18\" />\n <path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\" />\n <path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\" />\n <line\n x1=\"10\"\n x2=\"10\"\n y1=\"11\"\n y2=\"17\"\n />\n <line\n x1=\"14\"\n x2=\"14\"\n y1=\"11\"\n y2=\"17\"\n />\n </svg>\n);\n\n/** Cookie icon for cookie consent */\nconst CookieIcon = ({ className }: { className?: string }) => (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 256 256\"\n fill=\"currentColor\"\n className={className}\n >\n <path d=\"M164.49 163.51a12 12 0 1 1-17 0a12 12 0 0 1 17 0m-81-8a12 12 0 1 0 17 0a12 12 0 0 0-16.98 0Zm9-39a12 12 0 1 0-17 0a12 12 0 0 0 17-.02Zm48-1a12 12 0 1 0 0 17a12 12 0 0 0 0-17M232 128A104 104 0 1 1 128 24a8 8 0 0 1 8 8a40 40 0 0 0 40 40a8 8 0 0 1 8 8a40 40 0 0 0 40 40a8 8 0 0 1 8 8m-16.31 7.39A56.13 56.13 0 0 1 168.5 87.5a56.13 56.13 0 0 1-47.89-47.19a88 88 0 1 0 95.08 95.08\" />\n </svg>\n);\n\ninterface DialogContextValue {\n dialog: (options: DialogOptions) => void;\n}\n\nconst DialogContext = createContext<DialogContextValue | undefined>(undefined);\n\nexport function useDialog() {\n const context = useContext(DialogContext);\n if (!context) {\n throw new Error('useDialog must be used within a DialogProvider');\n }\n return context;\n}\n\ninterface DialogProviderProps {\n children: ReactNode;\n}\n\ninterface DialogState extends Omit<DialogOptions, 'onOk' | 'onCancel' | 'icon'> {\n id: string;\n mode: DialogOptions['mode'];\n from?: string[];\n iconType?: 'cookie';\n}\n\nexport const DialogProvider = ({ children }: DialogProviderProps) => {\n const [dialogState, setDialogState] = useState<DialogState | null>(null);\n const [isOpen, setIsOpen] = useState(false);\n const unmountTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const scheduleUnmount = useCallback(() => {\n if (unmountTimeoutRef.current) clearTimeout(unmountTimeoutRef.current);\n unmountTimeoutRef.current = setTimeout(() => {\n unmountTimeoutRef.current = null;\n setDialogState(null);\n }, DIALOG_EXIT_ANIMATION_MS);\n }, []);\n\n const handleOpenChange = useCallback(\n (open: boolean) => {\n setIsOpen(open);\n if (!open && dialogState) {\n // If dialog was closed without clicking a button (X button or outside click),\n // trigger cancel callback if it exists\n if (dialogState.from && dialogState.from.length > 0) {\n shellui.sendMessage({\n type: 'SHELLUI_DIALOG_CANCEL',\n payload: { id: dialogState.id },\n to: dialogState.from,\n });\n } else if (dialogState.id) {\n // Dialog opened from root window - trigger callback directly\n shellui.callbackRegistry.triggerCancel(dialogState.id);\n shellui.callbackRegistry.clear(dialogState.id);\n }\n // Unmount after exit animation finishes\n scheduleUnmount();\n }\n },\n [dialogState, scheduleUnmount],\n );\n\n const handleOk = useCallback(() => {\n if (dialogState?.from && dialogState.from.length > 0) {\n shellui.sendMessage({\n type: 'SHELLUI_DIALOG_OK',\n payload: { id: dialogState.id },\n to: dialogState.from,\n });\n } else if (dialogState?.id) {\n // Dialog opened from root window - trigger callback directly\n shellui.callbackRegistry.triggerAction(dialogState.id);\n shellui.callbackRegistry.clear(dialogState.id);\n }\n setIsOpen(false);\n scheduleUnmount();\n }, [dialogState, scheduleUnmount]);\n\n const handleCancel = useCallback(() => {\n if (dialogState?.from && dialogState.from.length > 0) {\n shellui.sendMessage({\n type: 'SHELLUI_DIALOG_CANCEL',\n payload: { id: dialogState.id },\n to: dialogState.from,\n });\n } else if (dialogState?.id) {\n // Dialog opened from root window - trigger callback directly\n shellui.callbackRegistry.triggerCancel(dialogState.id);\n shellui.callbackRegistry.clear(dialogState.id);\n }\n setIsOpen(false);\n scheduleUnmount();\n }, [dialogState, scheduleUnmount]);\n\n const handleSecondary = useCallback(() => {\n if (dialogState?.from && dialogState.from.length > 0) {\n shellui.sendMessage({\n type: 'SHELLUI_DIALOG_SECONDARY',\n payload: { id: dialogState.id },\n to: dialogState.from,\n });\n } else if (dialogState?.id) {\n // Dialog opened from root window - trigger callback directly\n shellui.callbackRegistry.triggerSecondary(dialogState.id);\n shellui.callbackRegistry.clear(dialogState.id);\n }\n setIsOpen(false);\n scheduleUnmount();\n }, [dialogState, scheduleUnmount]);\n\n const dialog = useCallback((options: DialogOptions) => {\n // Only show dialog if window is root\n if (typeof window === 'undefined' || window.parent !== window) {\n return;\n }\n if (unmountTimeoutRef.current) {\n clearTimeout(unmountTimeoutRef.current);\n unmountTimeoutRef.current = null;\n }\n\n const dialogId = options.id || `dialog-${Date.now()}-${Math.random()}`;\n\n // Register callbacks for direct calls (not from iframe)\n if (options.onOk || options.onCancel || options.secondaryButton?.onClick) {\n shellui.callbackRegistry.register(dialogId, {\n action: options.onOk,\n cancel: options.onCancel,\n secondary: options.secondaryButton?.onClick,\n });\n }\n\n setDialogState({\n id: dialogId,\n title: options.title,\n description: options.description,\n mode: options.mode || 'ok',\n okLabel: options.okLabel,\n cancelLabel: options.cancelLabel,\n size: options.size,\n position: options.position,\n secondaryButton: options.secondaryButton,\n iconType: options.icon === 'cookie' ? 'cookie' : undefined,\n });\n setIsOpen(true);\n }, []);\n\n // Listen for postMessage events from nested iframes\n useEffect(() => {\n // Only listen if window is root\n if (typeof window === 'undefined' || window.parent !== window) {\n return;\n }\n\n const cleanupDialog = shellui.addMessageListener('SHELLUI_DIALOG', (data: ShellUIMessage) => {\n if (unmountTimeoutRef.current) {\n clearTimeout(unmountTimeoutRef.current);\n unmountTimeoutRef.current = null;\n }\n const payload = data.payload as DialogOptions & { id: string };\n setDialogState({\n id: payload.id,\n title: payload.title,\n description: payload.description,\n mode: payload.mode || 'ok',\n okLabel: payload.okLabel,\n cancelLabel: payload.cancelLabel,\n size: payload.size,\n position: payload.position,\n secondaryButton: payload.secondaryButton,\n iconType: payload.icon === 'cookie' ? 'cookie' : undefined,\n from: data.from,\n });\n setIsOpen(true);\n });\n\n const cleanupDialogUpdate = shellui.addMessageListener(\n 'SHELLUI_DIALOG_UPDATE',\n (data: ShellUIMessage) => {\n if (unmountTimeoutRef.current) {\n clearTimeout(unmountTimeoutRef.current);\n unmountTimeoutRef.current = null;\n }\n const payload = data.payload as DialogOptions & { id: string };\n setDialogState({\n id: payload.id,\n title: payload.title,\n description: payload.description,\n mode: payload.mode || 'ok',\n okLabel: payload.okLabel,\n cancelLabel: payload.cancelLabel,\n size: payload.size,\n position: payload.position,\n secondaryButton: payload.secondaryButton,\n iconType: payload.icon === 'cookie' ? 'cookie' : undefined,\n from: data.from,\n });\n setIsOpen(true);\n },\n );\n\n return () => {\n cleanupDialog();\n cleanupDialogUpdate();\n if (unmountTimeoutRef.current) clearTimeout(unmountTimeoutRef.current);\n };\n }, []);\n\n const renderButtons = () => {\n if (!dialogState) return null;\n\n const { mode, okLabel, cancelLabel, secondaryButton } = dialogState;\n\n // Cookie consent layout: secondary button on left, primary buttons on right\n if (secondaryButton && dialogState.position === 'bottom-left') {\n return (\n <>\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={handleSecondary}\n >\n {secondaryButton.label}\n </Button>\n <div className=\"flex gap-2\">\n {mode === 'okCancel' && (\n <Button\n size=\"sm\"\n variant=\"ghost\"\n onClick={handleCancel}\n >\n {cancelLabel || 'Cancel'}\n </Button>\n )}\n <Button\n size=\"sm\"\n onClick={handleOk}\n >\n {okLabel || 'OK'}\n </Button>\n </div>\n </>\n );\n }\n\n switch (mode) {\n case 'ok':\n return <AlertDialogAction onClick={handleOk}>{okLabel || 'OK'}</AlertDialogAction>;\n\n case 'okCancel':\n return (\n <>\n <AlertDialogCancel\n variant=\"outline\"\n onClick={handleCancel}\n >\n {cancelLabel || 'Cancel'}\n </AlertDialogCancel>\n <AlertDialogAction onClick={handleOk}>{okLabel || 'OK'}</AlertDialogAction>\n </>\n );\n\n case 'delete':\n return (\n <>\n <AlertDialogCancel\n variant=\"outline\"\n onClick={handleCancel}\n >\n {cancelLabel || 'Cancel'}\n </AlertDialogCancel>\n <AlertDialogAction\n variant=\"destructive\"\n onClick={handleOk}\n >\n {okLabel || 'Delete'}\n </AlertDialogAction>\n </>\n );\n\n case 'confirm':\n return (\n <>\n <AlertDialogCancel\n variant=\"outline\"\n onClick={handleCancel}\n >\n {cancelLabel || 'Cancel'}\n </AlertDialogCancel>\n <AlertDialogAction onClick={handleOk}>{okLabel || 'Confirm'}</AlertDialogAction>\n </>\n );\n\n case 'onlyCancel':\n return (\n <AlertDialogCancel\n variant=\"outline\"\n onClick={handleCancel}\n >\n {cancelLabel || 'Cancel'}\n </AlertDialogCancel>\n );\n\n default:\n return <AlertDialogAction onClick={handleOk}>{okLabel || 'OK'}</AlertDialogAction>;\n }\n };\n\n // Render cookie consent dialog with custom layout\n const renderCookieConsentDialog = () => {\n if (!dialogState || dialogState.position !== 'bottom-left') return null;\n\n return (\n <AlertDialog\n open={isOpen}\n onOpenChange={handleOpenChange}\n >\n <AlertDialogPortal>\n <AlertDialogOverlay style={{ zIndex: Z_INDEX.COOKIE_CONSENT_OVERLAY }} />\n <AlertDialogPrimitive.Content\n className=\"fixed w-[calc(100%-32px)] max-w-[520px] rounded-xl border border-border bg-background text-foreground shadow-lg sm:w-full\"\n style={{\n bottom: 16,\n left: 16,\n zIndex: Z_INDEX.COOKIE_CONSENT_CONTENT,\n backgroundColor: 'hsl(var(--background))',\n top: 'auto',\n right: 'auto',\n transform: 'none',\n }}\n data-dialog-content\n data-cookie-consent\n >\n <div className=\"flex items-start gap-4 p-6 sm:gap-5 sm:p-7\">\n {dialogState.iconType === 'cookie' && (\n <div\n className=\"flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10\"\n aria-hidden\n >\n <CookieIcon className=\"h-5 w-5 text-primary\" />\n </div>\n )}\n <div className=\"flex-1 space-y-2\">\n <AlertDialogTitle className=\"text-base font-semibold leading-tight\">\n {dialogState.title}\n </AlertDialogTitle>\n {dialogState.description && (\n <AlertDialogDescription className=\"text-sm leading-relaxed\">\n {dialogState.description}\n </AlertDialogDescription>\n )}\n </div>\n </div>\n <div className=\"flex items-center justify-between rounded-b-xl border-t border-border bg-muted/50 px-6 py-4 sm:px-7\">\n {renderButtons()}\n </div>\n </AlertDialogPrimitive.Content>\n </AlertDialogPortal>\n </AlertDialog>\n );\n };\n\n return (\n <DialogContext.Provider value={{ dialog }}>\n {children}\n {dialogState && (\n <>\n {dialogState.position === 'bottom-left' ? (\n renderCookieConsentDialog()\n ) : (\n <AlertDialog\n open={isOpen}\n onOpenChange={handleOpenChange}\n >\n <AlertDialogContent size={dialogState.size ?? 'default'}>\n <AlertDialogHeader>\n {dialogState.mode === 'delete' && (\n <AlertDialogMedia className=\"bg-destructive/10 text-destructive dark:bg-destructive/20 dark:text-destructive\">\n <TrashIcon />\n </AlertDialogMedia>\n )}\n <AlertDialogTitle>{dialogState.title}</AlertDialogTitle>\n {dialogState.description && (\n <AlertDialogDescription>{dialogState.description}</AlertDialogDescription>\n )}\n </AlertDialogHeader>\n <AlertDialogFooter>{renderButtons()}</AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n )}\n </>\n )}\n </DialogContext.Provider>\n );\n};\n","import { useRef, useCallback, useEffect } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { shellui } from '@shellui/sdk';\nimport { useDialog } from '../alertDialog/DialogContext';\nimport { useConfig } from '../config/useConfig';\nimport { useSettings } from '../settings/hooks/useSettings';\nimport urls from '@/constants/urls';\n\n/**\n * Shows a friendly cookie consent modal on first visit (when user has not yet consented).\n * Accept all / Reject all only. Closing via Escape or overlay counts as Reject.\n */\nexport function CookieConsentModal() {\n const { t } = useTranslation('cookieConsent');\n const { config } = useConfig();\n const { settings, updateSetting } = useSettings();\n const { dialog: showDialog } = useDialog();\n const closedByChoiceRef = useRef(false);\n const dialogShownRef = useRef(false);\n\n const cookieConsent = config?.cookieConsent;\n const cookies = cookieConsent?.cookies ?? [];\n const consentedHosts = settings?.cookieConsent?.consentedCookieHosts ?? [];\n const allHosts = cookies.map((c) => c.host);\n const strictNecessaryHosts = cookies\n .filter((c) => c.category === 'strict_necessary')\n .map((c) => c.host);\n\n // Check if there are new cookies that weren't in the list when user last consented\n const hasNewCookies = allHosts.some((host) => !consentedHosts.includes(host));\n const neverConsented = consentedHosts.length === 0;\n const isRenewal = !neverConsented && hasNewCookies;\n\n // Only show in root window, not in sub-apps (iframes)\n const isRootWindow = typeof window !== 'undefined' && window.parent === window;\n // Show if: has cookies AND (never consented OR new cookies added)\n const shouldShow = isRootWindow && cookies.length > 0 && (neverConsented || hasNewCookies);\n\n // Use renewal text if showing due to cookie policy update\n const title = isRenewal ? t('titleRenewal') : t('title');\n const description = isRenewal ? t('descriptionRenewal') : t('description');\n\n const saveAccept = useCallback(() => {\n updateSetting('cookieConsent', {\n acceptedHosts: allHosts,\n consentedCookieHosts: allHosts,\n });\n }, [allHosts, updateSetting]);\n\n const saveReject = useCallback(() => {\n updateSetting('cookieConsent', {\n acceptedHosts: strictNecessaryHosts,\n consentedCookieHosts: allHosts,\n });\n }, [strictNecessaryHosts, allHosts, updateSetting]);\n\n const handleAccept = useCallback(() => {\n closedByChoiceRef.current = true;\n saveAccept();\n }, [saveAccept]);\n\n const handleReject = useCallback(() => {\n closedByChoiceRef.current = true;\n saveReject();\n }, [saveReject]);\n\n const handleSetPreferences = useCallback(() => {\n closedByChoiceRef.current = true;\n shellui.openDrawer({ url: `${urls.cookiePreferences}?initial=true`, size: '420px' });\n }, []);\n\n // Show/hide dialog based on shouldShow\n useEffect(() => {\n if (!shouldShow) {\n dialogShownRef.current = false;\n return;\n }\n\n // Prevent showing dialog multiple times\n if (dialogShownRef.current) {\n return;\n }\n\n // Mark as shown to prevent duplicate calls\n dialogShownRef.current = true;\n\n // Close any open modals/drawers when cookie consent is shown\n shellui.propagateMessage({ type: 'SHELLUI_CLOSE_MODAL', payload: {} });\n shellui.propagateMessage({ type: 'SHELLUI_CLOSE_DRAWER', payload: {} });\n\n // Reset choice ref when showing dialog\n closedByChoiceRef.current = false;\n\n // Show dialog using DialogContext directly (for root window)\n showDialog({\n title,\n description,\n mode: 'okCancel',\n okLabel: t('accept'),\n cancelLabel: t('reject'),\n position: 'bottom-left',\n icon: 'cookie',\n secondaryButton: {\n label: t('setPreferences'),\n onClick: handleSetPreferences,\n },\n onOk: handleAccept,\n onCancel: handleReject,\n });\n }, [\n shouldShow,\n title,\n description,\n t,\n handleAccept,\n handleReject,\n handleSetPreferences,\n showDialog,\n ]);\n\n return null;\n}\n","import type { ShellUIConfig } from '../config/types';\n\nconst STORAGE_KEY = 'shellui:settings';\n\nfunction getConfig(): ShellUIConfig | undefined {\n if (typeof globalThis === 'undefined') return undefined;\n const g = globalThis as unknown as { __SHELLUI_CONFIG__?: string | ShellUIConfig };\n const raw = g.__SHELLUI_CONFIG__;\n if (raw === null || raw === undefined) return undefined;\n return typeof raw === 'string' ? (JSON.parse(raw) as ShellUIConfig) : raw;\n}\n\nfunction getStoredCookieConsent(): {\n acceptedHosts: string[];\n consentedCookieHosts: string[];\n} {\n if (typeof window === 'undefined') {\n return { acceptedHosts: [], consentedCookieHosts: [] };\n }\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (!stored) return { acceptedHosts: [], consentedCookieHosts: [] };\n const parsed = JSON.parse(stored) as {\n cookieConsent?: { acceptedHosts?: string[]; consentedCookieHosts?: string[] };\n };\n return {\n acceptedHosts: Array.isArray(parsed?.cookieConsent?.acceptedHosts)\n ? parsed.cookieConsent.acceptedHosts\n : [],\n consentedCookieHosts: Array.isArray(parsed?.cookieConsent?.consentedCookieHosts)\n ? parsed.cookieConsent.consentedCookieHosts\n : [],\n };\n } catch {\n return { acceptedHosts: [], consentedCookieHosts: [] };\n }\n}\n\n/**\n * Returns whether the given cookie host is accepted by the user.\n * Use this outside React (e.g. in initSentry) to gate features by cookie consent.\n * - If there is no cookieConsent config, returns true (no consent required).\n * - If the host is not in the config list, returns true (unknown cookie, don't block).\n * - Otherwise returns whether the host is in settings.cookieConsent.acceptedHosts.\n */\nexport function getCookieConsentAccepted(host: string): boolean {\n const config = getConfig();\n if (!config?.cookieConsent?.cookies?.length) return true;\n const knownHosts = new Set(config.cookieConsent.cookies.map((c) => c.host));\n if (!knownHosts.has(host)) return true;\n const { acceptedHosts } = getStoredCookieConsent();\n return acceptedHosts.includes(host);\n}\n\n/**\n * Returns whether the app should ask for consent again because new cookies were added to config.\n * True when current config has at least one host that is not in consentedCookieHosts (the list\n * stored when the user last gave consent). When re-prompting, pre-fill with acceptedHosts so\n * existing approvals are kept.\n */\nexport function getCookieConsentNeedsRenewal(): boolean {\n const config = getConfig();\n if (!config?.cookieConsent?.cookies?.length) return false;\n const { consentedCookieHosts } = getStoredCookieConsent();\n if (consentedCookieHosts.length === 0) return true; // Never consented\n const currentHosts = new Set(config.cookieConsent.cookies.map((c) => c.host));\n for (const host of currentHosts) {\n if (!consentedCookieHosts.includes(host)) return true;\n }\n return false;\n}\n\n/**\n * Returns the list of cookie hosts that are in the current config but were not in the list\n * when the user last gave consent. Use to show \"new\" badges or to know which cookies need\n * fresh approval while keeping existing acceptedHosts as pre-checked.\n */\nexport function getCookieConsentNewHosts(): string[] {\n const config = getConfig();\n if (!config?.cookieConsent?.cookies?.length) return [];\n const { consentedCookieHosts } = getStoredCookieConsent();\n const consentedSet = new Set(consentedCookieHosts);\n return config.cookieConsent.cookies.map((c) => c.host).filter((host) => !consentedSet.has(host));\n}\n","import { getCookieConsentAccepted } from '../cookieConsent/cookieConsent';\n\nconst SETTINGS_KEY = 'shellui:settings';\n\n/** True after @sentry/react has been lazy-loaded and init() was called. */\nlet sentryLoaded = false;\n\nfunction isErrorReportingEnabled(): boolean {\n if (typeof window === 'undefined') return true;\n // If cookie consent is configured with a cookie for sentry.io, only enable when user accepted it\n if (!getCookieConsentAccepted('sentry.io')) return false;\n try {\n const stored = localStorage.getItem(SETTINGS_KEY);\n if (!stored) return true;\n const parsed = JSON.parse(stored) as { errorReporting?: { enabled?: boolean } };\n return parsed?.errorReporting?.enabled !== false;\n } catch {\n return true;\n }\n}\n\ntype SentryGlobals = {\n __SHELLUI_SENTRY_DSN__?: string;\n __SHELLUI_SENTRY_ENVIRONMENT__?: string;\n __SHELLUI_SENTRY_RELEASE__?: string;\n};\n\n/**\n * Initialize error reporting only in production when configured and user has not disabled it.\n * Lazy-loads @sentry/react only when needed so the bundle is not loaded when Sentry is unused.\n * Reads DSN, environment, and release from __SHELLUI_SENTRY_DSN__, __SHELLUI_SENTRY_ENVIRONMENT__,\n * and __SHELLUI_SENTRY_RELEASE__ (injected at build time) and user preference from settings.\n * Exported so the settings UI can re-initialize when the user re-enables reporting.\n */\nexport function initSentry(): void {\n const isDev = (import.meta as unknown as { env?: { DEV?: boolean } }).env?.DEV;\n if (isDev) {\n return;\n }\n if (!isErrorReportingEnabled()) {\n return;\n }\n const g = globalThis as unknown as SentryGlobals;\n const dsn = g.__SHELLUI_SENTRY_DSN__;\n if (!dsn || typeof dsn !== 'string') {\n return;\n }\n void import('@sentry/react').then((Sentry) => {\n Sentry.init({\n dsn,\n environment: g.__SHELLUI_SENTRY_ENVIRONMENT__ ?? 'production',\n release: g.__SHELLUI_SENTRY_RELEASE__,\n });\n sentryLoaded = true;\n });\n}\n\n/**\n * Close Sentry when the user disables error reporting in settings.\n * Only loads @sentry/react if it was already initialized (avoids loading the chunk just to close).\n */\nexport function closeSentry(): void {\n if (!sentryLoaded) {\n return;\n }\n void import('@sentry/react').then((Sentry) => {\n Sentry.close();\n sentryLoaded = false;\n });\n}\n\ninitSentry();\n","/* eslint-disable no-console */\nimport { Workbox } from 'workbox-window';\nimport { shellui, getLogger } from '@shellui/sdk';\n\nconst logger = getLogger('shellcore');\n\nlet wb: Workbox | null = null;\nlet updateAvailable = false;\nlet waitingServiceWorker: ServiceWorker | null = null;\nlet registrationPromise: Promise<void> | null = null;\nlet statusListeners: Array<(status: { registered: boolean; updateAvailable: boolean }) => void> =\n [];\nlet isInitialRegistration = false; // Track if this is the first registration (no reload needed)\nlet eventListenersAdded = false; // Track if event listeners have been added to prevent duplicates\nlet toastShownForServiceWorkerId: string | null = null; // Track which service worker we've shown toast for (prevents duplicates within same page load)\nlet isIntentionalUpdate = false; // Track if we're performing an intentional update (user clicked Install Now)\n// CRITICAL: Track registration state to prevent disabling during registration or immediately after page load\n// Initialize start time to page load time to provide grace period immediately after refresh\n// This prevents race conditions where error handlers fire before registration completes\nlet isRegistering = false; // Track if registration is currently in progress\nlet registrationStartTime = typeof window !== 'undefined' ? Date.now() : 0; // Track when registration started (initialize to page load time)\nconst REGISTRATION_GRACE_PERIOD = 5000; // Don't auto-disable within 5 seconds of page load/registration start\n\n// Store event handler references so we can remove them if needed\ntype EventHandler = (event?: unknown) => void;\nlet waitingHandler: EventHandler | null = null;\nlet activatedHandler: EventHandler | null = null;\nlet controllingHandler: EventHandler | null = null;\nlet registeredHandler: EventHandler | null = null;\nlet redundantHandler: EventHandler | null = null;\nlet serviceWorkerErrorHandler: EventHandler | null = null;\nlet messageErrorHandler: EventHandler | null = null;\n\n/** Global set by host or by us from config so Tauri can be forced (e.g. when __TAURI__ is not yet injected in dev). */\ndeclare global {\n interface Window {\n __SHELLUI_TAURI__?: boolean;\n }\n}\n\nfunction hasTauriOnWindow(w: Window | null): boolean {\n if (!w) return false;\n const o = w as Window & {\n __TAURI__?: unknown;\n __TAURI_INTERNALS__?: unknown;\n __SHELLUI_TAURI__?: boolean;\n };\n if (o.__SHELLUI_TAURI__ === true) return true;\n return !!(o.__TAURI__ ?? o.__TAURI_INTERNALS__);\n}\n\n/** True when the app is running inside Tauri (desktop). Service worker is disabled there; a different caching system is used. */\nexport function isTauri(): boolean {\n if (typeof window === 'undefined') return false;\n if (hasTauriOnWindow(window)) return true;\n try {\n if (window !== window.top && hasTauriOnWindow(window.top)) return true;\n if (window.parent && window.parent !== window && hasTauriOnWindow(window.parent)) return true;\n } catch {\n // Cross-origin: can't access top/parent\n }\n return false;\n}\n\n// Cache for service worker file existence check to avoid duplicate fetches\nlet swFileExistsCache: Promise<boolean> | null = null;\nlet swFileExistsCacheTime = 0;\nconst SW_FILE_EXISTS_CACHE_TTL = 5000; // Cache for 5 seconds\n\n// Notify all listeners of status changes\nasync function notifyStatusListeners() {\n const registered = await isServiceWorkerRegistered();\n const status = {\n registered,\n updateAvailable,\n };\n statusListeners.forEach((listener) => listener(status));\n}\n\nexport interface ServiceWorkerRegistrationOptions {\n enabled: boolean;\n onUpdateAvailable?: () => void;\n}\n\n/**\n * Disable caching automatically when errors occur\n * This helps prevent hard-to-debug issues\n */\nasync function disableCachingAutomatically(reason: string): Promise<void> {\n // CRITICAL: Don't disable if registration is in progress or just started\n // This prevents race conditions where errors fire during registration\n const timeSinceRegistrationStart = Date.now() - registrationStartTime;\n if (isRegistering || timeSinceRegistrationStart < REGISTRATION_GRACE_PERIOD) {\n console.warn(\n `[Service Worker] NOT disabling - registration in progress or within grace period. Reason: ${reason}, isRegistering: ${isRegistering}, timeSinceStart: ${timeSinceRegistrationStart}ms`,\n );\n logger.warn(\n `Not disabling service worker - registration in progress or within grace period: ${reason}`,\n );\n return;\n }\n\n logger.error(`Auto-disabling caching due to error: ${reason}`);\n\n try {\n // Unregister service worker first\n await unregisterServiceWorker();\n\n // Disable service worker in settings\n // We need to access settings through localStorage since we're in a module\n if (typeof window !== 'undefined') {\n const STORAGE_KEY = 'shellui:settings';\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) {\n const settings = JSON.parse(stored);\n // Only update if service worker is currently enabled to avoid unnecessary updates\n if (settings.serviceWorker?.enabled !== false) {\n settings.serviceWorker = { enabled: false };\n // Migrate legacy key so old cached shape is updated\n if (settings.caching !== undefined) {\n delete settings.caching;\n }\n localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));\n\n // Notify the app to reload settings via message system\n shellui.sendMessageToParent({\n type: 'SHELLUI_SETTINGS_UPDATED',\n payload: { settings },\n });\n\n // Also dispatch event for local listeners\n window.dispatchEvent(\n new CustomEvent('shellui:settings-updated', {\n detail: { settings },\n }),\n );\n\n // Show a toast notification\n shellui.toast({\n title: 'Service Worker Disabled',\n description: `The service worker has been automatically disabled due to an error: ${reason}`,\n type: 'error',\n duration: 10000,\n });\n }\n } else {\n // No settings stored, create default with service worker disabled\n const defaultSettings = {\n serviceWorker: { enabled: false },\n };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(defaultSettings));\n\n shellui.toast({\n title: 'Service Worker Disabled',\n description: `The service worker has been automatically disabled due to an error: ${reason}`,\n type: 'error',\n duration: 10000,\n });\n }\n } catch (error) {\n logger.error('Failed to disable service worker in settings:', { error });\n // Still show toast even if settings update fails\n shellui.toast({\n title: 'Service Worker Error',\n description: `Service worker error: ${reason}. Please disable it manually in settings.`,\n type: 'error',\n duration: 10000,\n });\n }\n }\n } catch (error) {\n logger.error('Failed to disable caching automatically:', { error });\n }\n}\n\n/**\n * Check if service worker file exists\n * Uses caching to prevent duplicate fetches when called concurrently\n */\nexport async function serviceWorkerFileExists(): Promise<boolean> {\n const now = Date.now();\n\n // Return cached promise if it's still valid and in progress\n if (swFileExistsCache && now - swFileExistsCacheTime < SW_FILE_EXISTS_CACHE_TTL) {\n return swFileExistsCache;\n }\n\n // Create a new fetch promise and cache it\n swFileExistsCache = (async () => {\n try {\n // Use a timestamp to prevent caching\n const response = await fetch(`/sw.js?t=${Date.now()}`, {\n method: 'GET',\n cache: 'no-store',\n headers: {\n 'Cache-Control': 'no-cache',\n Pragma: 'no-cache',\n },\n });\n\n // Handle 500 errors - server error, but don't disable caching immediately\n // This might be a transient server issue, just return false\n if (response.status >= 500) {\n console.warn(\n `[Service Worker] Server error (${response.status}) when fetching service worker - not disabling`,\n );\n logger.warn(\n `Server error (${response.status}) when fetching service worker - not disabling to avoid false positives`,\n );\n return false;\n }\n\n // If not ok or 404, file doesn't exist\n if (!response.ok || response.status === 404) {\n return false;\n }\n\n // Check content type - should be JavaScript\n const contentType = response.headers.get('content-type') || '';\n const isJavaScript =\n contentType.includes('javascript') ||\n contentType.includes('application/javascript') ||\n contentType.includes('text/javascript');\n\n // If content type is HTML, it's likely Vite's dev server returning index.html\n // which means the file doesn't exist\n if (contentType.includes('text/html')) {\n return false;\n }\n\n // Try to read a bit of the content to verify it's actually a service worker\n const text = await response.text();\n // Service worker files typically start with imports or have workbox/precache references\n const looksLikeServiceWorker =\n text.includes('workbox') ||\n text.includes('precache') ||\n text.includes('serviceWorker') ||\n text.includes('self.addEventListener');\n\n // If we got a response but it doesn't look like a service worker, log warning but don't disable\n // This could be a dev server issue or temporary problem\n if (!isJavaScript && !looksLikeServiceWorker) {\n console.warn('[Service Worker] File does not look like a service worker - not disabling');\n logger.warn(\n 'Service worker file appears to be invalid or corrupted - not disabling to avoid false positives',\n );\n return false;\n }\n\n return isJavaScript || looksLikeServiceWorker;\n } catch (error) {\n // Network errors - don't disable caching, might be offline or transient issue\n if (error instanceof TypeError && error.message.includes('Failed to fetch')) {\n // Don't disable on network errors - might be offline\n console.warn('[Service Worker] Network error when checking file existence - not disabling');\n return false;\n }\n // Other errors - log but don't disable, could be transient\n console.warn('[Service Worker] Error checking file existence - not disabling:', error);\n logger.warn(\n 'Network error checking service worker file - not disabling to avoid false positives',\n { error },\n );\n return false;\n }\n })();\n\n swFileExistsCacheTime = now;\n return swFileExistsCache;\n}\n\n/**\n * Register the service worker and handle updates\n */\nexport async function registerServiceWorker(\n options: ServiceWorkerRegistrationOptions = { enabled: true },\n): Promise<void> {\n if (!('serviceWorker' in navigator)) {\n return;\n }\n\n if (isTauri()) {\n await unregisterServiceWorker();\n wb = null;\n return;\n }\n\n if (!options.enabled) {\n // If disabled, unregister existing service worker\n await unregisterServiceWorker();\n wb = null;\n return;\n }\n\n // Check if service worker file exists (works in both dev and production)\n const swExists = await serviceWorkerFileExists();\n if (!swExists) {\n // In dev mode, the service worker might not be ready yet, try again after a short delay\n // Only retry once to avoid infinite loops\n if (!registrationPromise) {\n setTimeout(async () => {\n const retryExists = await serviceWorkerFileExists();\n if (retryExists && !registrationPromise) {\n // Retry registration if file becomes available\n registerServiceWorker(options);\n } else if (!retryExists) {\n logger.warn('Service worker file not found. Service workers may not be available.');\n }\n }, 1000);\n }\n return;\n }\n\n // If already registering, wait for that to complete\n if (registrationPromise) {\n return registrationPromise;\n }\n\n registrationPromise = (async () => {\n // CRITICAL: Mark that registration is starting to prevent auto-disable during registration\n isRegistering = true;\n registrationStartTime = Date.now();\n\n try {\n // Check if service worker is already registered\n const existingRegistration = await navigator.serviceWorker.getRegistration();\n\n // CRITICAL: If there's a waiting service worker on page load, automatically activate it\n // The user refreshed the page, so they want the new version - activate it automatically\n // This ensures the new version is used without requiring manual \"Install Now\" click\n if (existingRegistration?.waiting && !existingRegistration.installing) {\n // There's a waiting service worker from before the refresh\n // Since the user refreshed, they want the new version - activate it automatically\n console.info(\n '[Service Worker] Waiting service worker found on page load - automatically activating',\n );\n logger.info(\n 'Waiting service worker found on page load - automatically activating since user refreshed',\n );\n\n // Store reference to waiting service worker\n const waitingSW = existingRegistration.waiting;\n waitingServiceWorker = waitingSW;\n\n // CRITICAL: Mark that we're auto-activating so the controlling handler knows to reload\n // Store in sessionStorage so it survives if there's a reload\n if (typeof window !== 'undefined') {\n sessionStorage.setItem('shellui:service-worker:auto-activated', 'true');\n }\n\n // Automatically activate the waiting service worker\n // This is safe because the user already refreshed, so they want the new version\n // The controlling event handler will detect the auto-activation and reload the page\n try {\n waitingSW.postMessage({ type: 'SKIP_WAITING' });\n console.info(\n '[Service Worker] Sent SKIP_WAITING to waiting service worker - will reload when it takes control',\n );\n } catch (error) {\n logger.error('Failed to activate waiting service worker:', { error });\n // Clear the flag on error\n if (typeof window !== 'undefined') {\n sessionStorage.removeItem('shellui:service-worker:auto-activated');\n }\n }\n }\n\n if (existingRegistration && wb) {\n // Already registered, just update\n isInitialRegistration = false; // This is an update check\n wb.update();\n return;\n }\n\n // Check if there's already a service worker controlling the page\n // If not, this is an initial registration (don't reload)\n isInitialRegistration = !navigator.serviceWorker.controller;\n\n // Register the service worker\n // Only create new Workbox instance if one doesn't exist\n const isNewWorkbox = !wb;\n if (!wb) {\n // Use updateViaCache: 'none' to ensure service worker file changes are always detected\n // This bypasses the browser cache when checking for updates to sw.js/sw-dev.js\n wb = new Workbox('/sw.js', {\n type: 'classic',\n updateViaCache: 'none', // Always check network for service worker updates\n });\n }\n\n // Remove old listeners if they exist (handles React Strict Mode double-mounting)\n // Always remove listeners if wb exists and we have handler references, regardless of flag\n // This ensures we clean up properly even if the flag was reset\n if (wb) {\n if (waitingHandler) {\n wb.removeEventListener('waiting', waitingHandler);\n waitingHandler = null;\n }\n if (activatedHandler) {\n wb.removeEventListener('activated', activatedHandler);\n activatedHandler = null;\n }\n if (controllingHandler) {\n wb.removeEventListener('controlling', controllingHandler);\n controllingHandler = null;\n }\n if (registeredHandler) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (wb as any).removeEventListener('registered', registeredHandler);\n registeredHandler = null;\n }\n if (redundantHandler) {\n wb.removeEventListener('redundant', redundantHandler);\n redundantHandler = null;\n }\n if (serviceWorkerErrorHandler) {\n navigator.serviceWorker.removeEventListener('error', serviceWorkerErrorHandler);\n serviceWorkerErrorHandler = null;\n }\n if (messageErrorHandler) {\n navigator.serviceWorker.removeEventListener('messageerror', messageErrorHandler);\n messageErrorHandler = null;\n }\n // Reset flag so we can add listeners again\n eventListenersAdded = false;\n }\n\n // Only add event listeners once (when creating a new Workbox instance or if they were removed)\n if (isNewWorkbox && !eventListenersAdded) {\n // Set flag IMMEDIATELY to prevent duplicate listener registration\n eventListenersAdded = true;\n\n // Handle service worker updates\n // CRITICAL: Use a consistent toast ID to prevent duplicate toasts\n // If the handler is called multiple times (event listener + manual call),\n // using the same ID will update the existing toast instead of creating a new one\n const UPDATE_AVAILABLE_TOAST_ID = 'shellui:update-available';\n\n waitingHandler = async () => {\n try {\n // CRITICAL: If we're auto-activating (user refreshed), don't show toast\n // The service worker will activate automatically and page will reload\n const isAutoActivating =\n typeof window !== 'undefined' &&\n sessionStorage.getItem('shellui:service-worker:auto-activated') === 'true';\n\n // Get the waiting service worker\n const registration = await navigator.serviceWorker.getRegistration();\n if (!registration || !registration.waiting) {\n return;\n }\n\n const currentWaitingSW = registration.waiting;\n const currentWaitingSWId = currentWaitingSW.scriptURL;\n\n // CRITICAL: If auto-activating, update state but skip toast\n if (isAutoActivating) {\n console.info(\n '[Service Worker] Waiting event fired during auto-activation - skipping toast',\n );\n updateAvailable = true;\n waitingServiceWorker = currentWaitingSW;\n notifyStatusListeners();\n return;\n }\n\n // CRITICAL: Check flag BEFORE updating state to prevent race conditions\n // If we've already shown toast for this service worker in this page load, don't show again\n // This prevents duplicate toasts within the same page load, but allows showing after refresh\n if (toastShownForServiceWorkerId === currentWaitingSWId) {\n // Already shown, but ensure state is correct\n updateAvailable = true;\n waitingServiceWorker = currentWaitingSW;\n notifyStatusListeners();\n return;\n }\n\n // CRITICAL: Mark that we've shown toast for this service worker IMMEDIATELY\n // This must happen BEFORE showing the toast to prevent race conditions\n // If the handler is called twice quickly, both might pass the check before the flag is set\n toastShownForServiceWorkerId = currentWaitingSWId;\n\n // Update state\n updateAvailable = true;\n waitingServiceWorker = currentWaitingSW;\n notifyStatusListeners();\n\n // Show toast notification about update\n if (options.onUpdateAvailable) {\n options.onUpdateAvailable();\n } else {\n // CRITICAL: Use consistent toast ID so duplicate calls update the same toast\n // This prevents multiple toasts from appearing if the handler is called multiple times\n // CRITICAL: Always create fresh action handlers that reference the current waitingServiceWorker\n // This ensures the action handler always has the correct service worker reference\n // even if the toast is updated later\n const actionHandler = () => {\n logger.info('Install Now clicked, updating service worker...');\n // CRITICAL: Get the current waitingServiceWorker at click time, not at toast creation time\n // This ensures it works even if the toast was created earlier and then updated\n if (waitingServiceWorker) {\n updateServiceWorker().catch((error) => {\n logger.error('Failed to update service worker:', { error });\n });\n } else {\n logger.warn('Install Now clicked but no waiting service worker found');\n // Try to get it from registration as fallback\n navigator.serviceWorker.getRegistration().then((swRegistration) => {\n if (swRegistration?.waiting) {\n waitingServiceWorker = swRegistration.waiting;\n updateServiceWorker().catch((error) => {\n logger.error('Failed to update service worker:', { error });\n });\n }\n });\n }\n };\n\n shellui.toast({\n id: UPDATE_AVAILABLE_TOAST_ID, // Use consistent ID to prevent duplicates\n title: 'New version available',\n description: 'A new version of the app is available. Install now or later?',\n type: 'info',\n duration: 0, // Don't auto-dismiss\n position: 'bottom-left',\n action: {\n label: 'Install Now',\n onClick: actionHandler, // Use the handler function\n },\n cancel: {\n label: 'Later',\n onClick: () => {\n // User chose to install later, toast will be dismissed\n },\n },\n });\n }\n } catch (error) {\n logger.error('Error in waiting handler:', { error });\n // On error, reset the flag so we can try again for this service worker\n toastShownForServiceWorkerId = null;\n }\n };\n wb.addEventListener('waiting', waitingHandler);\n\n // Handle service worker activated\n activatedHandler = (event?: unknown) => {\n const evt = (event ?? {}) as Record<string, unknown>;\n console.info('[Service Worker] Service worker activated:', {\n isUpdate: evt.isUpdate,\n isInitialRegistration,\n });\n notifyStatusListeners();\n // Reset flags when service worker is activated (update installed or new registration)\n updateAvailable = false;\n waitingServiceWorker = null;\n toastShownForServiceWorkerId = null; // Reset so we can show toast for the next update\n\n // CRITICAL: Only reload if this is an intentional update (user clicked \"Install Now\")\n // Check both in-memory flag and sessionStorage to ensure we only reload when user explicitly requested it\n const isIntentionalUpdatePersisted =\n typeof window !== 'undefined' &&\n sessionStorage.getItem('shellui:service-worker:intentional-update') === 'true';\n const shouldReload = isIntentionalUpdate || isIntentionalUpdatePersisted;\n\n // Clear intentional update flag after activation (update is complete)\n if (typeof window !== 'undefined') {\n sessionStorage.removeItem('shellui:service-worker:intentional-update');\n }\n\n // CRITICAL: Only reload if this is an intentional update (user clicked \"Install Now\")\n // Do NOT reload automatically when a new service worker is installed - wait for user action\n // Exception: If we auto-activated on page load, the new version is already active, no reload needed\n if (evt.isUpdate && !isInitialRegistration && shouldReload) {\n // User explicitly clicked \"Install Now\", so reload to use the new version\n console.info('[Service Worker] Reloading page after intentional update');\n window.location.reload();\n } else if (evt.isUpdate && !isInitialRegistration && !shouldReload) {\n // Auto-activated on page load - new version is now active, UI will update via notifyStatusListeners\n console.info(\n '[Service Worker] Service worker auto-activated on page load - new version is now active',\n );\n }\n // Reset flag after activation\n isInitialRegistration = false;\n };\n wb.addEventListener('activated', activatedHandler as (event: unknown) => void);\n\n // Handle service worker controlling\n controllingHandler = () => {\n notifyStatusListeners();\n\n // CRITICAL: Check if this is an auto-activation from page load refresh\n // If user refreshed and we auto-activated, we need to reload to get the new JavaScript\n const wasAutoActivated =\n typeof window !== 'undefined' &&\n sessionStorage.getItem('shellui:service-worker:auto-activated') === 'true';\n\n // CRITICAL: Only reload if this is an intentional update (user clicked \"Install Now\") OR auto-activation\n // The controlling event fires when a service worker takes control\n // Check both in-memory flag and sessionStorage to ensure we only reload when appropriate\n const isIntentionalUpdatePersisted =\n typeof window !== 'undefined' &&\n sessionStorage.getItem('shellui:service-worker:intentional-update') === 'true';\n const shouldReload =\n isIntentionalUpdate || isIntentionalUpdatePersisted || wasAutoActivated;\n\n // Clear auto-activation flag if it was set\n if (wasAutoActivated && typeof window !== 'undefined') {\n sessionStorage.removeItem('shellui:service-worker:auto-activated');\n }\n\n // CRITICAL: Reload if this is an intentional update OR auto-activation from page refresh\n // After reload, the new version will be active and UI will show correct state\n if (!isInitialRegistration && shouldReload) {\n if (wasAutoActivated) {\n console.info(\n '[Service Worker] Auto-activated service worker took control - reloading to use new version',\n );\n } else {\n console.info(\n '[Service Worker] User clicked Install Now - reloading to use new version',\n );\n }\n // Reload to ensure new JavaScript is loaded\n window.location.reload();\n }\n // Reset flag after controlling\n isInitialRegistration = false;\n };\n wb.addEventListener('controlling', controllingHandler);\n\n // Handle service worker registered\n registeredHandler = () => {\n notifyStatusListeners();\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (wb as any).addEventListener('registered', registeredHandler);\n\n // CRITICAL: Handle service worker 'redundant' event\n // This event fires when a service worker is replaced, which is NORMAL during updates\n // The 'redundant' event fires for the OLD service worker when a NEW one takes control\n // During intentional updates (user clicked \"Install Now\"), this is EXPECTED behavior\n // We MUST check for intentional updates BEFORE disabling, otherwise we'll disable the\n // service worker right after the user explicitly asked to install an update!\n redundantHandler = (event?: unknown) => {\n logger.info('Service worker became redundant:', event as Record<string, unknown>);\n\n // CRITICAL CHECK: Verify this is an intentional update BEFORE doing anything\n // Check sessionStorage FIRST (survives page reloads) - this is set BEFORE skip waiting\n // Then check in-memory flag as backup\n // This prevents race conditions where the flag might not be set yet\n const isIntentionalUpdatePersisted =\n typeof window !== 'undefined' &&\n sessionStorage.getItem('shellui:service-worker:intentional-update') === 'true';\n\n // CRITICAL: Also check if there's a waiting service worker - if there is, we're in update flow\n // This provides an additional safety check in case sessionStorage check fails\n // A waiting service worker means an update is in progress, so redundant is expected\n // We check synchronously first (waitingServiceWorker variable), then async if needed\n const hasWaitingServiceWorkerSync = !!waitingServiceWorker;\n\n // CRITICAL: If ANY of these indicate an intentional update, DO NOT disable\n // The combination of checks prevents false positives from disabling during updates\n // This is the KEY fix - we check multiple signals to be absolutely sure it's an update\n const isUpdateFlow =\n isIntentionalUpdate || isIntentionalUpdatePersisted || hasWaitingServiceWorkerSync;\n\n // CRITICAL: Only disable if this is NOT part of a normal update flow\n // Disabling during an update would break the user's explicit \"Install Now\" action\n // This bug has been seen many times - the redundant event fires during normal updates\n // and without these checks, it would disable the service worker right after install\n if (!isUpdateFlow) {\n // Double-check asynchronously in case the sync check missed it\n // CRITICAL: Be very defensive here - only disable if we're absolutely sure it's an error\n navigator.serviceWorker\n .getRegistration()\n .then((registration) => {\n const hasWaitingAsync = !!registration?.waiting;\n const hasInstallingAsync = !!registration?.installing;\n const hasActiveAsync = !!registration?.active;\n\n // CRITICAL: Only disable if there's NO waiting, NO installing, and NO active service worker\n // If any of these exist, it means an update is in progress and redundant is expected\n if (!hasWaitingAsync && !hasInstallingAsync && !hasActiveAsync) {\n // No service worker at all - this is truly unexpected and likely an error\n console.warn(\n '[Service Worker] Redundant event: No service workers found, disabling',\n );\n logger.warn(\n 'Service worker became redundant unexpectedly (no service workers found)',\n );\n disableCachingAutomatically(\n 'Service worker became redundant (no service workers found)',\n );\n } else {\n // Service workers exist - this is likely part of an update flow, don't disable\n console.info(\n '[Service Worker] Redundant event: Service workers exist, likely update in progress - ignoring',\n );\n logger.info(\n 'Service worker became redundant but other service workers exist - likely update in progress, ignoring',\n );\n }\n })\n .catch((error) => {\n // CRITICAL: If async check fails, DON'T disable - this could be a transient error\n // Log the error but don't disable the service worker\n console.warn(\n '[Service Worker] Redundant event: Async check failed, but NOT disabling:',\n error,\n );\n logger.warn(\n 'Service worker redundant event: Async check failed, but NOT disabling to avoid false positives',\n { error },\n );\n });\n } else {\n console.info(\n '[Service Worker] Redundant event: Intentional update detected - ignoring',\n );\n logger.info(\n 'Service worker became redundant as part of normal update - this is expected and safe',\n );\n // CRITICAL: Don't clear the sessionStorage flag immediately - wait until activation\n // Clearing it too early could cause issues if redundant fires multiple times\n // The activated handler will clear it when the update is complete\n }\n };\n wb.addEventListener('redundant', redundantHandler);\n\n // Handle external service worker errors\n // Only disable caching on critical errors, not during normal update operations\n serviceWorkerErrorHandler = (event?: unknown) => {\n logger.error('Service worker error event:', event as Record<string, unknown>);\n\n // Check if this is an intentional update (check both in-memory flag and sessionStorage)\n const isIntentionalUpdatePersisted =\n typeof window !== 'undefined' &&\n sessionStorage.getItem('shellui:service-worker:intentional-update') === 'true';\n const isUpdateFlow = isIntentionalUpdate || isIntentionalUpdatePersisted;\n\n // CRITICAL: Be very defensive - only disable on truly critical errors\n // Many service worker errors are non-fatal and don't require disabling\n if (!isUpdateFlow) {\n // Only disable on actual errors, not warnings or non-critical issues\n const evt = (event ?? {}) as Record<string, unknown>;\n const evtError = evt.error as Record<string, unknown> | undefined;\n const errorMessage = (evt.message as string) || (evtError?.message as string) || 'Unknown error';\n const errorName = (evtError?.name as string) || '';\n\n // CRITICAL: Only disable on critical errors, ignore common non-fatal errors\n // Many errors during service worker lifecycle are expected and don't require disabling\n const isCriticalError =\n !errorMessage.includes('update') &&\n !errorMessage.includes('activate') &&\n !errorMessage.includes('install') &&\n !errorName.includes('AbortError') &&\n !errorName.includes('NetworkError');\n\n if (isCriticalError) {\n disableCachingAutomatically(`Service worker error: ${errorMessage}`);\n } else {\n console.warn('[Service Worker] Non-critical error, ignoring:', errorMessage);\n logger.warn('Service worker non-critical error, not disabling:', {\n errorMessage,\n errorName,\n });\n }\n } else {\n console.info('[Service Worker] Error during update flow, ignoring');\n logger.info('Service worker error during update flow, ignoring');\n }\n };\n navigator.serviceWorker.addEventListener('error', serviceWorkerErrorHandler);\n\n // Handle message errors from service worker\n messageErrorHandler = (event?: unknown) => {\n logger.error('Service worker message error:', event as Record<string, unknown>);\n // Don't disable on message errors - they're usually not critical\n };\n navigator.serviceWorker.addEventListener('messageerror', messageErrorHandler);\n } // End of event listeners block\n\n // Register the service worker\n await wb.register();\n\n // Get the underlying registration to set updateViaCache\n // This ensures changes to sw.js/sw-dev.js are always detected (bypasses cache)\n const registration = await navigator.serviceWorker.getRegistration();\n if (registration) {\n // Set updateViaCache to 'none' to ensure service worker file changes are always detected\n // This tells the browser to always check the network for sw.js/sw-dev.js updates\n // Note: This property is read-only in some browsers, but setting it helps where supported\n try {\n // Access the registration's update method to ensure cache-busting\n // The browser will check the service worker file with cache: 'reload' when update() is called\n } catch (_e) {\n // Ignore if updateViaCache can't be set (some browsers don't support it)\n }\n\n // Check if there's a waiting service worker after registration\n // If we already handled it above (auto-activation on page load), skip showing toast\n // Otherwise, show toast to let user know an update is available\n if (registration.waiting && waitingHandler) {\n const waitingSWId = registration.waiting.scriptURL;\n\n // Check if we already auto-activated this waiting service worker above\n // If so, don't show toast - it will activate automatically\n const wasAutoActivated =\n waitingServiceWorker === registration.waiting && updateAvailable === true;\n\n if (!wasAutoActivated) {\n // This is a new waiting service worker that appeared after registration\n // Show toast to notify user\n // CRITICAL: Check flag BEFORE calling handler to prevent duplicate toasts\n // The waiting event might have already fired and shown the toast\n if (toastShownForServiceWorkerId !== waitingSWId) {\n // Update state first\n updateAvailable = true;\n waitingServiceWorker = registration.waiting;\n // Trigger the waiting handler to show toast\n // The handler will check the flag again and show toast if needed\n waitingHandler();\n } else {\n // Toast already shown, just update state\n updateAvailable = true;\n waitingServiceWorker = registration.waiting;\n notifyStatusListeners();\n }\n } else {\n // Already auto-activated, just ensure state is correct\n updateAvailable = true;\n waitingServiceWorker = registration.waiting;\n notifyStatusListeners();\n }\n }\n }\n\n notifyStatusListeners();\n\n // Check for updates periodically (including service worker file changes)\n // This ensures changes to sw.js/sw-dev.js are detected\n /* const _updateInterval = */ setInterval(\n () => {\n if (wb && options.enabled) {\n // wb.update() checks for updates to the service worker file itself\n // The browser will compare the byte-by-byte content of sw.js/sw-dev.js\n wb.update();\n }\n },\n 60 * 60 * 1000,\n ); // Check every hour\n\n // Also check for updates when the page becomes visible (user returns to tab)\n // This helps detect service worker file changes more quickly\n let visibilityHandler: (() => void) | null = null;\n if (typeof document !== 'undefined') {\n visibilityHandler = () => {\n if (!document.hidden && wb && options.enabled) {\n wb.update();\n }\n };\n document.addEventListener('visibilitychange', visibilityHandler);\n }\n\n // CRITICAL: Mark registration as complete only after everything is set up\n // This prevents error handlers from disabling during the registration process\n isRegistering = false;\n\n // Store interval and handler for cleanup (though cleanup is best-effort)\n // The interval will continue until page reload, which is acceptable\n } catch (error) {\n // Handle registration errors - be very selective about disabling\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorName = error instanceof Error ? error.name : '';\n logger.error('Registration failed:', { error });\n\n // CRITICAL: Only disable on truly critical errors that indicate the service worker is broken\n // Many registration errors are transient or non-fatal\n const isCriticalError =\n (errorMessage.includes('Failed to register') &&\n !errorMessage.includes('already registered')) ||\n (errorMessage.includes('script error') && !errorMessage.includes('network')) ||\n errorMessage.includes('SyntaxError') ||\n (errorMessage.includes('TypeError') && !errorMessage.includes('fetch')) ||\n (error instanceof DOMException &&\n error.name !== 'SecurityError' &&\n error.name !== 'AbortError');\n\n if (isCriticalError) {\n await disableCachingAutomatically(`Registration failed: ${errorMessage}`);\n } else {\n console.warn(\n '[Service Worker] Non-critical registration error, NOT disabling:',\n errorMessage,\n );\n logger.warn('Non-critical registration error, not disabling:', { errorMessage, errorName });\n }\n } finally {\n // CRITICAL: Reset registration flag in finally block to ensure it's always reset\n // But keep a grace period to prevent immediate disable after registration completes\n // The grace period is handled in disableCachingAutomatically\n isRegistering = false;\n registrationPromise = null;\n }\n })();\n\n return registrationPromise;\n}\n\n/**\n * Update the service worker immediately\n * This will reload the page when the update is installed\n */\nexport async function updateServiceWorker(): Promise<void> {\n if (!wb || !waitingServiceWorker) {\n return;\n }\n\n try {\n // CRITICAL: Set intentional update flag FIRST, before any other operations\n // This flag MUST be set in sessionStorage BEFORE skip waiting is called\n // The 'redundant' event can fire very quickly after skip waiting, and if this flag\n // isn't set yet, the redundant handler will think it's an error and disable the SW\n // This is the ROOT CAUSE of the bug where service worker gets disabled on \"Install Now\"\n const INTENTIONAL_UPDATE_KEY = 'shellui:service-worker:intentional-update';\n if (typeof window !== 'undefined') {\n // CRITICAL: Set this IMMEDIATELY - don't wait for anything else\n sessionStorage.setItem(INTENTIONAL_UPDATE_KEY, 'true');\n }\n\n // CRITICAL: Also set in-memory flag immediately\n // This provides backup protection in case sessionStorage has issues\n isIntentionalUpdate = true;\n\n // CRITICAL: Ensure service worker setting is preserved and enabled before reload\n // This prevents the service worker from being disabled after refresh\n // The user explicitly clicked \"Install Now\", so we must keep the service worker enabled\n if (typeof window !== 'undefined') {\n const STORAGE_KEY = 'shellui:settings';\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) {\n const settings = JSON.parse(stored);\n // CRITICAL: Always ensure service worker is enabled when user clicks Install Now\n // This ensures it stays enabled after the page reloads\n // Without this, the service worker could be disabled after the reload\n settings.serviceWorker = { enabled: true };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));\n\n // Notify the app about the settings update (in case it's listening)\n shellui.sendMessageToParent({\n type: 'SHELLUI_SETTINGS_UPDATED',\n payload: { settings },\n });\n } else {\n // No settings stored, create default with service worker enabled\n const defaultSettings = {\n serviceWorker: { enabled: true },\n };\n localStorage.setItem(STORAGE_KEY, JSON.stringify(defaultSettings));\n }\n } catch (error) {\n logger.warn('Failed to preserve settings before update:', { error });\n // CRITICAL: Even if settings update fails, the intentional update flag is already set\n // This prevents the redundant handler from disabling the service worker\n // The app.tsx will default to enabled anyway, so continue with the update\n }\n }\n\n // Mark that this is an update (not initial registration)\n isInitialRegistration = false;\n\n // Set up reload handler before sending skip waiting\n const reloadApp = () => {\n // Use shellUI refresh message if available, otherwise fallback to window.location.reload\n const sent = shellui.sendMessageToParent({\n type: 'SHELLUI_REFRESH_PAGE',\n payload: {},\n });\n if (!sent) {\n window.location.reload();\n }\n };\n\n // Add one-time listener for controlling event\n const updateControllingHandler = () => {\n reloadApp();\n wb?.removeEventListener('controlling', updateControllingHandler);\n // Reset flag after reload is triggered\n setTimeout(() => {\n isIntentionalUpdate = false;\n }, 1000);\n };\n wb.addEventListener('controlling', updateControllingHandler);\n\n // Send skip waiting message to the waiting service worker\n waitingServiceWorker.postMessage({ type: 'SKIP_WAITING' });\n\n // Fallback: if controlling event doesn't fire within 2 seconds, reload anyway\n setTimeout(() => {\n if (controllingHandler) wb?.removeEventListener('controlling', controllingHandler);\n // Check if service worker is now controlling\n if (navigator.serviceWorker.controller) {\n reloadApp();\n }\n // Reset flag if fallback is used\n setTimeout(() => {\n isIntentionalUpdate = false;\n }, 1000);\n }, 2000);\n } catch (error) {\n logger.error('Failed to update service worker:', { error });\n // Reset flag on error\n isIntentionalUpdate = false;\n }\n}\n\n/**\n * Unregister the service worker silently (no page reload)\n */\nexport async function unregisterServiceWorker(): Promise<void> {\n if (!('serviceWorker' in navigator)) {\n return;\n }\n\n try {\n // Set flag to prevent any reloads during unregistration\n isInitialRegistration = true;\n\n const registration = await navigator.serviceWorker.getRegistration();\n if (registration) {\n await registration.unregister();\n\n // Clear all caches silently\n if ('caches' in window) {\n const cacheNames = await caches.keys();\n await Promise.all(cacheNames.map((name) => caches.delete(name)));\n }\n }\n\n // Clean up workbox instance and remove all event listeners\n if (wb) {\n // Remove all event listeners before cleaning up\n if (waitingHandler) wb.removeEventListener('waiting', waitingHandler);\n if (activatedHandler) wb.removeEventListener('activated', activatedHandler);\n if (controllingHandler) wb.removeEventListener('controlling', controllingHandler);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if (registeredHandler) (wb as any).removeEventListener('registered', registeredHandler);\n if (redundantHandler) wb.removeEventListener('redundant', redundantHandler);\n if (serviceWorkerErrorHandler) {\n navigator.serviceWorker.removeEventListener('error', serviceWorkerErrorHandler);\n }\n if (messageErrorHandler) {\n navigator.serviceWorker.removeEventListener('messageerror', messageErrorHandler);\n }\n // Clear handler references\n waitingHandler = null;\n activatedHandler = null;\n controllingHandler = null;\n registeredHandler = null;\n redundantHandler = null;\n serviceWorkerErrorHandler = null;\n messageErrorHandler = null;\n // Remove workbox instance\n wb = null;\n }\n\n updateAvailable = false;\n waitingServiceWorker = null;\n isInitialRegistration = false;\n toastShownForServiceWorkerId = null; // Reset toast flag on unregister\n eventListenersAdded = false; // Reset event listeners flag on unregister\n isIntentionalUpdate = false; // Reset intentional update flag on unregister\n notifyStatusListeners();\n } catch (error) {\n logger.error('Failed to unregister service worker:', { error });\n isInitialRegistration = false;\n }\n}\n\n/**\n * Check if service worker is registered and active\n */\nexport async function isServiceWorkerRegistered(): Promise<boolean> {\n if (!('serviceWorker' in navigator)) {\n return false;\n }\n if (isTauri()) {\n return false;\n }\n\n // First check if service worker file exists (only in production)\n const swExists = await serviceWorkerFileExists();\n if (!swExists) {\n return false;\n }\n\n try {\n const registration = await navigator.serviceWorker.getRegistration();\n if (!registration) {\n return false;\n }\n\n // Check if service worker is active (either controlling or installed)\n // A service worker can be registered but not yet active\n if (registration.active) {\n return true;\n }\n\n // Also check if there's a waiting or installing service worker\n // This means registration is in progress or update is available\n if (registration.waiting || registration.installing) {\n return true;\n }\n\n // If navigator.serviceWorker.controller exists, the SW is controlling the page\n if (navigator.serviceWorker.controller) {\n return true;\n }\n\n return false;\n } catch (_error) {\n // Silently return false if there's an error checking registration\n return false;\n }\n}\n\n/**\n * Get service worker status\n */\nexport async function getServiceWorkerStatus(): Promise<{\n registered: boolean;\n updateAvailable: boolean;\n}> {\n const registered = await isServiceWorkerRegistered();\n\n // Actually check if there's a waiting service worker (more reliable than in-memory flag)\n // This ensures we get the correct state even after page reloads\n let actuallyUpdateAvailable = false;\n if (registered && !isTauri()) {\n try {\n const registration = await navigator.serviceWorker.getRegistration();\n if (registration?.waiting) {\n // There's a waiting service worker, so an update is available\n actuallyUpdateAvailable = true;\n // Sync the in-memory flag with the actual state\n updateAvailable = true;\n waitingServiceWorker = registration.waiting;\n } else {\n // No waiting service worker, so no update is available\n actuallyUpdateAvailable = false;\n // Sync the in-memory flag with the actual state\n updateAvailable = false;\n waitingServiceWorker = null;\n }\n } catch (error) {\n logger.error('Failed to check service worker registration:', { error });\n // Fall back to in-memory flag if check fails\n actuallyUpdateAvailable = updateAvailable;\n }\n } else {\n // Not registered or Tauri, so no update available\n actuallyUpdateAvailable = false;\n updateAvailable = false;\n waitingServiceWorker = null;\n }\n\n return {\n registered,\n updateAvailable: actuallyUpdateAvailable,\n };\n}\n\n/**\n * Manually trigger a check for service worker updates (browser only).\n * Resolves when the check is complete. Listen to addStatusListener for updateAvailable changes.\n */\nexport async function checkForServiceWorkerUpdate(): Promise<void> {\n if (isTauri() || !wb) return;\n await wb.update();\n}\n\n/**\n * Add a listener for service worker status changes\n */\nexport function addStatusListener(\n listener: (status: { registered: boolean; updateAvailable: boolean }) => void,\n): () => void {\n statusListeners.push(listener);\n // Don't call immediately - let the component do the initial check to avoid duplicate fetches\n\n // Return unsubscribe function\n return () => {\n statusListeners = statusListeners.filter((l) => l !== listener);\n };\n}\n","import { useMemo, useLayoutEffect, useState, useEffect } from 'react';\nimport { RouterProvider } from 'react-router';\nimport { shellui } from '@shellui/sdk';\nimport { useConfig } from './features/config/useConfig';\nimport { ConfigProvider } from './features/config/ConfigProvider';\nimport { createAppRouter } from './router/router';\nimport { SettingsProvider } from './features/settings/SettingsProvider';\nimport { ThemeProvider } from './features/theme/ThemeProvider';\nimport { I18nProvider } from './i18n/I18nProvider';\nimport { DialogProvider } from './features/alertDialog/DialogContext';\nimport { CookieConsentModal } from './features/cookieConsent/CookieConsentModal';\nimport './features/sentry/initSentry';\nimport './i18n/config'; // Initialize i18n\nimport './index.css';\nimport { registerServiceWorker, unregisterServiceWorker, isTauri } from './service-worker/register';\nimport { useSettings } from './features/settings/hooks/useSettings';\n\nconst AppContent = () => {\n const { config } = useConfig();\n const { settings } = useSettings();\n\n // Apply favicon from config when available (allows projects to override default)\n useEffect(() => {\n if (config?.favicon) {\n const link = document.querySelector<HTMLLinkElement>('link[rel=\"icon\"]');\n if (link) link.href = config.favicon;\n }\n }, [config?.favicon]);\n\n // Register or unregister service worker based on setting\n useEffect(() => {\n if (isTauri()) {\n unregisterServiceWorker();\n return;\n }\n const serviceWorkerEnabled = settings?.serviceWorker?.enabled ?? true; // Default to enabled\n\n // Don't register service worker if navigation is empty or undefined\n // This helps prevent issues in development or misconfigured apps\n if (!config?.navigation || config.navigation.length === 0) {\n if (serviceWorkerEnabled) {\n // eslint-disable-next-line no-console\n console.warn('[Service Worker] Disabled: No navigation items configured');\n unregisterServiceWorker();\n }\n return;\n }\n\n if (serviceWorkerEnabled) {\n registerServiceWorker({\n enabled: true,\n });\n } else {\n unregisterServiceWorker();\n }\n }, [settings?.serviceWorker?.enabled, config?.navigation]);\n\n // Create router from config using data mode\n const router = useMemo(() => {\n if (!config) {\n return null;\n }\n return createAppRouter(config);\n }, [config]);\n\n // If no navigation, show simple layout\n if (!config.navigation || config.navigation.length === 0) {\n return (\n <>\n <CookieConsentModal />\n <div style={{ fontFamily: 'system-ui, sans-serif', padding: '2rem' }}>\n <h1>{config.title || 'ShellUI'}</h1>\n <p>No navigation items configured.</p>\n </div>\n </>\n );\n }\n\n if (!router) {\n return null;\n }\n\n return (\n <>\n <CookieConsentModal />\n <RouterProvider router={router} />\n </>\n );\n};\n\nconst App = () => {\n const [isLoading, setIsLoading] = useState(true);\n // Initialize ShellUI SDK to support recursive nesting\n useLayoutEffect(() => {\n shellui.init().then(() => {\n setIsLoading(false);\n });\n }, []);\n\n if (isLoading) {\n return null;\n }\n\n return (\n <ConfigProvider>\n <SettingsProvider>\n <ThemeProvider>\n <I18nProvider>\n <DialogProvider>\n <AppContent />\n </DialogProvider>\n </I18nProvider>\n </ThemeProvider>\n </SettingsProvider>\n </ConfigProvider>\n );\n};\n\nexport default App;\n","import { useMemo } from 'react';\nimport { useConfig } from '../config/useConfig';\nimport { useSettings } from '../settings/hooks/useSettings';\nimport { getCookieConsentNeedsRenewal } from './cookieConsent';\n\n/**\n * Returns whether the given cookie host is accepted (feature may run) and whether\n * consent should be re-collected. Use to gate features in React components.\n *\n * - isAccepted: true if cookie consent is not configured, or the host is not in the config list,\n * or the user has accepted this host.\n * - needsConsent: true if cookie consent is configured and the user has not yet consented,\n * or new cookies were added since last consent (renewal); when showing the UI again, pre-fill\n * with settings.cookieConsent.acceptedHosts to keep existing approvals.\n */\nexport function useCookieConsent(host: string): { isAccepted: boolean; needsConsent: boolean } {\n const { config } = useConfig();\n const { settings } = useSettings();\n\n return useMemo(() => {\n const cookieConsent = config?.cookieConsent;\n const list = cookieConsent?.cookies ?? [];\n const acceptedHosts = settings?.cookieConsent?.acceptedHosts ?? [];\n\n if (!list.length) {\n return { isAccepted: true, needsConsent: false };\n }\n\n const knownHosts = new Set(list.map((c) => c.host));\n if (!knownHosts.has(host)) {\n return { isAccepted: true, needsConsent: false };\n }\n\n const isAccepted = acceptedHosts.includes(host);\n const needsConsent = acceptedHosts.length === 0 || getCookieConsentNeedsRenewal();\n\n return { isAccepted, needsConsent };\n }, [config?.cookieConsent, settings?.cookieConsent?.acceptedHosts, host]);\n}\n"],"names":["logger","getLogger","ConfigContext","createContext","configLogged","ConfigProvider","props","config","useState","configValue","g","parsedConfig","parseError","fallbackValue","err","value","createElement","useConfig","context","useContext","error","cn","inputs","twMerge","clsx","buttonVariants","cva","Button","forwardRef","className","variant","size","asChild","ref","jsx","Slot","isChunkLoadError","msg","getErrorMessage","isRouteErrorResponse","getErrorStack","getErrorDetailsText","message","stack","RouteErrorBoundary","useRouteError","useTranslation","isChunkError","detailsText","jsxs","shellui","SettingsContext","useSettings","DefaultLayout","lazy","m","FullscreenLayout","WindowsLayout","LayoutFallback","AppLayout","layout","title","appIcon","logo","navigation","settings","effectiveLayout","LayoutComponent","layoutProps","Suspense","resolveLocalizedString","lang","flattenNavigationItems","item","filterNavigationByViewport","viewport","hideOnMobile","hideOnDesktop","group","visibleItems","navItem","filterNavigationForSidebar","splitNavigationByPosition","start","end","HomeView","SettingsView","CookiePreferencesView","ViewRoute","NotFoundView","RouteFallback","createRoutes","routes","Outlet","urls","layoutRoute","navigationItems","createAppRouter","createBrowserRouter","resolveLabel","buildSettingsWithNavigation","items","STORAGE_KEY","getBrowserTimezone","defaultSettings","SettingsProvider","children","i18n","settingsRef","useRef","setSettings","initialSettings","stored","parsed","useEffect","cleanup","newSettings","settingsToPropagate","cleanupSettingsRequested","currentSettings","settingsWithNav","cleanupSettings","data","updateSettings","useCallback","updates","updateSetting","key","currentValue","mergedValue","resetAllData","keysToRemove","i","useMemo","hexToHsl","hexString","hex","b","rNorm","gNorm","bNorm","max","min","h","s","l","d","hDeg","sPercent","lPercent","result","defaultTheme","blueTheme","warmYellowTheme","themeRegistry","registerTheme","theme","getTheme","name","getAllThemes","applyTheme","isDark","root","colors","primaryHsl","head","link","fontFile","index","style","fontName","bodyFont","headingFont","bodyShadow","match","rgba","values","v","opacity","actualPrimary","hslFormat","applyThemeToDocument","useTheme","themeName","useLayoutEffect","effectiveThemeName","themeDef","themeDefinition","ThemeProvider","allSupportedLanguages","resources","enCommon","enSettings","enCookieConsent","frCommon","frSettings","frCookieConsent","getInitialLanguage","enabledLanguages","languageCode","isInitialized","initializeI18n","validLangs","supported","finalLangs","initialLang","initReactI18next","getSupportedLanguages","enabledLangs","I18nProvider","currentLanguage","Z_INDEX","AlertDialog","AlertDialogPrimitive","AlertDialogPortal","AlertDialogOverlay","alertDialogContentVariants","AlertDialogContent","AlertDialogHeader","AlertDialogMedia","AlertDialogFooter","AlertDialogTitle","AlertDialogDescription","AlertDialogAction","AlertDialogCancel","DIALOG_EXIT_ANIMATION_MS","TrashIcon","CookieIcon","DialogContext","useDialog","DialogProvider","dialogState","setDialogState","isOpen","setIsOpen","unmountTimeoutRef","scheduleUnmount","handleOpenChange","open","handleOk","handleCancel","handleSecondary","dialog","options","dialogId","cleanupDialog","payload","cleanupDialogUpdate","renderButtons","mode","okLabel","cancelLabel","secondaryButton","Fragment","renderCookieConsentDialog","CookieConsentModal","t","showDialog","closedByChoiceRef","dialogShownRef","cookies","consentedHosts","allHosts","c","strictNecessaryHosts","hasNewCookies","host","neverConsented","isRenewal","shouldShow","description","saveAccept","saveReject","handleAccept","handleReject","handleSetPreferences","getConfig","raw","getStoredCookieConsent","getCookieConsentAccepted","acceptedHosts","getCookieConsentNeedsRenewal","consentedCookieHosts","currentHosts","getCookieConsentNewHosts","consentedSet","SETTINGS_KEY","sentryLoaded","isErrorReportingEnabled","initSentry","dsn","Sentry","closeSentry","wb","updateAvailable","waitingServiceWorker","registrationPromise","statusListeners","isInitialRegistration","eventListenersAdded","toastShownForServiceWorkerId","isIntentionalUpdate","isRegistering","registrationStartTime","REGISTRATION_GRACE_PERIOD","waitingHandler","activatedHandler","controllingHandler","registeredHandler","redundantHandler","serviceWorkerErrorHandler","messageErrorHandler","hasTauriOnWindow","w","o","isTauri","swFileExistsCache","swFileExistsCacheTime","SW_FILE_EXISTS_CACHE_TTL","notifyStatusListeners","status","isServiceWorkerRegistered","listener","disableCachingAutomatically","reason","timeSinceRegistrationStart","unregisterServiceWorker","serviceWorkerFileExists","now","response","contentType","isJavaScript","text","looksLikeServiceWorker","registerServiceWorker","retryExists","existingRegistration","waitingSW","isNewWorkbox","Workbox","UPDATE_AVAILABLE_TOAST_ID","isAutoActivating","registration","currentWaitingSW","currentWaitingSWId","actionHandler","updateServiceWorker","swRegistration","event","evt","isIntentionalUpdatePersisted","shouldReload","wasAutoActivated","hasWaitingAsync","hasInstallingAsync","hasActiveAsync","evtError","errorMessage","errorName","waitingSWId","visibilityHandler","reloadApp","updateControllingHandler","cacheNames","getServiceWorkerStatus","registered","actuallyUpdateAvailable","checkForServiceWorkerUpdate","addStatusListener","AppContent","serviceWorkerEnabled","router","RouterProvider","App","isLoading","setIsLoading","useCookieConsent","list","isAccepted","needsConsent"],"mappings":"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"}
|
package/dist/index.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export { default as App } from './app.js';
|
|
2
|
-
export type { ShellUIConfig, NavigationItem, NavigationGroup, LocalizedString, ThemeDefinition, ThemeColors, DrawerPosition, LayoutType, CookieConsentCategory, CookieDefinition, CookieConsentConfig, } from './features/config/types.js';
|
|
3
|
-
export { useConfig } from './features/config/useConfig.js';
|
|
4
|
-
export { default as urls } from './constants/urls.js';
|
|
5
|
-
export { getCookieConsentAccepted, getCookieConsentNeedsRenewal, getCookieConsentNewHosts, } from './features/cookieConsent/cookieConsent.js';
|
|
6
|
-
export { useCookieConsent } from './features/cookieConsent/useCookieConsent.js';
|
|
7
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,aAAa,CAAC;AAErB,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EACV,aAAa,EACb,cAAc,EACd,eAAe,EACf,eAAe,EACf,eAAe,EACf,WAAW,EACX,cAAc,EACd,UAAU,EACV,qBAAqB,EACrB,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC"}
|
package/dist/index.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { A as s, t, v as n, w as a, u as C, x as i } from "./index-CfvdAI_Y.js";
|
|
2
|
-
import { default as r } from "./constants/urls.js";
|
|
3
|
-
export {
|
|
4
|
-
s as App,
|
|
5
|
-
t as getCookieConsentAccepted,
|
|
6
|
-
n as getCookieConsentNeedsRenewal,
|
|
7
|
-
a as getCookieConsentNewHosts,
|
|
8
|
-
r as urls,
|
|
9
|
-
C as useConfig,
|
|
10
|
-
i as useCookieConsent
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
package/dist/lib/utils.d.ts
DELETED
package/dist/lib/utils.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/lib/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAG7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
|