@sudobility/building_blocks 0.0.205 → 0.0.207

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.
@@ -9,7 +9,7 @@ export interface AppFooterForHomePageProps {
9
9
  /** App name */
10
10
  appName: string;
11
11
  };
12
- /** Footer link sections (columns of links) */
12
+ /** Footer link sections displayed as horizontal rows */
13
13
  linkSections: FooterLinkSectionConfig[];
14
14
  /** Social media links */
15
15
  socialLinks?: SocialLinksConfig;
@@ -28,7 +28,7 @@ export interface AppFooterForHomePageProps {
28
28
  companyName: string;
29
29
  /** Company link URL (optional) */
30
30
  companyUrl?: string;
31
- /** Footer description text (below logo) */
31
+ /** Footer description text (tagline below logo) */
32
32
  description?: string;
33
33
  /** Rights text (e.g., "All rights reserved") */
34
34
  rightsText?: string;
@@ -38,26 +38,19 @@ export interface AppFooterForHomePageProps {
38
38
  isNetworkOnline?: boolean;
39
39
  /** Custom className */
40
40
  className?: string;
41
- /** Number of columns for link grid (default: auto based on section count) */
42
- gridColumns?: 2 | 3 | 4 | 5;
43
41
  /** Optional analytics tracking callback */
44
42
  onTrack?: (params: AnalyticsTrackingParams) => void;
45
43
  }
46
44
  /**
47
45
  * AppFooterForHomePage - Full footer for home/landing pages.
48
46
  *
49
- * Features:
50
- * - Multiple link sections in a grid
51
- * - Logo and brand description
52
- * - Social media links
53
- * - System status indicator (optional)
54
- * - Version and copyright
55
- * - Dark mode support
47
+ * Displays link sections as horizontal rows with section title in bold,
48
+ * followed by links that wrap to additional lines as needed.
49
+ * Below the sitemap, shows app name, tagline, version, and copyright
50
+ * on a single wrapping line.
56
51
  *
57
52
  * @example
58
53
  * ```tsx
59
- * import { SystemStatusIndicator } from '@sudobility/devops-components';
60
- *
61
54
  * <AppFooterForHomePage
62
55
  * logo={{ appName: 'My App' }}
63
56
  * linkSections={[
@@ -68,25 +61,10 @@ export interface AppFooterForHomePageProps {
68
61
  * { label: 'Pricing', href: '/pricing' },
69
62
  * ],
70
63
  * },
71
- * {
72
- * title: 'Company',
73
- * links: [
74
- * { label: 'About', href: '/about' },
75
- * { label: 'Contact', href: '/contact' },
76
- * ],
77
- * },
78
64
  * ]}
79
- * socialLinks={{
80
- * twitterUrl: 'https://twitter.com/myapp',
81
- * discordUrl: 'https://discord.gg/myapp',
82
- * }}
83
- * statusIndicator={{
84
- * statusPageUrl: 'https://status.example.com',
85
- * }}
86
- * StatusIndicatorComponent={SystemStatusIndicator}
87
65
  * version="1.0.0"
88
66
  * companyName="Sudobility Inc."
89
- * description="Building the future of web3 communication"
67
+ * description="Building the future"
90
68
  * />
91
69
  * ```
92
70
  */
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import Backend from "i18next-http-backend";
8
8
  import LanguageDetector from "i18next-browser-languagedetector";
9
9
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
10
10
  import React, { useState, useRef, useMemo, useCallback, useEffect } from "react";
11
- import { TopbarProvider, Topbar, TopbarLeft, TopbarNavigation, TopbarLogo, Logo, TopbarCenter, TopbarRight, TopbarActions, TopbarMobileContent, Footer, FooterCompact, FooterCompactLeft, FooterVersion, FooterCopyright, FooterCompactRight, FooterGrid, FooterLinkSection, FooterLink, FooterBottom, FooterBrand, FooterSocialLinks, LayoutProvider, AspectFitView, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, MasterListItem, MasterDetailLayout, Section } from "@sudobility/components";
11
+ import { TopbarProvider, Topbar, TopbarLeft, TopbarNavigation, TopbarLogo, Logo, TopbarCenter, TopbarRight, TopbarActions, TopbarMobileContent, Footer, FooterCompact, FooterCompactLeft, FooterVersion, FooterCopyright, FooterCompactRight, FooterSocialLinks, LayoutProvider, AspectFitView, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, MasterListItem, MasterDetailLayout, Section } from "@sudobility/components";
12
12
  import { ChevronDownIcon, CalendarDaysIcon, PaintBrushIcon, LanguageIcon, ChevronRightIcon, EnvelopeIcon, DocumentTextIcon, CogIcon, HomeIcon } from "@heroicons/react/24/outline";
13
13
  import { ui, GRADIENT_CLASSES, buttonVariant, textVariants, colors, focusRing } from "@sudobility/design";
14
14
  import { cva } from "class-variance-authority";
@@ -987,21 +987,6 @@ const AppFooter = ({
987
987
  }
988
988
  );
989
989
  };
990
- function getGridColumnsClass(sectionCount, explicit) {
991
- const cols = explicit || Math.min(sectionCount, 4);
992
- switch (cols) {
993
- case 2:
994
- return "md:grid-cols-2";
995
- case 3:
996
- return "md:grid-cols-3";
997
- case 4:
998
- return "md:grid-cols-4";
999
- case 5:
1000
- return "md:grid-cols-5";
1001
- default:
1002
- return "md:grid-cols-4";
1003
- }
1004
- }
1005
990
  const AppFooterForHomePage = ({
1006
991
  logo,
1007
992
  linkSections,
@@ -1017,11 +1002,9 @@ const AppFooterForHomePage = ({
1017
1002
  LinkComponent = DefaultLinkComponent,
1018
1003
  isNetworkOnline = true,
1019
1004
  className,
1020
- gridColumns,
1021
1005
  onTrack
1022
1006
  }) => {
1023
1007
  const year = copyrightYear || getCopyrightYear();
1024
- const gridClass = getGridColumnsClass(linkSections.length, gridColumns);
1025
1008
  const track = useCallback(
1026
1009
  (label, params) => {
1027
1010
  onTrack == null ? void 0 : onTrack({
@@ -1044,95 +1027,98 @@ const AppFooterForHomePage = ({
1044
1027
  },
1045
1028
  [track]
1046
1029
  );
1047
- const companyLink = companyUrl ? /* @__PURE__ */ jsx(
1048
- LinkComponent,
1049
- {
1050
- href: companyUrl,
1051
- className: cn(ui.text.linkSubtle, ui.transition.default),
1052
- children: companyName
1053
- }
1054
- ) : void 0;
1055
1030
  return /* @__PURE__ */ jsxs(Footer, { variant: "full", className: cn(className), children: [
1056
- /* @__PURE__ */ jsx(FooterGrid, { className: gridClass, children: linkSections.map((section, sectionIndex) => /* @__PURE__ */ jsx(
1057
- FooterLinkSection,
1031
+ /* @__PURE__ */ jsx(
1032
+ "nav",
1058
1033
  {
1059
- title: section.title,
1060
- children: section.links.map((link, linkIndex) => /* @__PURE__ */ jsx(FooterLink, { children: link.onClick ? /* @__PURE__ */ jsx(
1061
- "button",
1034
+ role: "navigation",
1035
+ "aria-label": "Footer Navigation",
1036
+ className: "space-y-1",
1037
+ children: linkSections.map((section, sectionIndex) => /* @__PURE__ */ jsxs(
1038
+ "div",
1062
1039
  {
1063
- onClick: createTrackedLinkHandler(
1064
- link.label,
1065
- link.href,
1066
- section.title,
1067
- link.onClick
1068
- ),
1069
- className: "text-left",
1070
- children: link.label
1071
- }
1072
- ) : /* @__PURE__ */ jsx(
1040
+ className: "flex flex-wrap items-baseline gap-y-0.5",
1041
+ children: [
1042
+ /* @__PURE__ */ jsx("span", { className: "font-bold text-xs text-gray-300 mr-2", children: section.title }),
1043
+ section.links.map((link, linkIndex) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
1044
+ linkIndex > 0 && /* @__PURE__ */ jsx("span", { className: "text-gray-600 mx-1.5", children: "·" }),
1045
+ link.onClick ? /* @__PURE__ */ jsx(
1046
+ "button",
1047
+ {
1048
+ onClick: createTrackedLinkHandler(
1049
+ link.label,
1050
+ link.href,
1051
+ section.title,
1052
+ link.onClick
1053
+ ),
1054
+ className: "text-xs text-gray-400 hover:text-white transition-colors",
1055
+ children: link.label
1056
+ }
1057
+ ) : /* @__PURE__ */ jsx(
1058
+ LinkComponent,
1059
+ {
1060
+ href: link.href,
1061
+ onClick: createTrackedLinkHandler(
1062
+ link.label,
1063
+ link.href,
1064
+ section.title
1065
+ ),
1066
+ className: "text-xs text-gray-400 hover:text-white transition-colors",
1067
+ children: link.label
1068
+ }
1069
+ )
1070
+ ] }, link.href || linkIndex))
1071
+ ]
1072
+ },
1073
+ section.title || sectionIndex
1074
+ ))
1075
+ }
1076
+ ),
1077
+ /* @__PURE__ */ jsx("div", { className: "border-t border-gray-700 mt-4 pt-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-x-3 gap-y-0.5 text-xs text-gray-400", children: [
1078
+ /* @__PURE__ */ jsx("span", { className: "font-semibold text-gray-200", children: logo.appName }),
1079
+ description && /* @__PURE__ */ jsxs(Fragment, { children: [
1080
+ /* @__PURE__ */ jsx("span", { className: "text-gray-600", children: "·" }),
1081
+ /* @__PURE__ */ jsx("span", { children: description })
1082
+ ] }),
1083
+ version && /* @__PURE__ */ jsxs(Fragment, { children: [
1084
+ /* @__PURE__ */ jsx("span", { className: "text-gray-600", children: "·" }),
1085
+ /* @__PURE__ */ jsxs("span", { children: [
1086
+ "v",
1087
+ version
1088
+ ] })
1089
+ ] }),
1090
+ /* @__PURE__ */ jsx("span", { className: "text-gray-600", children: "·" }),
1091
+ /* @__PURE__ */ jsxs("span", { children: [
1092
+ "© ",
1093
+ year,
1094
+ " ",
1095
+ companyUrl ? /* @__PURE__ */ jsx(
1073
1096
  LinkComponent,
1074
1097
  {
1075
- href: link.href,
1076
- onClick: createTrackedLinkHandler(
1077
- link.label,
1078
- link.href,
1079
- section.title
1080
- ),
1081
- children: link.label
1098
+ href: companyUrl,
1099
+ className: "text-gray-400 hover:text-white transition-colors",
1100
+ children: companyName
1082
1101
  }
1083
- ) }, link.href || linkIndex))
1084
- },
1085
- section.title || sectionIndex
1086
- )) }),
1087
- /* @__PURE__ */ jsxs(FooterBottom, { children: [
1088
- /* @__PURE__ */ jsx(
1089
- FooterBrand,
1090
- {
1091
- description,
1092
- className: "flex flex-col items-center",
1093
- children: /* @__PURE__ */ jsx(
1094
- LinkComponent,
1095
- {
1096
- href: "/",
1097
- className: "text-white hover:opacity-80 transition-opacity",
1098
- children: logo.src ? /* @__PURE__ */ jsx(
1099
- "img",
1100
- {
1101
- src: logo.src,
1102
- alt: logo.appName,
1103
- className: "h-8 object-contain"
1104
- }
1105
- ) : /* @__PURE__ */ jsx(Logo, { size: "md", showText: true, logoText: logo.appName })
1106
- }
1107
- )
1108
- }
1109
- ),
1110
- /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
1111
- version && /* @__PURE__ */ jsx(FooterVersion, { version, className: "block" }),
1102
+ ) : companyName,
1103
+ ". ",
1104
+ rightsText
1105
+ ] }),
1106
+ statusIndicator && StatusIndicatorComponent && /* @__PURE__ */ jsxs(Fragment, { children: [
1107
+ /* @__PURE__ */ jsx("span", { className: "text-gray-600", children: "·" }),
1112
1108
  /* @__PURE__ */ jsx(
1113
- FooterCopyright,
1109
+ StatusIndicatorComponent,
1114
1110
  {
1115
- year,
1116
- companyName,
1117
- rightsText,
1118
- companyLink,
1119
- className: "block"
1111
+ statusPageUrl: statusIndicator.statusPageUrl,
1112
+ apiEndpoint: statusIndicator.apiEndpoint,
1113
+ refreshInterval: statusIndicator.refreshInterval || 6e4,
1114
+ size: "sm",
1115
+ version,
1116
+ isNetworkOnline
1120
1117
  }
1121
1118
  )
1122
- ] }),
1123
- statusIndicator && StatusIndicatorComponent && /* @__PURE__ */ jsx(
1124
- StatusIndicatorComponent,
1125
- {
1126
- statusPageUrl: statusIndicator.statusPageUrl,
1127
- apiEndpoint: statusIndicator.apiEndpoint,
1128
- refreshInterval: statusIndicator.refreshInterval || 6e4,
1129
- size: "sm",
1130
- version,
1131
- isNetworkOnline
1132
- }
1133
- )
1134
- ] }),
1135
- socialLinks && /* @__PURE__ */ jsx("div", { className: "flex justify-center mt-4", children: /* @__PURE__ */ jsx(
1119
+ ] })
1120
+ ] }) }),
1121
+ socialLinks && /* @__PURE__ */ jsx("div", { className: "flex justify-center mt-3", children: /* @__PURE__ */ jsx(
1136
1122
  FooterSocialLinks,
1137
1123
  {
1138
1124
  twitterUrl: socialLinks.twitterUrl,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/utils/index.ts","../src/constants/languages.ts","../src/components/topbar/language-selector.tsx","../src/components/topbar/app-topbar.tsx","../src/components/topbar/app-topbar-with-firebase-auth.tsx","../src/components/topbar/app-topbar-with-wallet.tsx","../src/components/breadcrumbs/app-breadcrumbs.tsx","../src/components/footer/shared.tsx","../src/components/footer/app-footer.tsx","../src/components/footer/app-footer-for-home-page.tsx","../src/components/layout/app-page-layout.tsx","../src/components/settings/appearance-settings.tsx","../src/components/settings/global-settings-page.tsx","../src/components/pages/app-sitemap-page.tsx","../src/components/pages/app-text-page.tsx","../src/components/pages/login-page.tsx","../src/components/empty-state/EmptyState.tsx","../src/i18n/index.ts"],"sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Merge class names with Tailwind CSS classes.\n * Combines clsx for conditional classes and tailwind-merge for deduplication.\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","/**\n * @fileoverview Language configuration constants for i18n support.\n *\n * Provides a default set of 16 supported languages, RTL language detection,\n * and the LanguageConfig interface used throughout the building_blocks package.\n */\n\n/**\n * Configuration for a supported language.\n *\n * Used by LanguageSelector, initializeI18n, and consuming apps\n * to display available languages with their native names and emoji flags.\n */\nexport interface LanguageConfig {\n /** ISO 639-1 language code (e.g., 'en', 'zh-hant') */\n code: string;\n /** Native name of the language (e.g., 'English', '日本語') */\n name: string;\n /** Emoji flag representing the language's primary region (e.g., '🇺🇸') */\n flag: string;\n}\n\n/**\n * Default set of 16 supported languages with their flags.\n * Apps can override this list by passing their own languages prop.\n */\nexport const DEFAULT_LANGUAGES: LanguageConfig[] = [\n { code: 'en', name: 'English', flag: '🇺🇸' },\n { code: 'ar', name: 'العربية', flag: '🇸🇦' },\n { code: 'de', name: 'Deutsch', flag: '🇩🇪' },\n { code: 'es', name: 'Español', flag: '🇪🇸' },\n { code: 'fr', name: 'Français', flag: '🇫🇷' },\n { code: 'it', name: 'Italiano', flag: '🇮🇹' },\n { code: 'ja', name: '日本語', flag: '🇯🇵' },\n { code: 'ko', name: '한국어', flag: '🇰🇷' },\n { code: 'pt', name: 'Português', flag: '🇵🇹' },\n { code: 'ru', name: 'Русский', flag: '🇷🇺' },\n { code: 'sv', name: 'Svenska', flag: '🇸🇪' },\n { code: 'th', name: 'ไทย', flag: '🇹🇭' },\n { code: 'uk', name: 'Українська', flag: '🇺🇦' },\n { code: 'vi', name: 'Tiếng Việt', flag: '🇻🇳' },\n { code: 'zh', name: '简体中文', flag: '🇨🇳' },\n { code: 'zh-hant', name: '繁體中文', flag: '🇹🇼' },\n];\n\n/**\n * Languages that use right-to-left text direction.\n */\nexport const RTL_LANGUAGES = ['ar'];\n\n/**\n * Check if a language code is RTL.\n *\n * @param languageCode - ISO 639-1 language code to check\n * @returns true if the language uses right-to-left text direction\n */\nexport function isRTL(languageCode: string): boolean {\n return RTL_LANGUAGES.includes(languageCode);\n}\n","import React, {\n useState,\n useCallback,\n useMemo,\n useRef,\n useEffect,\n} from 'react';\nimport { ChevronDownIcon } from '@heroicons/react/24/outline';\nimport { cn } from '../../utils';\nimport { ui } from '@sudobility/design';\nimport {\n DEFAULT_LANGUAGES,\n type LanguageConfig,\n} from '../../constants/languages';\n\nexport interface LanguageSelectorProps {\n /** Available languages (defaults to 16 built-in languages) */\n languages?: LanguageConfig[];\n /** Current language code */\n currentLanguage?: string;\n /** Language change handler */\n onLanguageChange?: (languageCode: string) => void;\n /** Variant: 'compact' for topbar, 'full' for settings */\n variant?: 'compact' | 'full';\n /** Custom className */\n className?: string;\n /** Label text for full variant */\n label?: string;\n /** Helper text for full variant */\n helperText?: string;\n}\n\n/**\n * LanguageSelector component with dropdown for switching languages.\n * Uses default 16 languages if none provided.\n *\n * @example\n * ```tsx\n * // Compact variant for topbar\n * <LanguageSelector\n * currentLanguage=\"en\"\n * onLanguageChange={(code) => i18n.changeLanguage(code)}\n * variant=\"compact\"\n * />\n *\n * // Full variant for settings pages\n * <LanguageSelector\n * currentLanguage=\"en\"\n * onLanguageChange={(code) => i18n.changeLanguage(code)}\n * variant=\"full\"\n * label=\"Language\"\n * helperText=\"Select your preferred language\"\n * />\n * ```\n */\nexport const LanguageSelector: React.FC<LanguageSelectorProps> = ({\n languages = DEFAULT_LANGUAGES,\n currentLanguage = 'en',\n onLanguageChange,\n variant = 'compact',\n className,\n label = 'Language',\n helperText = 'Select your preferred language',\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Sort languages alphabetically by name\n const sortedLanguages = useMemo(\n () => [...languages].sort((a, b) => a.name.localeCompare(b.name)),\n [languages]\n );\n\n const currentLang = useMemo(\n () => languages.find(lang => lang.code === currentLanguage) || languages[0],\n [languages, currentLanguage]\n );\n\n const handleLanguageChange = useCallback(\n (langCode: string) => {\n if (langCode !== currentLanguage) {\n onLanguageChange?.(langCode);\n }\n setIsOpen(false);\n },\n [currentLanguage, onLanguageChange]\n );\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () =>\n document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n // Close dropdown on escape\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }\n }, [isOpen]);\n\n if (variant === 'compact') {\n return (\n <div ref={dropdownRef} className={cn('relative', className)}>\n <button\n onClick={() => setIsOpen(!isOpen)}\n className={cn(\n 'flex items-center gap-2 px-3 py-2 h-10 rounded-lg',\n 'hover:bg-gray-100 dark:hover:bg-gray-700',\n 'transition-colors'\n )}\n aria-label='Select language'\n aria-expanded={isOpen}\n aria-haspopup='listbox'\n >\n <span className='text-lg leading-none'>{currentLang?.flag}</span>\n <span\n className={`hidden sm:block text-sm font-medium ${ui.text.label}`}\n >\n {currentLang?.name}\n </span>\n <ChevronDownIcon\n className={cn(\n `h-4 w-4 ${ui.text.muted} transition-transform`,\n isOpen && 'rotate-180'\n )}\n />\n </button>\n\n {isOpen && (\n <div\n className={cn(\n 'absolute right-0 mt-2 w-48 py-1 z-50',\n ui.background.surface,\n `border ${ui.border.default}`,\n 'rounded-lg shadow-lg'\n )}\n role='listbox'\n aria-label='Languages'\n >\n {sortedLanguages.map(lang => (\n <button\n key={lang.code}\n onClick={() => handleLanguageChange(lang.code)}\n className={cn(\n 'w-full flex items-center gap-3 px-3 py-2 text-left',\n 'hover:bg-gray-100 dark:hover:bg-gray-700',\n 'transition-colors',\n lang.code === currentLanguage &&\n 'bg-gray-100 dark:bg-gray-700 font-medium'\n )}\n role='option'\n aria-selected={lang.code === currentLanguage}\n >\n <span className='text-lg leading-none'>{lang.flag}</span>\n <span className={`text-sm ${ui.text.label}`}>{lang.name}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n }\n\n // Full variant for settings pages\n return (\n <div ref={dropdownRef} className={cn('space-y-2', className)}>\n <label className={`${ui.text.label} flex items-center gap-2`}>\n <span>{label}</span>\n </label>\n\n <div className='relative'>\n <button\n onClick={() => setIsOpen(!isOpen)}\n className={cn(\n 'flex items-center justify-between w-full px-3 py-2 text-left',\n ui.background.surface,\n `border ${ui.border.default}`,\n 'rounded-md',\n 'hover:bg-gray-50 dark:hover:bg-gray-700',\n 'transition-colors'\n )}\n aria-expanded={isOpen}\n aria-haspopup='listbox'\n >\n <div className='flex items-center gap-2'>\n <span className='text-lg leading-none'>{currentLang?.flag}</span>\n <span className={`text-sm ${ui.text.label}`}>\n {currentLang?.name}\n </span>\n </div>\n <ChevronDownIcon\n className={cn(\n `h-4 w-4 ${ui.text.muted} transition-transform`,\n isOpen && 'rotate-180'\n )}\n />\n </button>\n\n {isOpen && (\n <div\n className={cn(\n 'absolute left-0 right-0 mt-1 py-1 z-50',\n ui.background.surface,\n `border ${ui.border.default}`,\n 'rounded-md shadow-lg'\n )}\n role='listbox'\n aria-label='Languages'\n >\n {sortedLanguages.map(lang => (\n <button\n key={lang.code}\n onClick={() => handleLanguageChange(lang.code)}\n className={cn(\n 'w-full flex items-center gap-3 px-3 py-2 text-left',\n 'hover:bg-gray-100 dark:hover:bg-gray-700',\n 'transition-colors',\n lang.code === currentLanguage &&\n 'bg-gray-100 dark:bg-gray-700 font-medium'\n )}\n role='option'\n aria-selected={lang.code === currentLanguage}\n >\n <span className='text-lg leading-none'>{lang.flag}</span>\n <span className={`text-sm ${ui.text.label}`}>{lang.name}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n\n {helperText && <p className={`text-xs ${ui.text.muted}`}>{helperText}</p>}\n </div>\n );\n};\n\nexport default LanguageSelector;\n","import React, { useMemo, type ComponentType, type ReactNode } from 'react';\nimport {\n Topbar,\n TopbarProvider,\n TopbarLeft,\n TopbarCenter,\n TopbarRight,\n TopbarLogo,\n TopbarNavigation,\n TopbarActions,\n TopbarMobileContent,\n Logo,\n type TopbarNavItem,\n} from '@sudobility/components';\nimport { cn } from '../../utils';\nimport {\n LanguageSelector,\n type LanguageSelectorProps,\n} from './language-selector';\nimport type {\n MenuItemConfig,\n LogoConfig,\n LanguageConfig,\n LinkComponentProps,\n} from '../../types';\nimport { DEFAULT_LANGUAGES } from '../../constants/languages';\n\nexport interface AppTopBarProps {\n /** Logo configuration */\n logo: LogoConfig;\n\n /** Navigation menu items */\n menuItems: MenuItemConfig[];\n\n /** Available languages for selector (defaults to 16 built-in languages) */\n languages?: LanguageConfig[];\n\n /** Current language code */\n currentLanguage?: string;\n\n /** Language change handler */\n onLanguageChange?: (languageCode: string) => void;\n\n /** Hide language selector */\n hideLanguageSelector?: boolean;\n\n /** Language selector props override */\n languageSelectorProps?: Partial<LanguageSelectorProps>;\n\n /** Breakpoint to collapse navigation to hamburger menu */\n collapseBelow?: 'sm' | 'md' | 'lg' | 'xl';\n\n /** Render prop for account/auth section (right side of topbar) */\n renderAccountSection?: () => ReactNode;\n\n /** Render prop for center section (e.g., search bar) - shown on desktop */\n renderCenterSection?: () => ReactNode;\n\n /** Render prop for mobile-specific content (e.g., mobile search) - shown below main topbar on mobile */\n renderMobileContent?: () => ReactNode;\n\n /** Custom Link component for navigation (for react-router-dom, Next.js, etc.) */\n LinkComponent?: ComponentType<LinkComponentProps>;\n\n /** Optional sticky positioning */\n sticky?: boolean;\n\n /** Optional variant */\n variant?: 'default' | 'app';\n\n /** Mobile menu label for accessibility */\n mobileMenuLabel?: string;\n\n /** Custom className for topbar */\n className?: string;\n\n /** z-index level */\n zIndex?: 'default' | 'highest' | 'high';\n\n /** Aria label for navigation */\n ariaLabel?: string;\n}\n\n/**\n * Default Link component that renders a plain anchor tag.\n * Apps should provide their own LinkComponent for router integration.\n */\nconst DefaultLinkComponent: ComponentType<LinkComponentProps> = ({\n href,\n className,\n children,\n onClick,\n}) => (\n <a href={href} className={className} onClick={onClick}>\n {children}\n </a>\n);\n\n/**\n * AppTopBar - Base topbar component for Sudobility apps.\n *\n * Features:\n * - Logo with app name on the left\n * - Navigation menu items with icons\n * - Language selector\n * - Render prop for center section (e.g., search bar)\n * - Render prop for account/auth section\n * - Render prop for mobile-specific content\n * - Responsive with hamburger menu on mobile\n * - Dark mode support\n */\nexport const AppTopBar: React.FC<AppTopBarProps> = ({\n logo,\n menuItems,\n languages = DEFAULT_LANGUAGES,\n currentLanguage = 'en',\n onLanguageChange,\n hideLanguageSelector = false,\n languageSelectorProps,\n collapseBelow = 'lg',\n renderAccountSection,\n renderCenterSection,\n renderMobileContent,\n LinkComponent = DefaultLinkComponent,\n sticky = true,\n variant = 'default',\n mobileMenuLabel = 'Menu',\n className,\n zIndex = 'highest',\n ariaLabel = 'Main navigation',\n}) => {\n // Filter menu items that should be shown\n const visibleMenuItems = useMemo(\n () => menuItems.filter(item => item.show !== false),\n [menuItems]\n );\n\n // Convert MenuItemConfig to TopbarNavItem (recursively for children)\n const navItems: TopbarNavItem[] = useMemo(() => {\n const mapItem = (item: MenuItemConfig): TopbarNavItem => ({\n id: item.id,\n label: item.label,\n icon: item.icon,\n href: item.href,\n className: item.className,\n children: item.children\n ?.filter(child => child.show !== false)\n .map(mapItem),\n });\n return visibleMenuItems.map(mapItem);\n }, [visibleMenuItems]);\n\n // Wrapper to adapt LinkComponent to TopbarNavigation expected interface\n const LinkWrapper: ComponentType<{\n href: string;\n className?: string;\n children: ReactNode;\n }> = useMemo(\n () =>\n ({ href, className, children }) => (\n <LinkComponent href={href} className={className}>\n {children}\n </LinkComponent>\n ),\n [LinkComponent]\n );\n\n const handleLogoClick = () => {\n logo.onClick?.();\n };\n\n return (\n <TopbarProvider variant={variant} sticky={sticky}>\n <Topbar\n variant={variant}\n sticky={sticky}\n zIndex={zIndex}\n aria-label={ariaLabel}\n className={cn(className)}\n >\n <TopbarLeft>\n {navItems.length > 0 ? (\n <TopbarNavigation\n items={navItems}\n collapseBelow={collapseBelow}\n LinkComponent={LinkWrapper}\n mobileMenuLabel={mobileMenuLabel}\n >\n <TopbarLogo onClick={handleLogoClick} size='md'>\n <Logo\n size='md'\n logoSrc={logo.src}\n logoText={logo.appName}\n logoAlt={logo.alt || logo.appName}\n showText={true}\n />\n </TopbarLogo>\n </TopbarNavigation>\n ) : (\n <TopbarLogo onClick={handleLogoClick} size='md'>\n <Logo\n size='md'\n logoSrc={logo.src}\n logoText={logo.appName}\n logoAlt={logo.alt || logo.appName}\n showText={true}\n />\n </TopbarLogo>\n )}\n </TopbarLeft>\n\n {renderCenterSection && (\n <TopbarCenter>{renderCenterSection()}</TopbarCenter>\n )}\n\n <TopbarRight>\n <TopbarActions gap='md'>\n {!hideLanguageSelector && (\n <LanguageSelector\n languages={languages}\n currentLanguage={currentLanguage}\n onLanguageChange={onLanguageChange}\n variant='compact'\n {...languageSelectorProps}\n />\n )}\n {renderAccountSection?.()}\n </TopbarActions>\n </TopbarRight>\n\n {renderMobileContent && (\n <TopbarMobileContent>{renderMobileContent()}</TopbarMobileContent>\n )}\n </Topbar>\n </TopbarProvider>\n );\n};\n\nexport default AppTopBar;\n","import React, { type ReactNode, type ComponentType } from 'react';\nimport { AppTopBar, type AppTopBarProps } from './app-topbar';\nimport { cn } from '../../utils';\nimport { GRADIENT_CLASSES } from '@sudobility/design';\n\n/**\n * Auth menu item for the authenticated user dropdown.\n * This matches the AuthMenuItem interface from @sudobility/auth-components.\n */\nexport interface AuthMenuItem {\n /** Unique identifier */\n id: string;\n /** Display label */\n label: string;\n /** Icon element (typically a small SVG) */\n icon?: ReactNode;\n /** Click handler */\n onClick?: () => void;\n /** Show divider after this item */\n dividerAfter?: boolean;\n}\n\n/**\n * Props for the AuthAction component from @sudobility/auth-components.\n */\nexport interface AuthActionProps {\n /** Avatar size in pixels */\n avatarSize?: number;\n /** Dropdown alignment */\n dropdownAlign?: 'left' | 'right';\n /** Login button click handler */\n onLoginClick?: () => void;\n /** Menu items for authenticated user dropdown */\n menuItems?: AuthMenuItem[];\n /** Custom login button text */\n loginButtonText?: string;\n /** Custom className for login button */\n loginButtonClassName?: string;\n}\n\nexport interface AppTopBarWithFirebaseAuthProps extends Omit<\n AppTopBarProps,\n 'renderAccountSection'\n> {\n /**\n * AuthAction component from @sudobility/auth-components.\n * This is passed as a prop to avoid hard dependency on auth-components.\n */\n AuthActionComponent: ComponentType<AuthActionProps>;\n\n /** Additional menu items for authenticated users */\n authenticatedMenuItems?: AuthMenuItem[];\n\n /** Login button click handler */\n onLoginClick?: () => void;\n\n /** Avatar size in pixels */\n avatarSize?: number;\n\n /** Dropdown alignment */\n dropdownAlign?: 'left' | 'right';\n\n /** Custom login button text */\n loginButtonText?: string;\n\n /** Custom login button className */\n loginButtonClassName?: string;\n}\n\n/**\n * AppTopBarWithFirebaseAuth - TopBar with Firebase authentication integration.\n *\n * This component wraps AppTopBar and provides the AuthAction component\n * from @sudobility/auth-components for the account section.\n *\n * Note: The AuthAction component must be passed as a prop to avoid\n * hard dependency on @sudobility/auth-components.\n *\n * @example\n * ```tsx\n * import { AuthAction } from '@sudobility/auth-components';\n *\n * <AppTopBarWithFirebaseAuth\n * logo={{ src: '/logo.png', appName: 'My App' }}\n * menuItems={[...]}\n * AuthActionComponent={AuthAction}\n * onLoginClick={() => navigate('/login')}\n * authenticatedMenuItems={[\n * { id: 'dashboard', label: 'Dashboard', onClick: () => navigate('/dashboard') },\n * ]}\n * />\n * ```\n */\nexport const AppTopBarWithFirebaseAuth: React.FC<\n AppTopBarWithFirebaseAuthProps\n> = ({\n AuthActionComponent,\n authenticatedMenuItems = [],\n onLoginClick,\n avatarSize = 32,\n dropdownAlign = 'right',\n loginButtonText,\n loginButtonClassName,\n ...topBarProps\n}) => {\n const renderAccountSection = () => (\n <AuthActionComponent\n avatarSize={avatarSize}\n dropdownAlign={dropdownAlign}\n onLoginClick={onLoginClick}\n menuItems={authenticatedMenuItems}\n loginButtonText={loginButtonText}\n loginButtonClassName={cn(\n GRADIENT_CLASSES.headerButton,\n 'py-1.5',\n loginButtonClassName\n )}\n />\n );\n\n return (\n <AppTopBar {...topBarProps} renderAccountSection={renderAccountSection} />\n );\n};\n\nexport default AppTopBarWithFirebaseAuth;\n","import React, { type ReactNode, type ComponentType } from 'react';\nimport { AppTopBar, type AppTopBarProps } from './app-topbar';\nimport { cn } from '../../utils';\nimport { GRADIENT_CLASSES, buttonVariant, ui } from '@sudobility/design';\n\n/**\n * Wallet menu item for the connected wallet dropdown.\n */\nexport interface WalletMenuItem {\n /** Unique identifier */\n id: string;\n /** Display label */\n label: string;\n /** Icon component */\n icon?: ComponentType<{ className?: string }>;\n /** Click handler */\n onClick: () => void;\n /** Whether this is a separator */\n separator?: boolean;\n}\n\n/**\n * Auth status enum matching @sudobility/types.\n */\nexport enum AuthStatus {\n DISCONNECTED = 'disconnected',\n CONNECTED = 'connected',\n VERIFIED = 'verified',\n}\n\n/**\n * Chain type enum matching @sudobility/types.\n */\nexport enum ChainType {\n EVM = 'evm',\n SOLANA = 'solana',\n}\n\n/**\n * Props for the WalletDropdownMenu component from @sudobility/web3-components.\n */\nexport interface WalletDropdownMenuProps {\n walletAddress: string;\n authStatus: AuthStatus | string;\n chainType: ChainType | string | 'unknown';\n menuItems: WalletMenuItem[];\n avatar?: string;\n displayName?: string;\n statusLabels?: {\n verified?: string;\n connected?: string;\n disconnected?: string;\n };\n}\n\nexport interface AppTopBarWithWalletProps extends Omit<\n AppTopBarProps,\n 'renderAccountSection'\n> {\n /**\n * WalletDropdownMenu component from @sudobility/web3-components.\n * This is passed as a prop to avoid hard dependency on web3-components.\n */\n WalletDropdownMenuComponent?: ComponentType<WalletDropdownMenuProps>;\n\n /** Whether wallet is connected */\n isConnected: boolean;\n\n /** Connected wallet address */\n walletAddress?: string;\n\n /** Authentication status */\n authStatus?: AuthStatus | string;\n\n /** Chain type (EVM, Solana, etc.) */\n chainType?: ChainType | string | 'unknown';\n\n /** Connect button click handler */\n onConnect: () => void;\n\n /** Disconnect handler */\n onDisconnect: () => Promise<void>;\n\n /** Custom menu items for wallet dropdown */\n walletMenuItems?: WalletMenuItem[];\n\n /** Connect button content (default: \"Connect Wallet\") */\n connectButtonContent?: ReactNode;\n\n /** Connect button className (supports gradient classes from @sudobility/design) */\n connectButtonClassName?: string;\n\n /** Use gradient styling for connect button */\n useGradientButton?: boolean;\n\n /** Optional user avatar */\n avatar?: string;\n\n /** Optional display name */\n displayName?: string;\n\n /** Custom status labels */\n statusLabels?: {\n verified?: string;\n connected?: string;\n disconnected?: string;\n };\n}\n\n/**\n * Default connect button when WalletDropdownMenuComponent is not provided\n * or when wallet is not connected.\n */\nconst DefaultConnectButton: React.FC<{\n onClick: () => void;\n content?: ReactNode;\n className?: string;\n useGradient?: boolean;\n}> = ({ onClick, content = 'Connect Wallet', className, useGradient }) => (\n <button\n onClick={onClick}\n className={cn(\n useGradient\n ? GRADIENT_CLASSES.headerButton\n : cn(\n 'px-4 py-2 text-sm font-medium rounded-lg transition-colors',\n buttonVariant('primary')\n ),\n className\n )}\n >\n {content}\n </button>\n);\n\n/**\n * Simple fallback wallet display when WalletDropdownMenuComponent is not provided.\n */\nconst FallbackWalletDisplay: React.FC<{\n walletAddress: string;\n onDisconnect: () => Promise<void>;\n}> = ({ walletAddress, onDisconnect }) => {\n const truncatedAddress = `${walletAddress.slice(0, 6)}...${walletAddress.slice(-4)}`;\n\n return (\n <div className='flex items-center gap-2'>\n <span className={`text-sm font-medium ${ui.text.label}`}>\n {truncatedAddress}\n </span>\n <button\n onClick={() => onDisconnect()}\n className={`text-xs ${ui.text.muted} hover:text-gray-700 dark:hover:text-gray-200`}\n >\n Disconnect\n </button>\n </div>\n );\n};\n\n/**\n * AppTopBarWithWallet - TopBar with wallet connection integration.\n *\n * This component wraps AppTopBar and provides wallet connection UI\n * for the account section. Uses WalletDropdownMenu from @sudobility/web3-components\n * when provided.\n *\n * @example\n * ```tsx\n * import { WalletDropdownMenu } from '@sudobility/web3-components';\n *\n * <AppTopBarWithWallet\n * logo={{ src: '/logo.png', appName: 'My App' }}\n * menuItems={[...]}\n * WalletDropdownMenuComponent={WalletDropdownMenu}\n * isConnected={isConnected}\n * walletAddress={walletAddress}\n * authStatus={authStatus}\n * chainType={chainType}\n * onConnect={() => navigate('/connect')}\n * onDisconnect={handleDisconnect}\n * walletMenuItems={[\n * { id: 'copy', label: 'Copy Address', icon: ClipboardIcon, onClick: handleCopy },\n * { id: 'disconnect', label: 'Disconnect', icon: LogoutIcon, onClick: handleDisconnect },\n * ]}\n * />\n * ```\n */\nexport const AppTopBarWithWallet: React.FC<AppTopBarWithWalletProps> = ({\n WalletDropdownMenuComponent,\n isConnected,\n walletAddress,\n authStatus = AuthStatus.DISCONNECTED,\n chainType = 'unknown',\n onConnect,\n onDisconnect,\n walletMenuItems = [],\n connectButtonContent,\n connectButtonClassName,\n useGradientButton = true,\n avatar,\n displayName,\n statusLabels,\n ...topBarProps\n}) => {\n const renderAccountSection = () => {\n // Not connected - show connect button\n if (!isConnected || !walletAddress) {\n return (\n <DefaultConnectButton\n onClick={onConnect}\n content={connectButtonContent}\n className={connectButtonClassName}\n useGradient={useGradientButton}\n />\n );\n }\n\n // Connected with WalletDropdownMenu component\n if (WalletDropdownMenuComponent) {\n return (\n <WalletDropdownMenuComponent\n walletAddress={walletAddress}\n authStatus={authStatus}\n chainType={chainType}\n menuItems={walletMenuItems}\n avatar={avatar}\n displayName={displayName}\n statusLabels={statusLabels}\n />\n );\n }\n\n // Connected without WalletDropdownMenu - fallback display\n return (\n <FallbackWalletDisplay\n walletAddress={walletAddress}\n onDisconnect={onDisconnect}\n />\n );\n };\n\n return (\n <AppTopBar {...topBarProps} renderAccountSection={renderAccountSection} />\n );\n};\n\nexport default AppTopBarWithWallet;\n","import React, {\n useState,\n useRef,\n useEffect,\n useCallback,\n type ComponentType,\n} from 'react';\nimport { CalendarDaysIcon } from '@heroicons/react/24/outline';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils';\nimport { ui } from '@sudobility/design';\nimport type {\n BreadcrumbItem,\n ShareConfig,\n TalkToFounderConfig,\n LinkComponentProps,\n} from '../../types';\n\nconst breadcrumbContainerVariants = cva('border-b', {\n variants: {\n variant: {\n default: `${ui.background.surface} ${ui.border.default}`,\n transparent: 'bg-transparent border-transparent',\n subtle: `${ui.background.subtle} ${ui.border.default}`,\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nexport interface AppBreadcrumbsProps extends VariantProps<\n typeof breadcrumbContainerVariants\n> {\n /** Breadcrumb items */\n items: BreadcrumbItem[];\n\n /** Share configuration (shows social share buttons on right) */\n shareConfig?: ShareConfig;\n\n /** Talk to founder button configuration */\n talkToFounder?: TalkToFounderConfig;\n\n /** Custom Link component */\n LinkComponent?: ComponentType<LinkComponentProps>;\n\n /** Custom className for the container */\n className?: string;\n\n /** Custom className for the inner content */\n contentClassName?: string;\n}\n\n// Social media share URL generators\nconst createShareUrl = {\n twitter: (url: string, text: string, hashtags: string[]) => {\n const hashtagStr =\n hashtags.length > 0 ? `&hashtags=${hashtags.join(',')}` : '';\n return `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}${hashtagStr}`;\n },\n facebook: (url: string) => {\n return `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`;\n },\n linkedin: (url: string) => {\n return `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`;\n },\n reddit: (url: string, title: string) => {\n return `https://reddit.com/submit?url=${encodeURIComponent(url)}&title=${encodeURIComponent(title)}`;\n },\n telegram: (url: string, text: string) => {\n return `https://t.me/share/url?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`;\n },\n email: (url: string, title: string, description: string) => {\n return `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(description + '\\n\\n' + url)}`;\n },\n};\n\n/**\n * Share dropdown component with keyboard navigation support.\n * Supports: Enter/Space to toggle, Escape to close, Arrow keys to navigate items.\n */\nconst ShareDropdown: React.FC<{ shareConfig: ShareConfig }> = ({\n shareConfig,\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const [shareUrl, setShareUrl] = useState<string>('');\n const [isPreparingShare, setIsPreparingShare] = useState(false);\n const [showCopiedFeedback, setShowCopiedFeedback] = useState(false);\n const [focusedIndex, setFocusedIndex] = useState(-1);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n useEffect(() => {\n const onBeforeShare = shareConfig.onBeforeShare;\n if (onBeforeShare) {\n const prepareUrl = async () => {\n setIsPreparingShare(true);\n try {\n const baseUrl =\n typeof window !== 'undefined' ? window.location.href : '';\n const modifiedUrl = await onBeforeShare(baseUrl);\n setShareUrl(modifiedUrl);\n } catch {\n const baseUrl =\n typeof window !== 'undefined' ? window.location.href : '';\n setShareUrl(baseUrl);\n } finally {\n setIsPreparingShare(false);\n }\n };\n prepareUrl();\n } else {\n setShareUrl('');\n }\n }, [shareConfig]);\n\n // Close dropdown on outside click\n useEffect(() => {\n if (!isOpen) return;\n const handleClickOutside = (event: MouseEvent) => {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n setFocusedIndex(-1);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [isOpen]);\n\n // Close on Escape, navigate with arrow keys\n useEffect(() => {\n if (!isOpen) return;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsOpen(false);\n setFocusedIndex(-1);\n triggerRef.current?.focus();\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen]);\n\n // Focus the item at focusedIndex when it changes\n useEffect(() => {\n if (focusedIndex >= 0 && itemRefs.current[focusedIndex]) {\n itemRefs.current[focusedIndex]?.focus();\n }\n }, [focusedIndex]);\n\n const url =\n shareUrl || (typeof window !== 'undefined' ? window.location.href : '');\n\n const sharePlatforms = [\n {\n name: 'Twitter',\n url: createShareUrl.twitter(url, shareConfig.title, shareConfig.hashtags),\n color: 'text-blue-400',\n },\n {\n name: 'Facebook',\n url: createShareUrl.facebook(url),\n color: 'text-blue-600',\n },\n {\n name: 'LinkedIn',\n url: createShareUrl.linkedin(url),\n color: 'text-blue-700',\n },\n {\n name: 'Reddit',\n url: createShareUrl.reddit(url, shareConfig.title),\n color: 'text-orange-600',\n },\n {\n name: 'Telegram',\n url: createShareUrl.telegram(url, shareConfig.title),\n color: 'text-blue-500',\n },\n {\n name: 'Email',\n url: createShareUrl.email(\n url,\n shareConfig.title,\n shareConfig.description\n ),\n color: 'text-gray-600',\n },\n ];\n\n // Check if Web Share API with files is supported\n const hasImageShare = !!shareConfig.getImageDataUrl;\n const [supportsWebShare, setSupportsWebShare] = useState(false);\n\n useEffect(() => {\n if (!hasImageShare) return;\n // Check if browser supports sharing files\n if (typeof navigator !== 'undefined' && navigator.canShare) {\n const testFile = new File([''], 'test.png', { type: 'image/png' });\n try {\n setSupportsWebShare(navigator.canShare({ files: [testFile] }));\n } catch {\n setSupportsWebShare(false);\n }\n }\n }, [hasImageShare]);\n\n // Extra items: Web Share (if supported) + Download Image (if getImageDataUrl provided)\n const extraItemCount = hasImageShare ? (supportsWebShare ? 2 : 1) : 0;\n // Total items = platforms + extra image items + copy link\n const totalItems = sharePlatforms.length + extraItemCount + 1;\n\n const copyToClipboard = async () => {\n try {\n await navigator.clipboard.writeText(url);\n setShowCopiedFeedback(true);\n setTimeout(() => {\n setShowCopiedFeedback(false);\n setIsOpen(false);\n }, 1500);\n } catch {\n // Copy failed\n }\n };\n\n const handleSocialShare = (platformUrl: string) => {\n window.open(\n platformUrl,\n '_blank',\n 'noopener,noreferrer,width=600,height=400'\n );\n setIsOpen(false);\n };\n\n /** Convert a base64 data URL to a Blob */\n const dataUrlToBlob = (dataUrl: string): Blob => {\n const [header, base64] = dataUrl.split(',');\n const mime = header.match(/:(.*?);/)?.[1] ?? 'image/png';\n const bytes = atob(base64);\n const arr = new Uint8Array(bytes.length);\n for (let i = 0; i < bytes.length; i++) arr[i] = bytes.charCodeAt(i);\n return new Blob([arr], { type: mime });\n };\n\n const handleWebShare = async () => {\n if (!shareConfig.getImageDataUrl) return;\n try {\n const dataUrl = await shareConfig.getImageDataUrl();\n if (!dataUrl) return;\n const blob = dataUrlToBlob(dataUrl);\n const file = new File([blob], 'puzzle.png', { type: 'image/png' });\n await navigator.share({\n title: shareConfig.title,\n text: shareConfig.description,\n url,\n files: [file],\n });\n } catch (err) {\n if (err instanceof Error && err.name !== 'AbortError') {\n console.error('Web Share failed:', err);\n }\n }\n setIsOpen(false);\n };\n\n const handleDownloadImage = async () => {\n if (!shareConfig.getImageDataUrl) return;\n try {\n const dataUrl = await shareConfig.getImageDataUrl();\n if (!dataUrl) return;\n const blob = dataUrlToBlob(dataUrl);\n const blobUrl = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = blobUrl;\n link.download = 'puzzle.png';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(blobUrl);\n } catch (err) {\n console.error('Download failed:', err);\n }\n setIsOpen(false);\n };\n\n const handleToggle = () => {\n const next = !isOpen;\n setIsOpen(next);\n if (next) {\n setFocusedIndex(0);\n } else {\n setFocusedIndex(-1);\n }\n };\n\n const handleMenuKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n setFocusedIndex(prev => (prev + 1) % totalItems);\n break;\n case 'ArrowUp':\n event.preventDefault();\n setFocusedIndex(prev => (prev - 1 + totalItems) % totalItems);\n break;\n case 'Home':\n event.preventDefault();\n setFocusedIndex(0);\n break;\n case 'End':\n event.preventDefault();\n setFocusedIndex(totalItems - 1);\n break;\n case 'Tab':\n setIsOpen(false);\n setFocusedIndex(-1);\n break;\n }\n },\n [totalItems]\n );\n\n return (\n <div className='relative' ref={dropdownRef}>\n <button\n ref={triggerRef}\n onClick={handleToggle}\n disabled={isPreparingShare}\n className='flex items-center justify-center w-8 h-8 bg-blue-50 hover:bg-blue-100 dark:bg-blue-900/30 dark:hover:bg-blue-900/50 text-blue-600 dark:text-blue-400 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed'\n aria-label='Share this page'\n aria-expanded={isOpen}\n aria-haspopup='menu'\n >\n {isPreparingShare ? (\n <div className='w-4 h-4 border-2 border-blue-600 border-t-transparent rounded-full animate-spin' />\n ) : (\n <svg\n className='w-4 h-4'\n fill='none'\n stroke='currentColor'\n viewBox='0 0 24 24'\n aria-hidden='true'\n >\n <path\n strokeLinecap='round'\n strokeLinejoin='round'\n strokeWidth={2}\n d='M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z'\n />\n </svg>\n )}\n </button>\n\n {isOpen && (\n <div\n className={`absolute right-0 top-10 z-[999999] w-40 ${ui.background.surface} rounded-lg shadow-xl border ${ui.border.default} py-1`}\n role='menu'\n aria-label='Share options'\n onKeyDown={handleMenuKeyDown}\n >\n {sharePlatforms.map((platform, index) => (\n <button\n key={platform.name}\n ref={el => {\n itemRefs.current[index] = el;\n }}\n onClick={() => handleSocialShare(platform.url)}\n className='w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors focus:bg-gray-50 dark:focus:bg-gray-700 focus:outline-none'\n role='menuitem'\n tabIndex={focusedIndex === index ? 0 : -1}\n >\n <span className={`text-sm ${platform.color}`}>\n {platform.name}\n </span>\n </button>\n ))}\n <div\n className={`border-t ${ui.border.default} my-1`}\n role='separator'\n />\n {/* Image sharing options (conditional) */}\n {hasImageShare && supportsWebShare && (\n <button\n ref={el => {\n itemRefs.current[sharePlatforms.length] = el;\n }}\n onClick={handleWebShare}\n className='w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors focus:bg-gray-50 dark:focus:bg-gray-700 focus:outline-none'\n role='menuitem'\n tabIndex={focusedIndex === sharePlatforms.length ? 0 : -1}\n >\n <span className='text-sm text-purple-600 dark:text-purple-400'>\n Share with Image\n </span>\n </button>\n )}\n {hasImageShare && (\n <button\n ref={el => {\n const idx = sharePlatforms.length + (supportsWebShare ? 1 : 0);\n itemRefs.current[idx] = el;\n }}\n onClick={handleDownloadImage}\n className='w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors focus:bg-gray-50 dark:focus:bg-gray-700 focus:outline-none'\n role='menuitem'\n tabIndex={\n focusedIndex ===\n sharePlatforms.length + (supportsWebShare ? 1 : 0)\n ? 0\n : -1\n }\n >\n <span className='text-sm text-green-600 dark:text-green-400'>\n Download Image\n </span>\n </button>\n )}\n {hasImageShare && (\n <div\n className={`border-t ${ui.border.default} my-1`}\n role='separator'\n />\n )}\n <button\n ref={el => {\n itemRefs.current[sharePlatforms.length + extraItemCount] = el;\n }}\n onClick={copyToClipboard}\n className='w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors focus:bg-gray-50 dark:focus:bg-gray-700 focus:outline-none'\n role='menuitem'\n tabIndex={\n focusedIndex === sharePlatforms.length + extraItemCount ? 0 : -1\n }\n >\n <span className={`text-sm ${ui.text.label}`}>\n {showCopiedFeedback ? 'Copied!' : 'Copy Link'}\n </span>\n </button>\n </div>\n )}\n </div>\n );\n};\n\n/**\n * Talk to Founder button - matches share button style\n */\nconst TalkToFounderButton: React.FC<{ config: TalkToFounderConfig }> = ({\n config,\n}) => {\n const IconComponent = config.icon || CalendarDaysIcon;\n const buttonText = config.buttonText || 'Talk to Founder';\n\n return (\n <a\n href={config.meetingUrl}\n target='_blank'\n rel='noopener noreferrer'\n className={cn(\n 'inline-flex items-center gap-1.5 px-2.5 h-8',\n 'text-sm font-medium',\n 'text-blue-600 dark:text-blue-400',\n 'hover:text-blue-700 dark:hover:text-blue-300',\n 'bg-blue-50 dark:bg-blue-900/30',\n 'hover:bg-blue-100 dark:hover:bg-blue-900/50',\n 'rounded-lg',\n 'transition-colors'\n )}\n >\n <IconComponent className='h-4 w-4' />\n <span>{buttonText}</span>\n </a>\n );\n};\n\n/**\n * AppBreadcrumbs - Self-contained breadcrumb navigation with share and \"Talk to Founder\" button.\n *\n * @example\n * ```tsx\n * <AppBreadcrumbs\n * items={[\n * { label: 'Home', href: '/' },\n * { label: 'Products', href: '/products' },\n * { label: 'Widget', current: true },\n * ]}\n * shareConfig={{\n * title: 'Widget Page',\n * description: 'Check out this widget',\n * hashtags: ['widget'],\n * }}\n * talkToFounder={{\n * meetingUrl: 'https://calendly.com/founder',\n * }}\n * variant=\"default\"\n * />\n * ```\n */\nexport const AppBreadcrumbs: React.FC<AppBreadcrumbsProps> = ({\n items,\n shareConfig,\n talkToFounder,\n variant = 'default',\n className,\n contentClassName,\n}) => {\n // Don't render if no items\n if (!items || items.length === 0) {\n return null;\n }\n\n return (\n <div className={cn(breadcrumbContainerVariants({ variant }), className)}>\n <div className={cn('max-w-7xl mx-auto px-4 py-2', contentClassName)}>\n <div className='flex items-center justify-between'>\n {/* Breadcrumb trail */}\n <nav aria-label='Breadcrumb'>\n <ol className='flex items-center text-sm space-x-2'>\n {items.map((item, index) => (\n <React.Fragment key={index}>\n <li>\n {item.current || !item.href ? (\n <span className={ui.text.body}>{item.label}</span>\n ) : (\n <a\n href={item.href}\n className={`${ui.text.linkSubtle} transition-colors`}\n >\n {item.label}\n </a>\n )}\n </li>\n {index < items.length - 1 && (\n <li>\n <span className={ui.text.muted}>/</span>\n </li>\n )}\n </React.Fragment>\n ))}\n </ol>\n </nav>\n\n {/* Right side: Talk to Founder + Share */}\n <div className='flex items-center gap-2'>\n {talkToFounder && <TalkToFounderButton config={talkToFounder} />}\n {shareConfig && <ShareDropdown shareConfig={shareConfig} />}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default AppBreadcrumbs;\n","import { type ComponentType } from 'react';\nimport type { LinkComponentProps } from '../../types';\n\n/**\n * Default link component that renders a plain anchor.\n * Shared between AppFooter and AppFooterForHomePage.\n */\nexport const DefaultLinkComponent: ComponentType<LinkComponentProps> = ({\n href,\n className,\n children,\n onClick,\n}) => (\n <a href={href} className={className} onClick={onClick}>\n {children}\n </a>\n);\n\n/**\n * Helper to get copyright year or range.\n * Shared between AppFooter and AppFooterForHomePage.\n *\n * @param startYear - The starting year for the copyright range (default: 2025)\n * @returns A string representing the year or year range\n */\nexport function getCopyrightYear(startYear = 2025): string {\n const currentYear = new Date().getFullYear();\n if (currentYear === startYear) {\n return String(startYear);\n } else if (currentYear > startYear) {\n return `${startYear}-${currentYear}`;\n }\n return String(startYear);\n}\n","import React, { useCallback, type ComponentType } from 'react';\nimport {\n Footer as FooterContainer,\n FooterCompact,\n FooterCompactLeft,\n FooterCompactRight,\n FooterVersion,\n FooterCopyright,\n} from '@sudobility/components';\nimport { ui } from '@sudobility/design';\nimport { cn } from '../../utils';\nimport type {\n StatusIndicatorConfig,\n LinkComponentProps,\n FooterLinkItem,\n AnalyticsTrackingParams,\n} from '../../types';\nimport { DefaultLinkComponent, getCopyrightYear } from './shared';\n\n/**\n * Props for the SystemStatusIndicator component from @sudobility/devops-components.\n */\nexport interface SystemStatusIndicatorProps {\n statusPageUrl: string;\n apiEndpoint?: string;\n refreshInterval?: number;\n size?: 'sm' | 'md' | 'lg';\n version?: string;\n isNetworkOnline?: boolean;\n}\n\nexport interface AppFooterProps {\n /** App version string */\n version?: string;\n\n /** Copyright year or range (e.g., \"2025\" or \"2025-2026\") */\n copyrightYear?: string;\n\n /** Company name */\n companyName: string;\n\n /** Company URL (optional - creates a link if provided) */\n companyUrl?: string;\n\n /** Rights text (e.g., \"All rights reserved\") */\n rightsText?: string;\n\n /** Status indicator config (optional) */\n statusIndicator?: StatusIndicatorConfig;\n\n /**\n * SystemStatusIndicator component from @sudobility/devops-components.\n * Pass this to enable status indicator functionality.\n */\n StatusIndicatorComponent?: ComponentType<SystemStatusIndicatorProps>;\n\n /** Right-side links (e.g., Privacy, Terms) */\n links?: FooterLinkItem[];\n\n /** Custom Link component */\n LinkComponent?: ComponentType<LinkComponentProps>;\n\n /** Sticky positioning (sticks to bottom of viewport) */\n sticky?: boolean;\n\n /** Network online status (for status indicator) */\n isNetworkOnline?: boolean;\n\n /** Custom className */\n className?: string;\n\n /** Optional analytics tracking callback */\n onTrack?: (params: AnalyticsTrackingParams) => void;\n}\n\n/**\n * AppFooter - Compact footer for app pages.\n *\n * Features:\n * - Version display\n * - Copyright with company name\n * - System status indicator (optional)\n * - Right-side links (Privacy, Terms, etc.)\n * - Sticky positioning option\n * - Dark mode support\n *\n * @example\n * ```tsx\n * import { SystemStatusIndicator } from '@sudobility/devops-components';\n *\n * <AppFooter\n * version=\"1.0.0\"\n * companyName=\"Sudobility Inc.\"\n * companyUrl=\"/\"\n * rightsText=\"All rights reserved\"\n * statusIndicator={{\n * statusPageUrl: 'https://status.example.com',\n * apiEndpoint: 'https://status.example.com/api/v1/status',\n * }}\n * StatusIndicatorComponent={SystemStatusIndicator}\n * links={[\n * { label: 'Privacy', href: '/privacy' },\n * { label: 'Terms', href: '/terms' },\n * ]}\n * sticky\n * />\n * ```\n */\nexport const AppFooter: React.FC<AppFooterProps> = ({\n version,\n copyrightYear,\n companyName,\n companyUrl,\n rightsText = 'All rights reserved',\n statusIndicator,\n StatusIndicatorComponent,\n links = [],\n LinkComponent = DefaultLinkComponent,\n sticky = true,\n isNetworkOnline = true,\n className,\n onTrack,\n}) => {\n const year = copyrightYear || getCopyrightYear();\n\n // Helper to track analytics events\n const track = useCallback(\n (label: string, params?: Record<string, unknown>) => {\n onTrack?.({\n eventType: 'link_click',\n componentName: 'AppFooter',\n label,\n params,\n });\n },\n [onTrack]\n );\n\n // Create a tracked link click handler\n const createTrackedLinkHandler = useCallback(\n (\n linkLabel: string,\n linkHref: string,\n originalOnClick?: (e: React.MouseEvent) => void\n ) =>\n (e: React.MouseEvent) => {\n track('footer_link_clicked', {\n link_label: linkLabel,\n link_href: linkHref,\n });\n originalOnClick?.(e);\n },\n [track]\n );\n\n const companyLink = companyUrl ? (\n <LinkComponent\n href={companyUrl}\n className={cn(ui.text.linkSubtle, ui.transition.default)}\n >\n {companyName}\n </LinkComponent>\n ) : undefined;\n\n return (\n <FooterContainer\n variant='compact'\n sticky={sticky}\n className={cn(className)}\n >\n <FooterCompact>\n <FooterCompactLeft>\n {version && <FooterVersion version={version} />}\n <FooterCopyright\n year={year}\n companyName={companyName}\n rightsText={rightsText}\n companyLink={companyLink}\n />\n {statusIndicator && StatusIndicatorComponent && (\n <StatusIndicatorComponent\n statusPageUrl={statusIndicator.statusPageUrl}\n apiEndpoint={statusIndicator.apiEndpoint}\n refreshInterval={statusIndicator.refreshInterval || 60000}\n size='sm'\n version={version}\n isNetworkOnline={isNetworkOnline}\n />\n )}\n </FooterCompactLeft>\n <FooterCompactRight>\n {links.map((link, index) => (\n <React.Fragment key={link.href || index}>\n {link.onClick ? (\n <button\n onClick={createTrackedLinkHandler(\n link.label,\n link.href,\n link.onClick\n )}\n className={cn(ui.text.linkMuted, ui.transition.default)}\n >\n {link.label}\n </button>\n ) : (\n <LinkComponent\n href={link.href}\n onClick={createTrackedLinkHandler(link.label, link.href)}\n className={cn(ui.text.linkMuted, ui.transition.default)}\n >\n {link.label}\n </LinkComponent>\n )}\n </React.Fragment>\n ))}\n </FooterCompactRight>\n </FooterCompact>\n </FooterContainer>\n );\n};\n\nexport default AppFooter;\n","import React, { useCallback, type ComponentType } from 'react';\nimport {\n Logo,\n Footer as FooterContainer,\n FooterGrid,\n FooterBrand,\n FooterLinkSection,\n FooterLink,\n FooterBottom,\n FooterVersion,\n FooterCopyright,\n FooterSocialLinks,\n} from '@sudobility/components';\nimport { ui } from '@sudobility/design';\nimport { cn } from '../../utils';\nimport type {\n StatusIndicatorConfig,\n LinkComponentProps,\n FooterLinkSection as FooterLinkSectionConfig,\n SocialLinksConfig,\n AnalyticsTrackingParams,\n} from '../../types';\nimport type { SystemStatusIndicatorProps } from './app-footer';\nimport { DefaultLinkComponent, getCopyrightYear } from './shared';\n\nexport interface AppFooterForHomePageProps {\n /** App logo configuration */\n logo: {\n /** Logo image src (optional - if not provided, uses Logo component) */\n src?: string;\n /** App name */\n appName: string;\n };\n\n /** Footer link sections (columns of links) */\n linkSections: FooterLinkSectionConfig[];\n\n /** Social media links */\n socialLinks?: SocialLinksConfig;\n\n /** System status indicator configuration */\n statusIndicator?: StatusIndicatorConfig;\n\n /**\n * SystemStatusIndicator component from @sudobility/devops-components.\n * Pass this to enable status indicator functionality.\n */\n StatusIndicatorComponent?: ComponentType<SystemStatusIndicatorProps>;\n\n /** App version string */\n version?: string;\n\n /** Copyright year or range */\n copyrightYear?: string;\n\n /** Company name for copyright */\n companyName: string;\n\n /** Company link URL (optional) */\n companyUrl?: string;\n\n /** Footer description text (below logo) */\n description?: string;\n\n /** Rights text (e.g., \"All rights reserved\") */\n rightsText?: string;\n\n /** Custom Link component */\n LinkComponent?: ComponentType<LinkComponentProps>;\n\n /** Network online status (for status indicator) */\n isNetworkOnline?: boolean;\n\n /** Custom className */\n className?: string;\n\n /** Number of columns for link grid (default: auto based on section count) */\n gridColumns?: 2 | 3 | 4 | 5;\n\n /** Optional analytics tracking callback */\n onTrack?: (params: AnalyticsTrackingParams) => void;\n}\n\n/**\n * Get grid columns class based on section count.\n */\nfunction getGridColumnsClass(sectionCount: number, explicit?: number): string {\n const cols = explicit || Math.min(sectionCount, 4);\n switch (cols) {\n case 2:\n return 'md:grid-cols-2';\n case 3:\n return 'md:grid-cols-3';\n case 4:\n return 'md:grid-cols-4';\n case 5:\n return 'md:grid-cols-5';\n default:\n return 'md:grid-cols-4';\n }\n}\n\n/**\n * AppFooterForHomePage - Full footer for home/landing pages.\n *\n * Features:\n * - Multiple link sections in a grid\n * - Logo and brand description\n * - Social media links\n * - System status indicator (optional)\n * - Version and copyright\n * - Dark mode support\n *\n * @example\n * ```tsx\n * import { SystemStatusIndicator } from '@sudobility/devops-components';\n *\n * <AppFooterForHomePage\n * logo={{ appName: 'My App' }}\n * linkSections={[\n * {\n * title: 'Product',\n * links: [\n * { label: 'Features', href: '/features' },\n * { label: 'Pricing', href: '/pricing' },\n * ],\n * },\n * {\n * title: 'Company',\n * links: [\n * { label: 'About', href: '/about' },\n * { label: 'Contact', href: '/contact' },\n * ],\n * },\n * ]}\n * socialLinks={{\n * twitterUrl: 'https://twitter.com/myapp',\n * discordUrl: 'https://discord.gg/myapp',\n * }}\n * statusIndicator={{\n * statusPageUrl: 'https://status.example.com',\n * }}\n * StatusIndicatorComponent={SystemStatusIndicator}\n * version=\"1.0.0\"\n * companyName=\"Sudobility Inc.\"\n * description=\"Building the future of web3 communication\"\n * />\n * ```\n */\nexport const AppFooterForHomePage: React.FC<AppFooterForHomePageProps> = ({\n logo,\n linkSections,\n socialLinks,\n statusIndicator,\n StatusIndicatorComponent,\n version,\n copyrightYear,\n companyName,\n companyUrl,\n description,\n rightsText = 'All rights reserved',\n LinkComponent = DefaultLinkComponent,\n isNetworkOnline = true,\n className,\n gridColumns,\n onTrack,\n}) => {\n const year = copyrightYear || getCopyrightYear();\n const gridClass = getGridColumnsClass(linkSections.length, gridColumns);\n\n // Helper to track analytics events\n const track = useCallback(\n (label: string, params?: Record<string, unknown>) => {\n onTrack?.({\n eventType: 'link_click',\n componentName: 'AppFooterForHomePage',\n label,\n params,\n });\n },\n [onTrack]\n );\n\n // Create a tracked link click handler\n const createTrackedLinkHandler = useCallback(\n (\n linkLabel: string,\n linkHref: string,\n sectionTitle: string,\n originalOnClick?: (e: React.MouseEvent) => void\n ) =>\n (e: React.MouseEvent) => {\n track('footer_link_clicked', {\n link_label: linkLabel,\n link_href: linkHref,\n section_title: sectionTitle,\n });\n originalOnClick?.(e);\n },\n [track]\n );\n\n const companyLink = companyUrl ? (\n <LinkComponent\n href={companyUrl}\n className={cn(ui.text.linkSubtle, ui.transition.default)}\n >\n {companyName}\n </LinkComponent>\n ) : undefined;\n\n return (\n <FooterContainer variant='full' className={cn(className)}>\n <FooterGrid className={gridClass}>\n {linkSections.map((section, sectionIndex) => (\n <FooterLinkSection\n key={section.title || sectionIndex}\n title={section.title}\n >\n {section.links.map((link, linkIndex) => (\n <FooterLink key={link.href || linkIndex}>\n {link.onClick ? (\n <button\n onClick={createTrackedLinkHandler(\n link.label,\n link.href,\n section.title,\n link.onClick\n )}\n className='text-left'\n >\n {link.label}\n </button>\n ) : (\n <LinkComponent\n href={link.href}\n onClick={createTrackedLinkHandler(\n link.label,\n link.href,\n section.title\n )}\n >\n {link.label}\n </LinkComponent>\n )}\n </FooterLink>\n ))}\n </FooterLinkSection>\n ))}\n </FooterGrid>\n\n <FooterBottom>\n <FooterBrand\n description={description}\n className='flex flex-col items-center'\n >\n <LinkComponent\n href='/'\n className='text-white hover:opacity-80 transition-opacity'\n >\n {logo.src ? (\n <img\n src={logo.src}\n alt={logo.appName}\n className='h-8 object-contain'\n />\n ) : (\n <Logo size='md' showText={true} logoText={logo.appName} />\n )}\n </LinkComponent>\n </FooterBrand>\n <div className='space-y-2'>\n {version && <FooterVersion version={version} className='block' />}\n <FooterCopyright\n year={year}\n companyName={companyName}\n rightsText={rightsText}\n companyLink={companyLink}\n className='block'\n />\n </div>\n {statusIndicator && StatusIndicatorComponent && (\n <StatusIndicatorComponent\n statusPageUrl={statusIndicator.statusPageUrl}\n apiEndpoint={statusIndicator.apiEndpoint}\n refreshInterval={statusIndicator.refreshInterval || 60000}\n size='sm'\n version={version}\n isNetworkOnline={isNetworkOnline}\n />\n )}\n </FooterBottom>\n\n {socialLinks && (\n <div className='flex justify-center mt-4'>\n <FooterSocialLinks\n twitterUrl={socialLinks.twitterUrl}\n discordUrl={socialLinks.discordUrl}\n linkedinUrl={socialLinks.linkedinUrl}\n githubUrl={socialLinks.githubUrl}\n redditUrl={socialLinks.redditUrl}\n farcasterUrl={socialLinks.farcasterUrl}\n telegramUrl={socialLinks.telegramUrl}\n />\n </div>\n )}\n </FooterContainer>\n );\n};\n\nexport default AppFooterForHomePage;\n","import React, { type ReactNode } from 'react';\nimport { LayoutProvider, AspectFitView } from '@sudobility/components';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils';\nimport { ui } from '@sudobility/design';\nimport {\n AppBreadcrumbs,\n type AppBreadcrumbsProps,\n} from '../breadcrumbs/app-breadcrumbs';\nimport { AppTopBar, type AppTopBarProps } from '../topbar/app-topbar';\nimport {\n AppTopBarWithFirebaseAuth,\n type AppTopBarWithFirebaseAuthProps,\n} from '../topbar/app-topbar-with-firebase-auth';\nimport {\n AppTopBarWithWallet,\n type AppTopBarWithWalletProps,\n} from '../topbar/app-topbar-with-wallet';\nimport { AppFooter, type AppFooterProps } from '../footer/app-footer';\nimport {\n AppFooterForHomePage,\n type AppFooterForHomePageProps,\n} from '../footer/app-footer-for-home-page';\nimport type { MaxWidth, ContentPadding, BackgroundVariant } from '../../types';\n\nconst layoutVariants = cva('flex flex-col', {\n variants: {\n background: {\n default: ui.background.subtle,\n white: 'bg-white dark:bg-gray-900',\n gradient:\n 'bg-gradient-to-br from-gray-50 to-blue-50 dark:from-gray-900 dark:to-gray-800',\n },\n },\n defaultVariants: {\n background: 'default',\n },\n});\n\nconst maxWidthClasses: Record<MaxWidth, string> = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n xl: 'max-w-xl',\n '2xl': 'max-w-2xl',\n '4xl': 'max-w-4xl',\n '7xl': 'max-w-7xl',\n full: 'max-w-full',\n};\n\nconst paddingClasses: Record<ContentPadding, string> = {\n none: '',\n sm: 'px-4 sm:px-6 py-6',\n md: 'px-4 py-8',\n lg: 'px-4 py-12',\n};\n\n/** Discriminated union for selecting which TopBar component to render. */\nexport type TopBarConfig =\n | ({ variant: 'base'; topBarVariant?: 'default' | 'app' } & Omit<\n AppTopBarProps,\n 'variant'\n >)\n | ({ variant: 'firebase'; topBarVariant?: 'default' | 'app' } & Omit<\n AppTopBarWithFirebaseAuthProps,\n 'variant'\n >)\n | ({ variant: 'wallet'; topBarVariant?: 'default' | 'app' } & Omit<\n AppTopBarWithWalletProps,\n 'variant'\n >);\n\n/** Discriminated union for selecting which Footer component to render. */\nexport type FooterConfig =\n | ({ variant: 'compact' } & AppFooterProps)\n | ({ variant: 'full' } & AppFooterForHomePageProps);\n\nfunction renderTopBar(config: TopBarConfig): ReactNode {\n const { variant, topBarVariant, ...rest } = config;\n switch (variant) {\n case 'base':\n return (\n <AppTopBar\n variant={topBarVariant}\n {...(rest as Omit<AppTopBarProps, 'variant'>)}\n />\n );\n case 'firebase':\n return (\n <AppTopBarWithFirebaseAuth\n variant={topBarVariant}\n {...(rest as Omit<AppTopBarWithFirebaseAuthProps, 'variant'>)}\n />\n );\n case 'wallet':\n return (\n <AppTopBarWithWallet\n variant={topBarVariant}\n {...(rest as Omit<AppTopBarWithWalletProps, 'variant'>)}\n />\n );\n }\n}\n\nfunction renderFooter(config: FooterConfig): ReactNode {\n const { variant, ...rest } = config;\n switch (variant) {\n case 'compact':\n return <AppFooter {...(rest as AppFooterProps)} />;\n case 'full':\n return <AppFooterForHomePage {...(rest as AppFooterForHomePageProps)} />;\n }\n}\n\n/** Page-level layout and styling options. */\nexport interface AppPageProps {\n /** Max width for content area (default: '7xl') */\n maxWidth?: MaxWidth;\n\n /** Content padding (default: 'md') */\n contentPadding?: ContentPadding;\n\n /** Background variant */\n background?: BackgroundVariant;\n\n /** Layout mode for LayoutProvider */\n layoutMode?: 'standard';\n\n /** Custom className for the layout container */\n className?: string;\n\n /** Custom className for the content area */\n contentClassName?: string;\n\n /** Custom className for the main element */\n mainClassName?: string;\n\n /** Whether the content area should be scrollable in sticky layout mode (default: true).\n * Set to false for pages with MasterDetailLayout where panels handle their own scrolling. */\n scrollable?: boolean;\n\n /** Optional aspect ratio (width / height) for content area. When set, children are placed inside a container with fixed aspect ratio using AspectFit behavior. */\n aspectRatio?: number;\n}\n\nexport interface AppPageLayoutProps {\n /** Page content */\n children: ReactNode;\n\n /** TopBar configuration - selects which TopBar component to render */\n topBar: TopBarConfig;\n\n /** Breadcrumbs configuration (optional) */\n breadcrumbs?: AppBreadcrumbsProps;\n\n /** Footer configuration - selects which Footer component to render */\n footer?: FooterConfig;\n\n /** Page-level layout and styling options */\n page?: AppPageProps;\n}\n\n/**\n * AppPageLayout - Layout wrapper combining TopBar, Breadcrumbs, Content, and Footer.\n *\n * Features:\n * - Props-based TopBar and Footer via discriminated unions\n * - Optional breadcrumbs with share and \"Talk to Founder\"\n * - Configurable content max-width and padding\n * - Background variants\n * - Dark mode support\n * - Compact footer sticks to the bottom while content scrolls independently\n * - Full footer scrolls with content (no sticky behavior)\n *\n * @example\n * ```tsx\n * <AppPageLayout\n * topBar={{\n * variant: 'firebase',\n * logo: { src: '/logo.png', appName: 'My App' },\n * menuItems: menuItems,\n * AuthActionComponent: AuthAction,\n * onLoginClick: () => navigate('/login'),\n * }}\n * breadcrumbs={{\n * items: breadcrumbItems,\n * shareConfig: { title: 'Page', description: 'Description', hashtags: [] },\n * }}\n * footer={{\n * variant: 'compact',\n * version: '1.0.0',\n * companyName: 'My Company',\n * links: [{ label: 'Privacy', href: '/privacy' }],\n * }}\n * page={{ maxWidth: '7xl', background: 'default' }}\n * >\n * <h1>Page Content</h1>\n * </AppPageLayout>\n * ```\n */\nexport const AppPageLayout: React.FC<AppPageLayoutProps> = ({\n children,\n topBar,\n breadcrumbs,\n footer,\n page,\n}) => {\n const {\n maxWidth = '7xl',\n contentPadding = 'md',\n background = 'default',\n layoutMode = 'standard',\n className,\n contentClassName,\n mainClassName,\n scrollable = true,\n aspectRatio,\n } = page ?? {};\n const isCompactFooter = footer?.variant === 'compact';\n // Compact footer: viewport-locked layout with internal scrolling\n // Full footer: natural page scrolling so footer scrolls with content\n const stickyLayout = !footer || isCompactFooter;\n const content = aspectRatio ? (\n <AspectFitView aspectRatio={aspectRatio}>{children}</AspectFitView>\n ) : (\n children\n );\n\n return (\n <LayoutProvider mode={layoutMode}>\n <div\n className={cn(\n layoutVariants({ background }),\n stickyLayout ? 'h-screen overflow-hidden' : 'min-h-screen',\n className\n )}\n >\n {/* Header Section */}\n <header>{renderTopBar(topBar)}</header>\n\n {/* Breadcrumb Section */}\n {breadcrumbs && breadcrumbs.items && breadcrumbs.items.length > 0 && (\n <AppBreadcrumbs {...breadcrumbs} />\n )}\n\n {/* Main Content */}\n <main\n className={cn(\n 'flex-1',\n stickyLayout && 'flex flex-col overflow-hidden',\n mainClassName\n )}\n >\n <div\n className={cn(\n 'mx-auto',\n maxWidthClasses[maxWidth],\n paddingClasses[contentPadding],\n stickyLayout &&\n (scrollable\n ? 'flex-1 min-h-0 overflow-auto'\n : 'flex-1 min-h-0 overflow-hidden flex flex-col'),\n contentClassName\n )}\n >\n {content}\n </div>\n </main>\n\n {/* Footer */}\n {footer && (\n <footer\n className={isCompactFooter ? 'sticky bottom-0 z-10' : undefined}\n >\n {renderFooter(footer)}\n </footer>\n )}\n </div>\n </LayoutProvider>\n );\n};\n\nexport default AppPageLayout;\n","import React from 'react';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Label,\n} from '@sudobility/components';\nimport { textVariants, colors, ui } from '@sudobility/design';\n\n/**\n * Theme options for appearance settings.\n */\nexport enum Theme {\n LIGHT = 'light',\n DARK = 'dark',\n SYSTEM = 'system',\n}\n\n/**\n * Font size options for appearance settings.\n */\nexport enum FontSize {\n SMALL = 'small',\n MEDIUM = 'medium',\n LARGE = 'large',\n}\n\n/**\n * Translation keys used by AppearanceSettings.\n * Provide a translation function to customize labels.\n */\nexport interface AppearanceSettingsTranslations {\n heading: string;\n description: string;\n themeLabel: string;\n themeSelectPlaceholder: string;\n themeLight: string;\n themeDark: string;\n themeSystem: string;\n themeDescription: string;\n fontSizeLabel: string;\n fontSizeSelectPlaceholder: string;\n fontSizeSmall: string;\n fontSizeMedium: string;\n fontSizeLarge: string;\n fontSizeDescription: string;\n infoHeading: string;\n infoDescription: string;\n}\n\nconst defaultTranslations: AppearanceSettingsTranslations = {\n heading: 'Appearance',\n description: 'Customize the look and feel of the application.',\n themeLabel: 'Theme',\n themeSelectPlaceholder: 'Select theme',\n themeLight: 'Light',\n themeDark: 'Dark',\n themeSystem: 'System',\n themeDescription: 'Choose your preferred color theme.',\n fontSizeLabel: 'Font Size',\n fontSizeSelectPlaceholder: 'Select font size',\n fontSizeSmall: 'Small',\n fontSizeMedium: 'Medium',\n fontSizeLarge: 'Large',\n fontSizeDescription: 'Adjust the text size for better readability.',\n infoHeading: 'About Settings',\n infoDescription:\n 'Your appearance preferences are saved locally and will be applied automatically on your next visit.',\n};\n\nexport interface AppearanceSettingsProps {\n /** Current theme value */\n theme: Theme | string;\n\n /** Current font size value */\n fontSize: FontSize | string;\n\n /** Callback when theme changes */\n onThemeChange: (theme: Theme) => void;\n\n /** Callback when font size changes */\n onFontSizeChange: (fontSize: FontSize) => void;\n\n /**\n * Optional translation function.\n * If provided, will be called with a key from AppearanceSettingsTranslations.\n * Falls back to default English strings if not provided.\n */\n t?: (key: string, fallback?: string) => string;\n\n /** Optional className for the container */\n className?: string;\n\n /** Whether to show the information box at the bottom */\n showInfoBox?: boolean;\n}\n\n/**\n * AppearanceSettings - A reusable component for theme and font size settings.\n *\n * This component can be used across different apps to provide consistent\n * appearance customization options.\n *\n * @example\n * ```tsx\n * // Basic usage with useTheme hook\n * const { theme, fontSize, setTheme, setFontSize } = useTheme();\n *\n * <AppearanceSettings\n * theme={theme}\n * fontSize={fontSize}\n * onThemeChange={setTheme}\n * onFontSizeChange={setFontSize}\n * />\n *\n * // With i18n translation\n * const { t } = useTranslation('settings');\n *\n * <AppearanceSettings\n * theme={theme}\n * fontSize={fontSize}\n * onThemeChange={setTheme}\n * onFontSizeChange={setFontSize}\n * t={(key, fallback) => t(`appearance.${key}`, fallback)}\n * />\n * ```\n */\nexport const AppearanceSettings: React.FC<AppearanceSettingsProps> = ({\n theme,\n fontSize,\n onThemeChange,\n onFontSizeChange,\n t,\n className,\n showInfoBox = true,\n}) => {\n // Helper to get translated string with fallback\n const getText = (key: keyof AppearanceSettingsTranslations): string => {\n const fallback = defaultTranslations[key];\n return t ? t(key, fallback) : fallback;\n };\n\n return (\n <div className={className}>\n <div className='space-y-6'>\n <div>\n <h2 className={`${textVariants.heading.h4()} mb-2`}>\n {getText('heading')}\n </h2>\n <p className={textVariants.body.sm()}>{getText('description')}</p>\n </div>\n\n <div className='space-y-6'>\n {/* Theme Setting */}\n <div className='space-y-2'>\n <Label\n htmlFor='theme-select'\n className={textVariants.label.default()}\n >\n {getText('themeLabel')}\n </Label>\n <Select\n value={theme}\n onValueChange={(value: string) => onThemeChange(value as Theme)}\n >\n <SelectTrigger id='theme-select'>\n <SelectValue placeholder={getText('themeSelectPlaceholder')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={Theme.LIGHT}>\n {getText('themeLight')}\n </SelectItem>\n <SelectItem value={Theme.DARK}>\n {getText('themeDark')}\n </SelectItem>\n <SelectItem value={Theme.SYSTEM}>\n {getText('themeSystem')}\n </SelectItem>\n </SelectContent>\n </Select>\n <p className={textVariants.body.xs()}>\n {getText('themeDescription')}\n </p>\n </div>\n\n {/* Font Size Setting */}\n <div className='space-y-2'>\n <Label\n htmlFor='font-size-select'\n className={textVariants.label.default()}\n >\n {getText('fontSizeLabel')}\n </Label>\n <Select\n value={fontSize}\n onValueChange={(value: string) =>\n onFontSizeChange(value as FontSize)\n }\n >\n <SelectTrigger id='font-size-select'>\n <SelectValue\n placeholder={getText('fontSizeSelectPlaceholder')}\n />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={FontSize.SMALL}>\n {getText('fontSizeSmall')}\n </SelectItem>\n <SelectItem value={FontSize.MEDIUM}>\n {getText('fontSizeMedium')}\n </SelectItem>\n <SelectItem value={FontSize.LARGE}>\n {getText('fontSizeLarge')}\n </SelectItem>\n </SelectContent>\n </Select>\n <p className={textVariants.body.xs()}>\n {getText('fontSizeDescription')}\n </p>\n </div>\n </div>\n\n {/* Information Box */}\n {showInfoBox && (\n <div\n className={`${colors.component.alert.info.base} ${colors.component.alert.info.dark} rounded-lg p-4 border`}\n >\n <h4 className={`${ui.text.info} text-sm mb-2`}>\n {getText('infoHeading')}\n </h4>\n <p className={`${ui.text.info} text-sm font-normal`}>\n {getText('infoDescription')}\n </p>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default AppearanceSettings;\n","/**\n * @fileoverview Global Settings Page\n * @description Reusable settings page with sidebar navigation.\n *\n * The consuming page is responsible for page-level layout (width constraints,\n * padding, scrollable behavior) — e.g. via useSetPageConfig or a Section wrapper.\n */\n\nimport React, {\n useState,\n useMemo,\n useCallback,\n type ReactNode,\n type ComponentType,\n} from 'react';\nimport { PaintBrushIcon } from '@heroicons/react/24/outline';\nimport { MasterDetailLayout, MasterListItem } from '@sudobility/components';\nimport { AppearanceSettings } from './appearance-settings';\nimport { Theme, FontSize } from './appearance-settings';\nimport type { AnalyticsTrackingParams } from '../../types';\n\n/**\n * Configuration for a settings section in the navigation.\n */\nexport interface SettingsSectionConfig {\n /** Unique identifier for the section */\n id: string;\n /** Icon component to display */\n icon: ComponentType<{ className?: string }>;\n /** Display label */\n label: string;\n /** Short description shown below label */\n description: string;\n /** The content to render when this section is selected */\n content: ReactNode;\n}\n\n/**\n * Translation keys used by GlobalSettingsPage.\n */\nexport interface GlobalSettingsPageTranslations {\n title: string;\n backButton: string;\n appearanceLabel: string;\n appearanceDescription: string;\n}\n\nconst defaultTranslations: GlobalSettingsPageTranslations = {\n title: 'Settings',\n backButton: 'Back',\n appearanceLabel: 'Appearance',\n appearanceDescription: 'Theme and font size settings',\n};\n\nexport interface GlobalSettingsPageProps {\n /** Current theme value */\n theme: Theme | string;\n\n /** Current font size value */\n fontSize: FontSize | string;\n\n /** Callback when theme changes */\n onThemeChange: (theme: Theme) => void;\n\n /** Callback when font size changes */\n onFontSizeChange: (fontSize: FontSize) => void;\n\n /**\n * Additional settings sections to display after Appearance.\n * Each section needs an id, icon, label, description, and content.\n */\n additionalSections?: SettingsSectionConfig[];\n\n /**\n * Optional translation function.\n * Falls back to default English strings if not provided.\n */\n t?: (key: string, fallback?: string) => string;\n\n /**\n * Translation function for AppearanceSettings.\n * If provided, will be passed to AppearanceSettings component.\n */\n appearanceT?: (key: string, fallback?: string) => string;\n\n /** Optional className for the container */\n className?: string;\n\n /** Whether to show the info box in appearance settings */\n showAppearanceInfoBox?: boolean;\n\n /** Optional analytics tracking callback */\n onTrack?: (params: AnalyticsTrackingParams) => void;\n}\n\n/**\n * GlobalSettingsPage - A reusable settings page with master-detail layout.\n *\n * Features:\n * - Appearance settings built-in as the first section\n * - Extensible via additionalSections prop\n * - Responsive master-detail layout\n * - Mobile-friendly with back navigation\n *\n * @example\n * ```tsx\n * // Basic usage\n * <GlobalSettingsPage\n * theme={theme}\n * fontSize={fontSize}\n * onThemeChange={setTheme}\n * onFontSizeChange={setFontSize}\n * />\n *\n * // With additional sections\n * <GlobalSettingsPage\n * theme={theme}\n * fontSize={fontSize}\n * onThemeChange={setTheme}\n * onFontSizeChange={setFontSize}\n * additionalSections={[\n * {\n * id: 'notifications',\n * icon: BellIcon,\n * label: 'Notifications',\n * description: 'Manage notification preferences',\n * content: <NotificationSettings />,\n * },\n * ]}\n * />\n * ```\n */\nexport const GlobalSettingsPage: React.FC<GlobalSettingsPageProps> = ({\n theme,\n fontSize,\n onThemeChange,\n onFontSizeChange,\n additionalSections = [],\n t,\n appearanceT,\n showAppearanceInfoBox = true,\n onTrack,\n}) => {\n // Development-only warnings for common misconfigurations\n if (process.env.NODE_ENV !== 'production') {\n const ids = additionalSections.map(s => s.id);\n const duplicateIds = ids.filter((id, i) => ids.indexOf(id) !== i);\n if (duplicateIds.length > 0) {\n console.warn(\n `[GlobalSettingsPage] Duplicate section IDs found: ${duplicateIds.join(', ')}. ` +\n 'Each section must have a unique id.'\n );\n }\n if (ids.includes('appearance')) {\n console.warn(\n '[GlobalSettingsPage] additionalSections contains a section with id \"appearance\" which conflicts with the built-in Appearance section. ' +\n 'Use a different id to avoid unexpected behavior.'\n );\n }\n }\n const [selectedSection, setSelectedSection] = useState('appearance');\n const [mobileView, setMobileView] = useState<'navigation' | 'content'>(\n 'navigation'\n );\n\n // Helper to track analytics events\n const track = useCallback(\n (label: string, params?: Record<string, unknown>) => {\n onTrack?.({\n eventType: 'settings_change',\n componentName: 'GlobalSettingsPage',\n label,\n params,\n });\n },\n [onTrack]\n );\n\n // Wrapped handlers with tracking\n const handleThemeChange = useCallback(\n (newTheme: Theme) => {\n track('theme_changed', { theme: newTheme });\n onThemeChange(newTheme);\n },\n [track, onThemeChange]\n );\n\n const handleFontSizeChange = useCallback(\n (newFontSize: FontSize) => {\n track('font_size_changed', { font_size: newFontSize });\n onFontSizeChange(newFontSize);\n },\n [track, onFontSizeChange]\n );\n\n // Helper to get translated string with fallback\n const getText = useCallback(\n (key: keyof GlobalSettingsPageTranslations): string => {\n const fallback = defaultTranslations[key];\n return t ? t(key, fallback) : fallback;\n },\n [t]\n );\n\n // Build all sections with appearance first\n const allSections: SettingsSectionConfig[] = useMemo(\n () => [\n {\n id: 'appearance',\n icon: PaintBrushIcon,\n label: getText('appearanceLabel'),\n description: getText('appearanceDescription'),\n content: (\n <AppearanceSettings\n theme={theme}\n fontSize={fontSize}\n onThemeChange={handleThemeChange}\n onFontSizeChange={handleFontSizeChange}\n t={appearanceT}\n showInfoBox={showAppearanceInfoBox}\n />\n ),\n },\n ...additionalSections,\n ],\n [\n additionalSections,\n getText,\n theme,\n fontSize,\n handleThemeChange,\n handleFontSizeChange,\n appearanceT,\n showAppearanceInfoBox,\n ]\n );\n\n const currentSection =\n allSections.find(s => s.id === selectedSection) || allSections[0];\n\n const handleSectionSelect = (sectionId: string) => {\n track('section_selected', { section_id: sectionId });\n setSelectedSection(sectionId);\n setMobileView('content');\n };\n\n const handleBackToNavigation = () => {\n track('back_to_navigation');\n setMobileView('navigation');\n };\n\n // Navigation list using MasterListItem\n const navigationList = (\n <div>\n {allSections.map(section => (\n <MasterListItem\n key={section.id}\n isSelected={selectedSection === section.id}\n onClick={() => handleSectionSelect(section.id)}\n icon={section.icon}\n label={section.label}\n description={section.description}\n />\n ))}\n </div>\n );\n\n return (\n <MasterDetailLayout\n masterTitle={getText('title')}\n backButtonText={getText('backButton')}\n masterContent={navigationList}\n detailContent={currentSection.content}\n detailTitle={currentSection.label}\n mobileView={mobileView}\n onBackToNavigation={handleBackToNavigation}\n masterWidth={280}\n stickyMaster={true}\n enableAnimations={true}\n />\n );\n};\n\nexport default GlobalSettingsPage;\n","/**\n * @fileoverview App Sitemap Page\n * @description Reusable sitemap page component with categorized links.\n *\n * This component uses Section internally for proper page layout.\n * Do NOT wrap this component in a Section when consuming it.\n */\n\nimport React, { type ComponentType, type ReactNode } from 'react';\nimport {\n ChevronRightIcon,\n HomeIcon,\n DocumentTextIcon,\n EnvelopeIcon,\n CogIcon,\n LanguageIcon,\n} from '@heroicons/react/24/outline';\nimport { Section } from '@sudobility/components';\nimport { cn } from '../../utils';\nimport { ui, colors, buttonVariant } from '@sudobility/design';\nimport type { LinkComponentProps } from '../../types';\n\n/**\n * Configuration for a single sitemap link\n */\nexport interface SitemapLink {\n /** URL path */\n path: string;\n /** Display label */\n label: string;\n /** Optional description */\n description?: string;\n}\n\n/**\n * Configuration for a sitemap section\n */\nexport interface SitemapSection {\n /** Section title */\n title: string;\n /** Section icon type (optional) */\n icon?: 'home' | 'document' | 'envelope' | 'cog' | 'language';\n /** Links in this section */\n links: SitemapLink[];\n}\n\n/**\n * Configuration for a language option\n */\nexport interface LanguageOption {\n /** Language code (e.g., 'en', 'es') */\n code: string;\n /** Display name */\n name: string;\n /** Flag emoji */\n flag: string;\n}\n\n/**\n * Configuration for quick action buttons\n */\nexport interface QuickLink {\n /** URL path */\n path: string;\n /** Display label */\n label: string;\n /** Button variant */\n variant: 'primary' | 'secondary' | 'outline';\n /** Optional icon */\n icon?: 'envelope' | 'document';\n}\n\n/**\n * Text content for the sitemap page\n */\nexport interface SitemapPageText {\n /** Page title */\n title: string;\n /** Page subtitle */\n subtitle: string;\n /** Languages section title */\n languagesSectionTitle: string;\n /** Languages section description */\n languagesDescription: string;\n /** Quick links section title */\n quickLinksTitle: string;\n}\n\n/**\n * Props for AppSitemapPage component\n */\nexport interface AppSitemapPageProps {\n /** All text content (must be provided by consumer) */\n text: SitemapPageText;\n /** Sitemap sections */\n sections: SitemapSection[];\n /** Available languages */\n languages: LanguageOption[];\n /** Quick action links */\n quickLinks?: QuickLink[];\n /** Custom Link component for navigation */\n LinkComponent: ComponentType<LinkComponentProps & { language?: string }>;\n /** Optional wrapper component for the page layout */\n PageWrapper?: ComponentType<{ children: ReactNode }>;\n /** Path to use for language switcher links (defaults to current page path via window.location) */\n languageLinkPath?: string;\n /** Optional className for the container */\n className?: string;\n}\n\n/**\n * Get icon component based on icon type\n */\nconst getIcon = (icon?: string) => {\n switch (icon) {\n case 'home':\n return <HomeIcon className='w-5 h-5 mr-2' />;\n case 'document':\n return <DocumentTextIcon className='w-5 h-5 mr-2' />;\n case 'envelope':\n return <EnvelopeIcon className='w-5 h-5 mr-2' />;\n case 'cog':\n return <CogIcon className='w-5 h-5 mr-2' />;\n case 'language':\n return <LanguageIcon className='w-5 h-5 mr-2' />;\n default:\n return null;\n }\n};\n\n/**\n * AppSitemapPage - A reusable sitemap page component\n *\n * Displays a comprehensive sitemap with:\n * - Language selector\n * - Organized sections with links\n * - Quick action buttons\n *\n * All text content must be provided by the consumer app.\n *\n * @example\n * ```tsx\n * <AppSitemapPage\n * text={{\n * title: \"Sitemap\",\n * subtitle: \"Explore all pages\",\n * languagesSectionTitle: \"Languages\",\n * languagesDescription: \"Available in multiple languages\",\n * quickLinksTitle: \"Quick Links\"\n * }}\n * sections={[\n * { title: \"Main\", icon: \"home\", links: [{ path: \"/\", label: \"Home\" }] }\n * ]}\n * languages={[{ code: \"en\", name: \"English\", flag: \"🇺🇸\" }]}\n * LinkComponent={LocalizedLink}\n * />\n * ```\n */\nexport const AppSitemapPage: React.FC<AppSitemapPageProps> = ({\n text,\n sections,\n languages,\n quickLinks = [],\n LinkComponent,\n PageWrapper,\n languageLinkPath,\n className,\n}) => {\n const content = (\n <Section spacing='3xl' maxWidth='6xl' className={cn(className)}>\n {/* Header */}\n <div className='text-center mb-12'>\n <h1 className={`text-4xl font-bold ${ui.text.strong} mb-4`}>\n {text.title}\n </h1>\n <p className={`text-xl ${ui.text.muted}`}>{text.subtitle}</p>\n </div>\n\n {/* Language Section */}\n {languages.length > 0 && (\n <div\n className={`mb-12 p-6 ${colors.component.alert.info.base} ${colors.component.alert.info.dark} rounded-lg`}\n >\n <h2\n className={`text-xl font-semibold ${ui.text.strong} mb-4 flex items-center`}\n >\n <LanguageIcon className='w-6 h-6 mr-2' />\n {text.languagesSectionTitle}\n </h2>\n <p className={`${ui.text.body} mb-6`}>{text.languagesDescription}</p>\n <div className='grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4'>\n {languages.map(lang => (\n <LinkComponent\n key={lang.code}\n href={languageLinkPath ?? '/'}\n language={lang.code}\n className={`flex items-center space-x-2 p-3 ${ui.background.surface} rounded-lg hover:shadow-md transition-shadow`}\n >\n <span className='text-2xl'>{lang.flag}</span>\n <div className={`font-medium ${ui.text.strong}`}>\n {lang.name}\n </div>\n </LinkComponent>\n ))}\n </div>\n </div>\n )}\n\n {/* Sitemap Grid */}\n <div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8'>\n {sections.map((section, index) => (\n <div\n key={index}\n className={`${ui.background.surface} rounded-lg shadow-sm p-6`}\n >\n <h2\n className={`text-lg font-semibold ${ui.text.strong} mb-4 flex items-center`}\n >\n {getIcon(section.icon)}\n {section.title}\n </h2>\n <ul className='space-y-2'>\n {section.links.map((link, linkIndex) => (\n <li key={linkIndex}>\n <LinkComponent\n href={link.path}\n className={`group flex items-start text-sm ${ui.text.linkSubtle} transition-colors`}\n >\n <ChevronRightIcon\n className={`w-4 h-4 mt-0.5 mr-2 flex-shrink-0 ${ui.text.muted} group-hover:text-blue-600 dark:group-hover:text-blue-400`}\n />\n <div>\n <span\n className={`font-medium ${ui.text.label} group-hover:text-blue-600 dark:group-hover:text-blue-400`}\n >\n {link.label}\n </span>\n {link.description && (\n <span\n className={`block text-xs ${ui.text.muted} mt-0.5`}\n >\n {link.description}\n </span>\n )}\n </div>\n </LinkComponent>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n\n {/* Quick Links Section */}\n {quickLinks.length > 0 && (\n <div className={`mt-12 p-6 ${ui.background.subtle} rounded-lg`}>\n <h3 className={`text-lg font-semibold ${ui.text.strong} mb-4`}>\n {text.quickLinksTitle}\n </h3>\n <div className='flex flex-wrap gap-3'>\n {quickLinks.map((link, index) => {\n const baseClasses =\n 'inline-flex items-center px-4 py-2 rounded-lg';\n const variantClasses = buttonVariant(\n link.variant === 'primary'\n ? 'primary'\n : link.variant === 'secondary'\n ? 'secondary'\n : 'outline'\n );\n\n return (\n <LinkComponent\n key={index}\n href={link.path}\n className={cn(baseClasses, variantClasses)}\n >\n {link.icon === 'envelope' && (\n <EnvelopeIcon className='w-5 h-5 mr-2' />\n )}\n {link.icon === 'document' && (\n <DocumentTextIcon className='w-5 h-5 mr-2' />\n )}\n {link.label}\n </LinkComponent>\n );\n })}\n </div>\n </div>\n )}\n </Section>\n );\n\n if (PageWrapper) {\n return <PageWrapper>{content}</PageWrapper>;\n }\n\n return content;\n};\n\nexport default AppSitemapPage;\n","/**\n * @fileoverview App Text Page\n * @description Reusable page component for text-heavy content like Privacy Policy, Terms, etc.\n *\n * This component uses Section internally for proper page layout.\n * Do NOT wrap this component in a Section when consuming it.\n */\n\nimport React, { type ReactNode, type ComponentType } from 'react';\nimport { Section } from '@sudobility/components';\nimport { cn } from '../../utils';\nimport { ui, colors } from '@sudobility/design';\n\n/**\n * Configuration for a text section with paragraph content\n */\nexport interface TextSectionWithContent {\n /** Section title */\n title: string;\n /** Paragraph content */\n content: string;\n /** Whether content contains HTML that should be rendered */\n isHtml?: boolean;\n}\n\n/**\n * Configuration for a text section with a list\n */\nexport interface TextSectionWithList {\n /** Section title */\n title: string;\n /** Optional description before the list */\n description?: string;\n /** List items */\n items: string[];\n /** Optional additional content after the list */\n additionalContent?: string;\n}\n\n/**\n * Configuration for a text section with subsections (e.g., \"Information You Provide\" and \"Information Collected Automatically\")\n */\nexport interface TextSectionWithSubsections {\n /** Section title */\n title: string;\n /** Subsections, each with a title and list items */\n subsections: Array<{\n title: string;\n items: string[];\n }>;\n}\n\n/**\n * Union type for all section types\n */\nexport type TextSection =\n | TextSectionWithContent\n | TextSectionWithList\n | TextSectionWithSubsections;\n\n/**\n * Contact information configuration\n */\nexport interface TextPageContactInfo {\n /** Email label (e.g., \"Email:\") */\n emailLabel: string;\n /** Email address */\n email: string;\n /** Website label (e.g., \"Website:\") */\n websiteLabel: string;\n /** Website URL */\n websiteUrl: string;\n /** Data Protection Officer label (optional, for privacy pages) */\n dpoLabel?: string;\n /** DPO email (optional, for privacy pages) */\n dpoEmail?: string;\n}\n\n/**\n * GDPR notice configuration (optional, for privacy pages)\n */\nexport interface GdprNotice {\n /** GDPR section title */\n title: string;\n /** GDPR section content */\n content: string;\n}\n\n/**\n * Contact section configuration\n */\nexport interface TextPageContact {\n /** Section title */\n title: string;\n /** Section description */\n description: string;\n /** Whether description contains HTML */\n isHtml?: boolean;\n /** Contact details */\n info: TextPageContactInfo;\n /** Optional GDPR notice (for privacy pages) */\n gdprNotice?: GdprNotice;\n}\n\n/**\n * All text content for the text page\n */\nexport interface TextPageContent {\n /** Page title */\n title: string;\n /** Last updated text (use {{date}} as placeholder for the date) */\n lastUpdated?: string;\n /** All sections in order */\n sections: TextSection[];\n /** Contact information (optional) */\n contact?: TextPageContact;\n}\n\n/**\n * Props for AppTextPage component\n */\nexport interface AppTextPageProps {\n /** All text content (must be provided by consumer) */\n text: TextPageContent;\n /** Current date for \"last updated\" display */\n lastUpdatedDate?: string;\n /** Optional wrapper component for the page layout */\n PageWrapper?: ComponentType<{ children: ReactNode }>;\n /** Optional className for the container */\n className?: string;\n}\n\n/**\n * Type guard to check if section has items (is a list section)\n */\nfunction isSectionWithList(\n section: TextSection\n): section is TextSectionWithList {\n return 'items' in section && Array.isArray(section.items);\n}\n\n/**\n * Type guard to check if section has subsections\n */\nfunction isSectionWithSubsections(\n section: TextSection\n): section is TextSectionWithSubsections {\n return 'subsections' in section && Array.isArray(section.subsections);\n}\n\n/**\n * Heading component for h2 sections\n */\nconst SectionHeading: React.FC<{ children: ReactNode }> = ({ children }) => (\n <h2 className={`text-2xl font-bold ${ui.text.strong} mt-8 mb-4`}>\n {children}\n </h2>\n);\n\n/**\n * Heading component for h3 subsections\n */\nconst SubsectionHeading: React.FC<{ children: ReactNode }> = ({ children }) => (\n <h3 className={`text-xl font-semibold ${ui.text.strong} mt-6 mb-3`}>\n {children}\n </h3>\n);\n\n/**\n * Paragraph component\n */\nconst Paragraph: React.FC<{ children: ReactNode; className?: string }> = ({\n children,\n className = '',\n}) => <p className={cn(ui.text.body, 'mb-6', className)}>{children}</p>;\n\n/**\n * List component - renders items with HTML support\n */\nconst List: React.FC<{ items: string[] }> = ({ items }) => (\n <ul className={`list-disc list-inside ${ui.text.body} mb-6 space-y-1`}>\n {items.map((item, index) => (\n <li key={index} dangerouslySetInnerHTML={{ __html: item }} />\n ))}\n </ul>\n);\n\n/**\n * AppTextPage - A reusable text page component for legal/informational pages\n *\n * Displays a text-heavy page with:\n * - Flexible section structure (content, list, or subsections)\n * - Optional contact information\n * - Optional GDPR notice\n *\n * Use this for Privacy Policy, Terms of Service, Cookie Policy, etc.\n *\n * @example\n * ```tsx\n * <AppTextPage\n * text={{\n * title: \"Privacy Policy\",\n * lastUpdated: \"Last updated: {{date}}\",\n * sections: [\n * { title: \"Introduction\", content: \"We respect your privacy...\" },\n * { title: \"Data We Collect\", items: [\"Email\", \"Usage data\"] },\n * {\n * title: \"Information We Collect\",\n * subsections: [\n * { title: \"You Provide\", items: [\"Email\", \"Name\"] },\n * { title: \"Automatic\", items: [\"IP\", \"Browser\"] }\n * ]\n * }\n * ],\n * contact: {\n * title: \"Contact\",\n * description: \"Questions?\",\n * info: { emailLabel: \"Email:\", email: \"support@example.com\", ... }\n * }\n * }}\n * lastUpdatedDate=\"January 1, 2025\"\n * />\n * ```\n */\nexport const AppTextPage: React.FC<AppTextPageProps> = ({\n text,\n lastUpdatedDate = new Date().toLocaleDateString(),\n PageWrapper,\n className,\n}) => {\n const content = (\n <Section spacing='3xl' maxWidth='4xl' className={cn(className)}>\n <h1 className={`text-4xl font-bold ${ui.text.strong} mb-8`}>\n {text.title}\n </h1>\n\n <div className='prose prose-lg dark:prose-invert max-w-none'>\n {text.lastUpdated && (\n <Paragraph className='mb-6'>\n {text.lastUpdated.replace('{{date}}', lastUpdatedDate)}\n </Paragraph>\n )}\n\n {/* Render all sections */}\n {text.sections.map((section, index) => (\n <React.Fragment key={index}>\n <SectionHeading>{section.title}</SectionHeading>\n\n {isSectionWithSubsections(section) ? (\n // Section with subsections (h3 + lists)\n <>\n {section.subsections.map((subsection, subIndex) => (\n <React.Fragment key={subIndex}>\n <SubsectionHeading>{subsection.title}</SubsectionHeading>\n <List items={subsection.items} />\n </React.Fragment>\n ))}\n </>\n ) : isSectionWithList(section) ? (\n // Section with list\n <>\n {section.description && (\n <Paragraph className='mb-4'>{section.description}</Paragraph>\n )}\n <List items={section.items} />\n {section.additionalContent && (\n <Paragraph>{section.additionalContent}</Paragraph>\n )}\n </>\n ) : section.isHtml ? (\n // Section with HTML content\n <Paragraph>\n <span dangerouslySetInnerHTML={{ __html: section.content }} />\n </Paragraph>\n ) : (\n // Section with plain text content\n <Paragraph>{section.content}</Paragraph>\n )}\n </React.Fragment>\n ))}\n\n {/* Contact Section */}\n {text.contact && (\n <>\n <SectionHeading>{text.contact.title}</SectionHeading>\n {text.contact.isHtml ? (\n <Paragraph>\n <span\n dangerouslySetInnerHTML={{ __html: text.contact.description }}\n />\n </Paragraph>\n ) : (\n <Paragraph>{text.contact.description}</Paragraph>\n )}\n <div className={`${ui.background.subtle} p-4 rounded-lg`}>\n <p className={ui.text.body}>\n {text.contact.info.emailLabel}{' '}\n <a\n href={`mailto:${text.contact.info.email}`}\n className={ui.text.link}\n >\n {text.contact.info.email}\n </a>\n <br />\n {text.contact.info.websiteLabel}{' '}\n <a href={text.contact.info.websiteUrl} className={ui.text.link}>\n {text.contact.info.websiteUrl}\n </a>\n {text.contact.info.dpoLabel && text.contact.info.dpoEmail && (\n <>\n <br />\n {text.contact.info.dpoLabel}{' '}\n <a\n href={`mailto:${text.contact.info.dpoEmail}`}\n className={ui.text.link}\n >\n {text.contact.info.dpoEmail}\n </a>\n </>\n )}\n </p>\n </div>\n\n {/* GDPR Notice */}\n {text.contact.gdprNotice && (\n <div\n className={`mt-8 p-4 ${colors.component.alert.info.base} ${colors.component.alert.info.dark} rounded-lg`}\n >\n <h3 className={`text-lg font-semibold ${ui.text.info} mb-2`}>\n {text.contact.gdprNotice.title}\n </h3>\n <p className={ui.text.info}>\n {text.contact.gdprNotice.content}{' '}\n {text.contact.info.dpoEmail && (\n <a\n href={`mailto:${text.contact.info.dpoEmail}`}\n className={ui.text.link}\n >\n {text.contact.info.dpoEmail}\n </a>\n )}\n </p>\n </div>\n )}\n </>\n )}\n </div>\n </Section>\n );\n\n if (PageWrapper) {\n return <PageWrapper>{content}</PageWrapper>;\n }\n\n return content;\n};\n\nexport default AppTextPage;\n","import React, { useState, useEffect, useRef, type ReactNode } from 'react';\nimport { cn } from '../../utils';\nimport {\n buttonVariant,\n focusRing,\n colors as designColors,\n ui,\n} from '@sudobility/design';\n\n/**\n * Google logo SVG component\n */\nfunction GoogleIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox='0 0 24 24' aria-hidden='true'>\n <path\n d='M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z'\n fill='#4285F4'\n />\n <path\n d='M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z'\n fill='#34A853'\n />\n <path\n d='M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z'\n fill='#FBBC05'\n />\n <path\n d='M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z'\n fill='#EA4335'\n />\n </svg>\n );\n}\n\n/**\n * Auth error info passed to onAuthError callback\n */\nexport interface AuthErrorInfo {\n /** Firebase error code (e.g., 'auth/popup-closed-by-user') */\n code: string;\n /** Error message */\n message: string;\n /** Whether this is a user-initiated action (like closing popup) vs actual error */\n isUserAction: boolean;\n}\n\n/**\n * Color variant for the LoginPage.\n * Each variant maps to a set of static, JIT-safe Tailwind classes.\n */\nexport type LoginPageColorVariant =\n | 'primary'\n | 'blue'\n | 'indigo'\n | 'violet'\n | 'orange'\n | 'emerald'\n | 'rose';\n\n/**\n * Props for the LoginPage component\n *\n * LoginPage is a presentational component that accepts auth handler callbacks.\n * The consumer must provide the actual auth logic (e.g., Firebase signIn).\n */\nexport interface LoginPageProps {\n /** Application name displayed as the main title */\n appName: string;\n /** Optional logo element to display above the title */\n logo?: ReactNode;\n /**\n * Handler for email/password sign-in.\n * Called with email and password; should throw on error.\n * The error object should have `code` and `message` properties for proper error display.\n */\n onEmailSignIn: (email: string, password: string) => Promise<void>;\n /**\n * Handler for email/password sign-up (account creation).\n * Called with email and password; should throw on error.\n * Only used when `showSignUp` is true.\n */\n onEmailSignUp?: (email: string, password: string) => Promise<void>;\n /**\n * Handler for Google sign-in.\n * Should perform the Google OAuth flow; should throw on error.\n * Only used when `showGoogleSignIn` is true.\n */\n onGoogleSignIn?: () => Promise<void>;\n /** Callback fired on successful authentication */\n onSuccess: () => void;\n /** Callback fired on auth errors - if provided, errors won't be shown inline */\n onAuthError?: (error: AuthErrorInfo) => void;\n /** Whether to show Google sign-in option (default: true) */\n showGoogleSignIn?: boolean;\n /** Whether to show sign-up option (default: true) */\n showSignUp?: boolean;\n /** Custom text overrides for localization. Falls back to English defaults for any omitted keys. */\n text?: Partial<LoginPageText>;\n /** Custom className for the container */\n className?: string;\n /**\n * Color variant for themed elements (default: 'primary').\n * Uses static Tailwind classes to ensure JIT compatibility.\n */\n colorVariant?: LoginPageColorVariant;\n}\n\n/**\n * Text content for the LoginPage\n */\nexport interface LoginPageText {\n signIn: string;\n signUp: string;\n createAccount: string;\n signInToAccount: string;\n emailLabel: string;\n emailPlaceholder: string;\n passwordLabel: string;\n passwordPlaceholder: string;\n orContinueWith: string;\n signInWithGoogle: string;\n alreadyHaveAccount: string;\n dontHaveAccount: string;\n}\n\nconst defaultText: LoginPageText = {\n signIn: 'Sign in',\n signUp: 'Sign up',\n createAccount: 'Create your account',\n signInToAccount: 'Sign in to your account',\n emailLabel: 'Email address',\n emailPlaceholder: '',\n passwordLabel: 'Password',\n passwordPlaceholder: '',\n orContinueWith: 'Or continue with',\n signInWithGoogle: 'Sign in with Google',\n alreadyHaveAccount: 'Already have an account?',\n dontHaveAccount: \"Don't have an account?\",\n};\n\n// Error codes that represent user actions rather than actual errors\nconst USER_ACTION_ERROR_CODES = [\n 'auth/popup-closed-by-user',\n 'auth/cancelled-popup-request',\n 'auth/user-cancelled',\n];\n\n/**\n * Static Tailwind class mappings for text elements per color variant.\n * Button and input styles come from @sudobility/design system.\n */\nconst colorVariantClasses: Record<\n LoginPageColorVariant,\n {\n title: string;\n toggleLink: string;\n }\n> = {\n primary: {\n title: 'text-blue-600',\n toggleLink: 'text-blue-600 hover:text-blue-500',\n },\n blue: {\n title: 'text-blue-600',\n toggleLink: 'text-blue-600 hover:text-blue-500',\n },\n indigo: {\n title: 'text-indigo-600',\n toggleLink: 'text-indigo-600 hover:text-indigo-500',\n },\n violet: {\n title: 'text-violet-600',\n toggleLink: 'text-violet-600 hover:text-violet-500',\n },\n orange: {\n title: 'text-orange-600',\n toggleLink: 'text-orange-600 hover:text-orange-500',\n },\n emerald: {\n title: 'text-emerald-600',\n toggleLink: 'text-emerald-600 hover:text-emerald-500',\n },\n rose: {\n title: 'text-rose-600',\n toggleLink: 'text-rose-600 hover:text-rose-500',\n },\n};\n\n/**\n * A reusable login page component with email/password and Google sign-in support.\n *\n * This component is fully decoupled from any auth provider. The consumer provides\n * auth handler callbacks (`onEmailSignIn`, `onEmailSignUp`, `onGoogleSignIn`).\n *\n * @example\n * ```tsx\n * import { LoginPage } from '@sudobility/building_blocks';\n * import { signInWithEmailAndPassword, createUserWithEmailAndPassword, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';\n * import { getFirebaseAuth } from '@sudobility/auth_lib';\n *\n * function MyLoginPage() {\n * const navigate = useNavigate();\n * const auth = getFirebaseAuth();\n *\n * return (\n * <LoginPage\n * appName=\"My App\"\n * onEmailSignIn={async (email, password) => {\n * await signInWithEmailAndPassword(auth, email, password);\n * }}\n * onEmailSignUp={async (email, password) => {\n * await createUserWithEmailAndPassword(auth, email, password);\n * }}\n * onGoogleSignIn={async () => {\n * await signInWithPopup(auth, new GoogleAuthProvider());\n * }}\n * onSuccess={() => navigate('/')}\n * />\n * );\n * }\n * ```\n */\nexport function LoginPage({\n appName,\n logo,\n onEmailSignIn,\n onEmailSignUp,\n onGoogleSignIn,\n onSuccess,\n onAuthError,\n text: textOverrides,\n showGoogleSignIn = true,\n showSignUp = true,\n className = '',\n colorVariant = 'primary',\n}: LoginPageProps) {\n // Development-only warnings for common misconfigurations\n if (process.env.NODE_ENV !== 'production') {\n if (showSignUp && !onEmailSignUp) {\n console.warn(\n '[LoginPage] showSignUp is true but onEmailSignUp handler is not provided. ' +\n 'Sign-up will fall back to onEmailSignIn. Provide onEmailSignUp for proper account creation.'\n );\n }\n if (showGoogleSignIn && !onGoogleSignIn) {\n console.warn(\n '[LoginPage] showGoogleSignIn is true but onGoogleSignIn handler is not provided. ' +\n 'Google sign-in button will not be rendered. Provide onGoogleSignIn or set showGoogleSignIn to false.'\n );\n }\n }\n const [isSignUp, setIsSignUp] = useState(false);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [isGoogleSignInPending, setIsGoogleSignInPending] = useState(false);\n const googleSignInStartTime = useRef<number | null>(null);\n\n const colors = colorVariantClasses[colorVariant];\n\n // Reset Google sign-in state when window regains focus\n // This handles the case where browser opens a new tab instead of popup\n useEffect(() => {\n const handleFocus = () => {\n if (isGoogleSignInPending && googleSignInStartTime.current) {\n // If more than 2 seconds have passed since sign-in started,\n // and we're back in focus, the user likely closed the tab/popup\n const elapsed = Date.now() - googleSignInStartTime.current;\n if (elapsed > 2000) {\n setIsLoading(false);\n setIsGoogleSignInPending(false);\n googleSignInStartTime.current = null;\n }\n }\n };\n\n window.addEventListener('focus', handleFocus);\n return () => window.removeEventListener('focus', handleFocus);\n }, [isGoogleSignInPending]);\n\n const handleAuthError = (err: unknown) => {\n const firebaseError = err as { code?: string; message?: string };\n const code = firebaseError.code || 'unknown';\n const message = firebaseError.message || 'Authentication failed';\n const isUserAction = USER_ACTION_ERROR_CODES.includes(code);\n\n if (onAuthError) {\n onAuthError({ code, message, isUserAction });\n } else if (!isUserAction) {\n // Only show inline error for actual errors, not user actions\n setError(message);\n }\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n setIsLoading(true);\n\n try {\n if (isSignUp && showSignUp && onEmailSignUp) {\n await onEmailSignUp(email, password);\n } else {\n await onEmailSignIn(email, password);\n }\n onSuccess();\n } catch (err) {\n handleAuthError(err);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleGoogleSignIn = async () => {\n if (!onGoogleSignIn) return;\n\n setError(null);\n setIsLoading(true);\n setIsGoogleSignInPending(true);\n googleSignInStartTime.current = Date.now();\n\n try {\n await onGoogleSignIn();\n onSuccess();\n } catch (err) {\n handleAuthError(err);\n } finally {\n setIsLoading(false);\n setIsGoogleSignInPending(false);\n googleSignInStartTime.current = null;\n }\n };\n\n const text = { ...defaultText, ...textOverrides };\n\n return (\n <div\n className={cn(\n `min-h-screen flex items-center justify-center ${ui.background.subtle} py-12 px-4 sm:px-6 lg:px-8`,\n className\n )}\n >\n <div className='max-w-md w-full space-y-8'>\n <div>\n {logo && <div className='flex justify-center mb-4'>{logo}</div>}\n <h1 className={cn('text-center text-3xl font-bold', colors.title)}>\n {appName}\n </h1>\n <h2\n className={`mt-6 text-center text-2xl font-semibold ${ui.text.strong}`}\n >\n {isSignUp && showSignUp ? text.createAccount : text.signInToAccount}\n </h2>\n </div>\n\n <form className='mt-8 space-y-6' onSubmit={handleSubmit}>\n {error && (\n <div\n className={`${designColors.component.alert.error.base} ${designColors.component.alert.error.dark} border px-4 py-3 rounded-md text-sm`}\n role='alert'\n >\n {error}\n </div>\n )}\n\n <div className='space-y-4'>\n <div>\n <label htmlFor='login-email' className={`block ${ui.text.label}`}>\n {text.emailLabel}\n </label>\n <input\n id='login-email'\n name='email'\n type='email'\n autoComplete='email'\n required\n value={email}\n onChange={e => setEmail(e.target.value)}\n placeholder={text.emailPlaceholder}\n className={cn(\n `mt-1 appearance-none block w-full px-3 py-2 border rounded-md shadow-sm sm:text-sm ${designColors.component.input.default.base} ${designColors.component.input.default.dark}`,\n focusRing\n )}\n />\n </div>\n\n <div>\n <label\n htmlFor='login-password'\n className={`block ${ui.text.label}`}\n >\n {text.passwordLabel}\n </label>\n <input\n id='login-password'\n name='password'\n type='password'\n autoComplete={isSignUp ? 'new-password' : 'current-password'}\n required\n value={password}\n onChange={e => setPassword(e.target.value)}\n placeholder={text.passwordPlaceholder}\n className={cn(\n `mt-1 appearance-none block w-full px-3 py-2 border rounded-md shadow-sm sm:text-sm ${designColors.component.input.default.base} ${designColors.component.input.default.dark}`,\n focusRing\n )}\n />\n </div>\n </div>\n\n <div>\n <button\n type='submit'\n disabled={isLoading}\n className={cn(\n 'w-full inline-flex items-center justify-center font-medium rounded-md px-4 py-2 text-sm',\n buttonVariant('primary'),\n 'disabled:opacity-50 disabled:cursor-not-allowed'\n )}\n >\n {isLoading && (\n <svg\n className='animate-spin -ml-1 mr-2 h-4 w-4'\n xmlns='http://www.w3.org/2000/svg'\n fill='none'\n viewBox='0 0 24 24'\n aria-hidden='true'\n >\n <circle\n className='opacity-25'\n cx='12'\n cy='12'\n r='10'\n stroke='currentColor'\n strokeWidth='4'\n />\n <path\n className='opacity-75'\n fill='currentColor'\n d='M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z'\n />\n </svg>\n )}\n {isSignUp && showSignUp ? text.signUp : text.signIn}\n </button>\n </div>\n\n {showGoogleSignIn && onGoogleSignIn && (\n <>\n <div className='relative'>\n <div className='absolute inset-0 flex items-center'>\n <div className={`w-full border-t ${ui.border.default}`} />\n </div>\n <div className='relative flex justify-center text-sm'>\n <span\n className={`px-2 ${ui.background.subtle} ${ui.text.muted}`}\n >\n {text.orContinueWith}\n </span>\n </div>\n </div>\n\n <div>\n <button\n type='button'\n onClick={handleGoogleSignIn}\n disabled={isLoading}\n className={cn(\n 'w-full inline-flex items-center justify-center font-medium rounded-md px-4 py-2 text-sm',\n buttonVariant('outline'),\n `${ui.background.surface} ${ui.text.label} disabled:opacity-50 disabled:cursor-not-allowed`\n )}\n >\n {isLoading ? (\n <svg\n className='animate-spin -ml-1 mr-2 h-5 w-5'\n xmlns='http://www.w3.org/2000/svg'\n fill='none'\n viewBox='0 0 24 24'\n aria-hidden='true'\n >\n <circle\n className='opacity-25'\n cx='12'\n cy='12'\n r='10'\n stroke='currentColor'\n strokeWidth='4'\n />\n <path\n className='opacity-75'\n fill='currentColor'\n d='M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z'\n />\n </svg>\n ) : (\n <GoogleIcon className='h-5 w-5 mr-2' />\n )}\n {text.signInWithGoogle}\n </button>\n </div>\n </>\n )}\n </form>\n\n {showSignUp && (\n <p className={`text-center text-sm ${ui.text.muted}`}>\n {isSignUp ? text.alreadyHaveAccount : text.dontHaveAccount}{' '}\n <button\n type='button'\n onClick={() => setIsSignUp(!isSignUp)}\n className={cn('font-medium', colors.toggleLink)}\n >\n {isSignUp ? text.signIn : text.signUp}\n </button>\n </p>\n )}\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport { buttonVariant, ui } from '@sudobility/design';\nimport { cn } from '../../utils';\n\nexport interface EmptyStateProps {\n /** Message text displayed in the empty state */\n message: string;\n /** Label for the primary action button */\n buttonLabel: string;\n /** Callback fired when the button is pressed */\n onPress: () => void;\n}\n\n/**\n * EmptyState - Centered message with a primary action button.\n *\n * Use this when a list or page has no content to display.\n *\n * @example\n * ```tsx\n * <EmptyState\n * message=\"No items found\"\n * buttonLabel=\"Create Item\"\n * onPress={() => navigate('/new')}\n * />\n * ```\n */\nexport const EmptyState: React.FC<EmptyStateProps> = ({\n message,\n buttonLabel,\n onPress,\n}) => {\n return (\n <div className='flex-1 flex flex-col items-center justify-center px-8'>\n <p\n className={cn(\n ui.text.muted,\n 'text-center text-[15px] leading-relaxed mb-5'\n )}\n >\n {message}\n </p>\n <button\n type='button'\n onClick={onPress}\n className={cn(\n buttonVariant('primary'),\n 'rounded-md px-6 py-2 text-sm font-medium min-h-[44px]'\n )}\n >\n {buttonLabel}\n </button>\n </div>\n );\n};\n\nexport default EmptyState;\n","/**\n * Default i18n configuration for Sudobility apps\n *\n * Creates a pre-configured i18next instance with:\n * - HTTP backend for loading translations from /locales/\n * - Language detection from URL path, localStorage, navigator\n * - React integration\n */\n\nimport i18n from 'i18next';\nimport { initReactI18next } from 'react-i18next';\nimport Backend from 'i18next-http-backend';\nimport LanguageDetector from 'i18next-browser-languagedetector';\n\n// Default supported languages\nconst DEFAULT_SUPPORTED_LANGUAGES = ['en'];\n\n// Default namespaces\nconst DEFAULT_NAMESPACES = [\n 'common',\n 'home',\n 'pricing',\n 'docs',\n 'dashboard',\n 'auth',\n 'privacy',\n 'terms',\n 'settings',\n];\n\n/**\n * Detect language from URL path first, then localStorage\n */\nfunction detectLanguageFromPath(supportedLanguages: string[]): string {\n if (typeof window === 'undefined') {\n return 'en';\n }\n\n // Check URL path first\n const pathLang = window.location.pathname.split('/')[1];\n if (pathLang && supportedLanguages.includes(pathLang)) {\n return pathLang;\n }\n\n // Fall back to localStorage\n try {\n const stored = localStorage.getItem('language');\n if (stored && supportedLanguages.includes(stored)) {\n return stored;\n }\n } catch {\n // localStorage may throw in Safari private browsing\n }\n\n return 'en';\n}\n\nexport interface I18nConfig {\n /**\n * Supported language codes.\n * Defaults to [\"en\"].\n */\n supportedLanguages?: string[];\n\n /**\n * Translation namespaces to load.\n * Defaults to common app namespaces.\n */\n namespaces?: string[];\n\n /**\n * Default namespace.\n * Defaults to \"common\".\n */\n defaultNamespace?: string;\n\n /**\n * Path pattern for loading translations.\n * Defaults to \"/locales/{{lng}}/{{ns}}.json\".\n */\n loadPath?: string;\n\n /**\n * Enable debug logging.\n * Defaults to false.\n */\n debug?: boolean;\n}\n\nlet initialized = false;\n\n/**\n * Initialize the default i18n instance.\n * Safe to call multiple times - only initializes once.\n */\nexport function initializeI18n(config: I18nConfig = {}): typeof i18n {\n if (initialized) {\n return i18n;\n }\n initialized = true;\n\n const {\n supportedLanguages = DEFAULT_SUPPORTED_LANGUAGES,\n namespaces = DEFAULT_NAMESPACES,\n defaultNamespace = 'common',\n loadPath = '/locales/{{lng}}/{{ns}}.json',\n debug = false,\n } = config;\n\n i18n\n .use(Backend)\n .use(LanguageDetector)\n .use(initReactI18next)\n .init({\n lng: detectLanguageFromPath(supportedLanguages),\n fallbackLng: {\n zh: ['zh', 'en'],\n 'zh-hant': ['zh-hant', 'zh', 'en'],\n default: ['en'],\n },\n initImmediate: false,\n supportedLngs: supportedLanguages,\n debug,\n nonExplicitSupportedLngs: true,\n\n interpolation: {\n escapeValue: false,\n },\n\n backend: {\n loadPath,\n },\n\n detection: {\n order: ['path', 'localStorage', 'navigator'],\n caches: ['localStorage'],\n lookupLocalStorage: 'language',\n lookupFromPathIndex: 0,\n },\n\n load: 'languageOnly',\n preload: [],\n cleanCode: false,\n lowerCaseLng: false,\n\n defaultNS: defaultNamespace,\n ns: namespaces,\n });\n\n return i18n;\n}\n\n/**\n * Get the i18n instance.\n * Initializes with defaults if not already initialized.\n */\nexport function getI18n(): typeof i18n {\n if (!initialized) {\n initializeI18n();\n }\n return i18n;\n}\n\nexport { i18n };\nexport default i18n;\n"],"names":["a","b","DefaultLinkComponent","className","AuthStatus","ChainType","FooterContainer","Theme","FontSize","defaultTranslations","colors","designColors"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/utils/index.ts","../src/constants/languages.ts","../src/components/topbar/language-selector.tsx","../src/components/topbar/app-topbar.tsx","../src/components/topbar/app-topbar-with-firebase-auth.tsx","../src/components/topbar/app-topbar-with-wallet.tsx","../src/components/breadcrumbs/app-breadcrumbs.tsx","../src/components/footer/shared.tsx","../src/components/footer/app-footer.tsx","../src/components/footer/app-footer-for-home-page.tsx","../src/components/layout/app-page-layout.tsx","../src/components/settings/appearance-settings.tsx","../src/components/settings/global-settings-page.tsx","../src/components/pages/app-sitemap-page.tsx","../src/components/pages/app-text-page.tsx","../src/components/pages/login-page.tsx","../src/components/empty-state/EmptyState.tsx","../src/i18n/index.ts"],"sourcesContent":["import { type ClassValue, clsx } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\n/**\n * Merge class names with Tailwind CSS classes.\n * Combines clsx for conditional classes and tailwind-merge for deduplication.\n */\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","/**\n * @fileoverview Language configuration constants for i18n support.\n *\n * Provides a default set of 16 supported languages, RTL language detection,\n * and the LanguageConfig interface used throughout the building_blocks package.\n */\n\n/**\n * Configuration for a supported language.\n *\n * Used by LanguageSelector, initializeI18n, and consuming apps\n * to display available languages with their native names and emoji flags.\n */\nexport interface LanguageConfig {\n /** ISO 639-1 language code (e.g., 'en', 'zh-hant') */\n code: string;\n /** Native name of the language (e.g., 'English', '日本語') */\n name: string;\n /** Emoji flag representing the language's primary region (e.g., '🇺🇸') */\n flag: string;\n}\n\n/**\n * Default set of 16 supported languages with their flags.\n * Apps can override this list by passing their own languages prop.\n */\nexport const DEFAULT_LANGUAGES: LanguageConfig[] = [\n { code: 'en', name: 'English', flag: '🇺🇸' },\n { code: 'ar', name: 'العربية', flag: '🇸🇦' },\n { code: 'de', name: 'Deutsch', flag: '🇩🇪' },\n { code: 'es', name: 'Español', flag: '🇪🇸' },\n { code: 'fr', name: 'Français', flag: '🇫🇷' },\n { code: 'it', name: 'Italiano', flag: '🇮🇹' },\n { code: 'ja', name: '日本語', flag: '🇯🇵' },\n { code: 'ko', name: '한국어', flag: '🇰🇷' },\n { code: 'pt', name: 'Português', flag: '🇵🇹' },\n { code: 'ru', name: 'Русский', flag: '🇷🇺' },\n { code: 'sv', name: 'Svenska', flag: '🇸🇪' },\n { code: 'th', name: 'ไทย', flag: '🇹🇭' },\n { code: 'uk', name: 'Українська', flag: '🇺🇦' },\n { code: 'vi', name: 'Tiếng Việt', flag: '🇻🇳' },\n { code: 'zh', name: '简体中文', flag: '🇨🇳' },\n { code: 'zh-hant', name: '繁體中文', flag: '🇹🇼' },\n];\n\n/**\n * Languages that use right-to-left text direction.\n */\nexport const RTL_LANGUAGES = ['ar'];\n\n/**\n * Check if a language code is RTL.\n *\n * @param languageCode - ISO 639-1 language code to check\n * @returns true if the language uses right-to-left text direction\n */\nexport function isRTL(languageCode: string): boolean {\n return RTL_LANGUAGES.includes(languageCode);\n}\n","import React, {\n useState,\n useCallback,\n useMemo,\n useRef,\n useEffect,\n} from 'react';\nimport { ChevronDownIcon } from '@heroicons/react/24/outline';\nimport { cn } from '../../utils';\nimport { ui } from '@sudobility/design';\nimport {\n DEFAULT_LANGUAGES,\n type LanguageConfig,\n} from '../../constants/languages';\n\nexport interface LanguageSelectorProps {\n /** Available languages (defaults to 16 built-in languages) */\n languages?: LanguageConfig[];\n /** Current language code */\n currentLanguage?: string;\n /** Language change handler */\n onLanguageChange?: (languageCode: string) => void;\n /** Variant: 'compact' for topbar, 'full' for settings */\n variant?: 'compact' | 'full';\n /** Custom className */\n className?: string;\n /** Label text for full variant */\n label?: string;\n /** Helper text for full variant */\n helperText?: string;\n}\n\n/**\n * LanguageSelector component with dropdown for switching languages.\n * Uses default 16 languages if none provided.\n *\n * @example\n * ```tsx\n * // Compact variant for topbar\n * <LanguageSelector\n * currentLanguage=\"en\"\n * onLanguageChange={(code) => i18n.changeLanguage(code)}\n * variant=\"compact\"\n * />\n *\n * // Full variant for settings pages\n * <LanguageSelector\n * currentLanguage=\"en\"\n * onLanguageChange={(code) => i18n.changeLanguage(code)}\n * variant=\"full\"\n * label=\"Language\"\n * helperText=\"Select your preferred language\"\n * />\n * ```\n */\nexport const LanguageSelector: React.FC<LanguageSelectorProps> = ({\n languages = DEFAULT_LANGUAGES,\n currentLanguage = 'en',\n onLanguageChange,\n variant = 'compact',\n className,\n label = 'Language',\n helperText = 'Select your preferred language',\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n // Sort languages alphabetically by name\n const sortedLanguages = useMemo(\n () => [...languages].sort((a, b) => a.name.localeCompare(b.name)),\n [languages]\n );\n\n const currentLang = useMemo(\n () => languages.find(lang => lang.code === currentLanguage) || languages[0],\n [languages, currentLanguage]\n );\n\n const handleLanguageChange = useCallback(\n (langCode: string) => {\n if (langCode !== currentLanguage) {\n onLanguageChange?.(langCode);\n }\n setIsOpen(false);\n },\n [currentLanguage, onLanguageChange]\n );\n\n // Close dropdown when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n return () =>\n document.removeEventListener('mousedown', handleClickOutside);\n }\n }, [isOpen]);\n\n // Close dropdown on escape\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }\n }, [isOpen]);\n\n if (variant === 'compact') {\n return (\n <div ref={dropdownRef} className={cn('relative', className)}>\n <button\n onClick={() => setIsOpen(!isOpen)}\n className={cn(\n 'flex items-center gap-2 px-3 py-2 h-10 rounded-lg',\n 'hover:bg-gray-100 dark:hover:bg-gray-700',\n 'transition-colors'\n )}\n aria-label='Select language'\n aria-expanded={isOpen}\n aria-haspopup='listbox'\n >\n <span className='text-lg leading-none'>{currentLang?.flag}</span>\n <span\n className={`hidden sm:block text-sm font-medium ${ui.text.label}`}\n >\n {currentLang?.name}\n </span>\n <ChevronDownIcon\n className={cn(\n `h-4 w-4 ${ui.text.muted} transition-transform`,\n isOpen && 'rotate-180'\n )}\n />\n </button>\n\n {isOpen && (\n <div\n className={cn(\n 'absolute right-0 mt-2 w-48 py-1 z-50',\n ui.background.surface,\n `border ${ui.border.default}`,\n 'rounded-lg shadow-lg'\n )}\n role='listbox'\n aria-label='Languages'\n >\n {sortedLanguages.map(lang => (\n <button\n key={lang.code}\n onClick={() => handleLanguageChange(lang.code)}\n className={cn(\n 'w-full flex items-center gap-3 px-3 py-2 text-left',\n 'hover:bg-gray-100 dark:hover:bg-gray-700',\n 'transition-colors',\n lang.code === currentLanguage &&\n 'bg-gray-100 dark:bg-gray-700 font-medium'\n )}\n role='option'\n aria-selected={lang.code === currentLanguage}\n >\n <span className='text-lg leading-none'>{lang.flag}</span>\n <span className={`text-sm ${ui.text.label}`}>{lang.name}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n );\n }\n\n // Full variant for settings pages\n return (\n <div ref={dropdownRef} className={cn('space-y-2', className)}>\n <label className={`${ui.text.label} flex items-center gap-2`}>\n <span>{label}</span>\n </label>\n\n <div className='relative'>\n <button\n onClick={() => setIsOpen(!isOpen)}\n className={cn(\n 'flex items-center justify-between w-full px-3 py-2 text-left',\n ui.background.surface,\n `border ${ui.border.default}`,\n 'rounded-md',\n 'hover:bg-gray-50 dark:hover:bg-gray-700',\n 'transition-colors'\n )}\n aria-expanded={isOpen}\n aria-haspopup='listbox'\n >\n <div className='flex items-center gap-2'>\n <span className='text-lg leading-none'>{currentLang?.flag}</span>\n <span className={`text-sm ${ui.text.label}`}>\n {currentLang?.name}\n </span>\n </div>\n <ChevronDownIcon\n className={cn(\n `h-4 w-4 ${ui.text.muted} transition-transform`,\n isOpen && 'rotate-180'\n )}\n />\n </button>\n\n {isOpen && (\n <div\n className={cn(\n 'absolute left-0 right-0 mt-1 py-1 z-50',\n ui.background.surface,\n `border ${ui.border.default}`,\n 'rounded-md shadow-lg'\n )}\n role='listbox'\n aria-label='Languages'\n >\n {sortedLanguages.map(lang => (\n <button\n key={lang.code}\n onClick={() => handleLanguageChange(lang.code)}\n className={cn(\n 'w-full flex items-center gap-3 px-3 py-2 text-left',\n 'hover:bg-gray-100 dark:hover:bg-gray-700',\n 'transition-colors',\n lang.code === currentLanguage &&\n 'bg-gray-100 dark:bg-gray-700 font-medium'\n )}\n role='option'\n aria-selected={lang.code === currentLanguage}\n >\n <span className='text-lg leading-none'>{lang.flag}</span>\n <span className={`text-sm ${ui.text.label}`}>{lang.name}</span>\n </button>\n ))}\n </div>\n )}\n </div>\n\n {helperText && <p className={`text-xs ${ui.text.muted}`}>{helperText}</p>}\n </div>\n );\n};\n\nexport default LanguageSelector;\n","import React, { useMemo, type ComponentType, type ReactNode } from 'react';\nimport {\n Topbar,\n TopbarProvider,\n TopbarLeft,\n TopbarCenter,\n TopbarRight,\n TopbarLogo,\n TopbarNavigation,\n TopbarActions,\n TopbarMobileContent,\n Logo,\n type TopbarNavItem,\n} from '@sudobility/components';\nimport { cn } from '../../utils';\nimport {\n LanguageSelector,\n type LanguageSelectorProps,\n} from './language-selector';\nimport type {\n MenuItemConfig,\n LogoConfig,\n LanguageConfig,\n LinkComponentProps,\n} from '../../types';\nimport { DEFAULT_LANGUAGES } from '../../constants/languages';\n\nexport interface AppTopBarProps {\n /** Logo configuration */\n logo: LogoConfig;\n\n /** Navigation menu items */\n menuItems: MenuItemConfig[];\n\n /** Available languages for selector (defaults to 16 built-in languages) */\n languages?: LanguageConfig[];\n\n /** Current language code */\n currentLanguage?: string;\n\n /** Language change handler */\n onLanguageChange?: (languageCode: string) => void;\n\n /** Hide language selector */\n hideLanguageSelector?: boolean;\n\n /** Language selector props override */\n languageSelectorProps?: Partial<LanguageSelectorProps>;\n\n /** Breakpoint to collapse navigation to hamburger menu */\n collapseBelow?: 'sm' | 'md' | 'lg' | 'xl';\n\n /** Render prop for account/auth section (right side of topbar) */\n renderAccountSection?: () => ReactNode;\n\n /** Render prop for center section (e.g., search bar) - shown on desktop */\n renderCenterSection?: () => ReactNode;\n\n /** Render prop for mobile-specific content (e.g., mobile search) - shown below main topbar on mobile */\n renderMobileContent?: () => ReactNode;\n\n /** Custom Link component for navigation (for react-router-dom, Next.js, etc.) */\n LinkComponent?: ComponentType<LinkComponentProps>;\n\n /** Optional sticky positioning */\n sticky?: boolean;\n\n /** Optional variant */\n variant?: 'default' | 'app';\n\n /** Mobile menu label for accessibility */\n mobileMenuLabel?: string;\n\n /** Custom className for topbar */\n className?: string;\n\n /** z-index level */\n zIndex?: 'default' | 'highest' | 'high';\n\n /** Aria label for navigation */\n ariaLabel?: string;\n}\n\n/**\n * Default Link component that renders a plain anchor tag.\n * Apps should provide their own LinkComponent for router integration.\n */\nconst DefaultLinkComponent: ComponentType<LinkComponentProps> = ({\n href,\n className,\n children,\n onClick,\n}) => (\n <a href={href} className={className} onClick={onClick}>\n {children}\n </a>\n);\n\n/**\n * AppTopBar - Base topbar component for Sudobility apps.\n *\n * Features:\n * - Logo with app name on the left\n * - Navigation menu items with icons\n * - Language selector\n * - Render prop for center section (e.g., search bar)\n * - Render prop for account/auth section\n * - Render prop for mobile-specific content\n * - Responsive with hamburger menu on mobile\n * - Dark mode support\n */\nexport const AppTopBar: React.FC<AppTopBarProps> = ({\n logo,\n menuItems,\n languages = DEFAULT_LANGUAGES,\n currentLanguage = 'en',\n onLanguageChange,\n hideLanguageSelector = false,\n languageSelectorProps,\n collapseBelow = 'lg',\n renderAccountSection,\n renderCenterSection,\n renderMobileContent,\n LinkComponent = DefaultLinkComponent,\n sticky = true,\n variant = 'default',\n mobileMenuLabel = 'Menu',\n className,\n zIndex = 'highest',\n ariaLabel = 'Main navigation',\n}) => {\n // Filter menu items that should be shown\n const visibleMenuItems = useMemo(\n () => menuItems.filter(item => item.show !== false),\n [menuItems]\n );\n\n // Convert MenuItemConfig to TopbarNavItem (recursively for children)\n const navItems: TopbarNavItem[] = useMemo(() => {\n const mapItem = (item: MenuItemConfig): TopbarNavItem => ({\n id: item.id,\n label: item.label,\n icon: item.icon,\n href: item.href,\n className: item.className,\n children: item.children\n ?.filter(child => child.show !== false)\n .map(mapItem),\n });\n return visibleMenuItems.map(mapItem);\n }, [visibleMenuItems]);\n\n // Wrapper to adapt LinkComponent to TopbarNavigation expected interface\n const LinkWrapper: ComponentType<{\n href: string;\n className?: string;\n children: ReactNode;\n }> = useMemo(\n () =>\n ({ href, className, children }) => (\n <LinkComponent href={href} className={className}>\n {children}\n </LinkComponent>\n ),\n [LinkComponent]\n );\n\n const handleLogoClick = () => {\n logo.onClick?.();\n };\n\n return (\n <TopbarProvider variant={variant} sticky={sticky}>\n <Topbar\n variant={variant}\n sticky={sticky}\n zIndex={zIndex}\n aria-label={ariaLabel}\n className={cn(className)}\n >\n <TopbarLeft>\n {navItems.length > 0 ? (\n <TopbarNavigation\n items={navItems}\n collapseBelow={collapseBelow}\n LinkComponent={LinkWrapper}\n mobileMenuLabel={mobileMenuLabel}\n >\n <TopbarLogo onClick={handleLogoClick} size='md'>\n <Logo\n size='md'\n logoSrc={logo.src}\n logoText={logo.appName}\n logoAlt={logo.alt || logo.appName}\n showText={true}\n />\n </TopbarLogo>\n </TopbarNavigation>\n ) : (\n <TopbarLogo onClick={handleLogoClick} size='md'>\n <Logo\n size='md'\n logoSrc={logo.src}\n logoText={logo.appName}\n logoAlt={logo.alt || logo.appName}\n showText={true}\n />\n </TopbarLogo>\n )}\n </TopbarLeft>\n\n {renderCenterSection && (\n <TopbarCenter>{renderCenterSection()}</TopbarCenter>\n )}\n\n <TopbarRight>\n <TopbarActions gap='md'>\n {!hideLanguageSelector && (\n <LanguageSelector\n languages={languages}\n currentLanguage={currentLanguage}\n onLanguageChange={onLanguageChange}\n variant='compact'\n {...languageSelectorProps}\n />\n )}\n {renderAccountSection?.()}\n </TopbarActions>\n </TopbarRight>\n\n {renderMobileContent && (\n <TopbarMobileContent>{renderMobileContent()}</TopbarMobileContent>\n )}\n </Topbar>\n </TopbarProvider>\n );\n};\n\nexport default AppTopBar;\n","import React, { type ReactNode, type ComponentType } from 'react';\nimport { AppTopBar, type AppTopBarProps } from './app-topbar';\nimport { cn } from '../../utils';\nimport { GRADIENT_CLASSES } from '@sudobility/design';\n\n/**\n * Auth menu item for the authenticated user dropdown.\n * This matches the AuthMenuItem interface from @sudobility/auth-components.\n */\nexport interface AuthMenuItem {\n /** Unique identifier */\n id: string;\n /** Display label */\n label: string;\n /** Icon element (typically a small SVG) */\n icon?: ReactNode;\n /** Click handler */\n onClick?: () => void;\n /** Show divider after this item */\n dividerAfter?: boolean;\n}\n\n/**\n * Props for the AuthAction component from @sudobility/auth-components.\n */\nexport interface AuthActionProps {\n /** Avatar size in pixels */\n avatarSize?: number;\n /** Dropdown alignment */\n dropdownAlign?: 'left' | 'right';\n /** Login button click handler */\n onLoginClick?: () => void;\n /** Menu items for authenticated user dropdown */\n menuItems?: AuthMenuItem[];\n /** Custom login button text */\n loginButtonText?: string;\n /** Custom className for login button */\n loginButtonClassName?: string;\n}\n\nexport interface AppTopBarWithFirebaseAuthProps extends Omit<\n AppTopBarProps,\n 'renderAccountSection'\n> {\n /**\n * AuthAction component from @sudobility/auth-components.\n * This is passed as a prop to avoid hard dependency on auth-components.\n */\n AuthActionComponent: ComponentType<AuthActionProps>;\n\n /** Additional menu items for authenticated users */\n authenticatedMenuItems?: AuthMenuItem[];\n\n /** Login button click handler */\n onLoginClick?: () => void;\n\n /** Avatar size in pixels */\n avatarSize?: number;\n\n /** Dropdown alignment */\n dropdownAlign?: 'left' | 'right';\n\n /** Custom login button text */\n loginButtonText?: string;\n\n /** Custom login button className */\n loginButtonClassName?: string;\n}\n\n/**\n * AppTopBarWithFirebaseAuth - TopBar with Firebase authentication integration.\n *\n * This component wraps AppTopBar and provides the AuthAction component\n * from @sudobility/auth-components for the account section.\n *\n * Note: The AuthAction component must be passed as a prop to avoid\n * hard dependency on @sudobility/auth-components.\n *\n * @example\n * ```tsx\n * import { AuthAction } from '@sudobility/auth-components';\n *\n * <AppTopBarWithFirebaseAuth\n * logo={{ src: '/logo.png', appName: 'My App' }}\n * menuItems={[...]}\n * AuthActionComponent={AuthAction}\n * onLoginClick={() => navigate('/login')}\n * authenticatedMenuItems={[\n * { id: 'dashboard', label: 'Dashboard', onClick: () => navigate('/dashboard') },\n * ]}\n * />\n * ```\n */\nexport const AppTopBarWithFirebaseAuth: React.FC<\n AppTopBarWithFirebaseAuthProps\n> = ({\n AuthActionComponent,\n authenticatedMenuItems = [],\n onLoginClick,\n avatarSize = 32,\n dropdownAlign = 'right',\n loginButtonText,\n loginButtonClassName,\n ...topBarProps\n}) => {\n const renderAccountSection = () => (\n <AuthActionComponent\n avatarSize={avatarSize}\n dropdownAlign={dropdownAlign}\n onLoginClick={onLoginClick}\n menuItems={authenticatedMenuItems}\n loginButtonText={loginButtonText}\n loginButtonClassName={cn(\n GRADIENT_CLASSES.headerButton,\n 'py-1.5',\n loginButtonClassName\n )}\n />\n );\n\n return (\n <AppTopBar {...topBarProps} renderAccountSection={renderAccountSection} />\n );\n};\n\nexport default AppTopBarWithFirebaseAuth;\n","import React, { type ReactNode, type ComponentType } from 'react';\nimport { AppTopBar, type AppTopBarProps } from './app-topbar';\nimport { cn } from '../../utils';\nimport { GRADIENT_CLASSES, buttonVariant, ui } from '@sudobility/design';\n\n/**\n * Wallet menu item for the connected wallet dropdown.\n */\nexport interface WalletMenuItem {\n /** Unique identifier */\n id: string;\n /** Display label */\n label: string;\n /** Icon component */\n icon?: ComponentType<{ className?: string }>;\n /** Click handler */\n onClick: () => void;\n /** Whether this is a separator */\n separator?: boolean;\n}\n\n/**\n * Auth status enum matching @sudobility/types.\n */\nexport enum AuthStatus {\n DISCONNECTED = 'disconnected',\n CONNECTED = 'connected',\n VERIFIED = 'verified',\n}\n\n/**\n * Chain type enum matching @sudobility/types.\n */\nexport enum ChainType {\n EVM = 'evm',\n SOLANA = 'solana',\n}\n\n/**\n * Props for the WalletDropdownMenu component from @sudobility/web3-components.\n */\nexport interface WalletDropdownMenuProps {\n walletAddress: string;\n authStatus: AuthStatus | string;\n chainType: ChainType | string | 'unknown';\n menuItems: WalletMenuItem[];\n avatar?: string;\n displayName?: string;\n statusLabels?: {\n verified?: string;\n connected?: string;\n disconnected?: string;\n };\n}\n\nexport interface AppTopBarWithWalletProps extends Omit<\n AppTopBarProps,\n 'renderAccountSection'\n> {\n /**\n * WalletDropdownMenu component from @sudobility/web3-components.\n * This is passed as a prop to avoid hard dependency on web3-components.\n */\n WalletDropdownMenuComponent?: ComponentType<WalletDropdownMenuProps>;\n\n /** Whether wallet is connected */\n isConnected: boolean;\n\n /** Connected wallet address */\n walletAddress?: string;\n\n /** Authentication status */\n authStatus?: AuthStatus | string;\n\n /** Chain type (EVM, Solana, etc.) */\n chainType?: ChainType | string | 'unknown';\n\n /** Connect button click handler */\n onConnect: () => void;\n\n /** Disconnect handler */\n onDisconnect: () => Promise<void>;\n\n /** Custom menu items for wallet dropdown */\n walletMenuItems?: WalletMenuItem[];\n\n /** Connect button content (default: \"Connect Wallet\") */\n connectButtonContent?: ReactNode;\n\n /** Connect button className (supports gradient classes from @sudobility/design) */\n connectButtonClassName?: string;\n\n /** Use gradient styling for connect button */\n useGradientButton?: boolean;\n\n /** Optional user avatar */\n avatar?: string;\n\n /** Optional display name */\n displayName?: string;\n\n /** Custom status labels */\n statusLabels?: {\n verified?: string;\n connected?: string;\n disconnected?: string;\n };\n}\n\n/**\n * Default connect button when WalletDropdownMenuComponent is not provided\n * or when wallet is not connected.\n */\nconst DefaultConnectButton: React.FC<{\n onClick: () => void;\n content?: ReactNode;\n className?: string;\n useGradient?: boolean;\n}> = ({ onClick, content = 'Connect Wallet', className, useGradient }) => (\n <button\n onClick={onClick}\n className={cn(\n useGradient\n ? GRADIENT_CLASSES.headerButton\n : cn(\n 'px-4 py-2 text-sm font-medium rounded-lg transition-colors',\n buttonVariant('primary')\n ),\n className\n )}\n >\n {content}\n </button>\n);\n\n/**\n * Simple fallback wallet display when WalletDropdownMenuComponent is not provided.\n */\nconst FallbackWalletDisplay: React.FC<{\n walletAddress: string;\n onDisconnect: () => Promise<void>;\n}> = ({ walletAddress, onDisconnect }) => {\n const truncatedAddress = `${walletAddress.slice(0, 6)}...${walletAddress.slice(-4)}`;\n\n return (\n <div className='flex items-center gap-2'>\n <span className={`text-sm font-medium ${ui.text.label}`}>\n {truncatedAddress}\n </span>\n <button\n onClick={() => onDisconnect()}\n className={`text-xs ${ui.text.muted} hover:text-gray-700 dark:hover:text-gray-200`}\n >\n Disconnect\n </button>\n </div>\n );\n};\n\n/**\n * AppTopBarWithWallet - TopBar with wallet connection integration.\n *\n * This component wraps AppTopBar and provides wallet connection UI\n * for the account section. Uses WalletDropdownMenu from @sudobility/web3-components\n * when provided.\n *\n * @example\n * ```tsx\n * import { WalletDropdownMenu } from '@sudobility/web3-components';\n *\n * <AppTopBarWithWallet\n * logo={{ src: '/logo.png', appName: 'My App' }}\n * menuItems={[...]}\n * WalletDropdownMenuComponent={WalletDropdownMenu}\n * isConnected={isConnected}\n * walletAddress={walletAddress}\n * authStatus={authStatus}\n * chainType={chainType}\n * onConnect={() => navigate('/connect')}\n * onDisconnect={handleDisconnect}\n * walletMenuItems={[\n * { id: 'copy', label: 'Copy Address', icon: ClipboardIcon, onClick: handleCopy },\n * { id: 'disconnect', label: 'Disconnect', icon: LogoutIcon, onClick: handleDisconnect },\n * ]}\n * />\n * ```\n */\nexport const AppTopBarWithWallet: React.FC<AppTopBarWithWalletProps> = ({\n WalletDropdownMenuComponent,\n isConnected,\n walletAddress,\n authStatus = AuthStatus.DISCONNECTED,\n chainType = 'unknown',\n onConnect,\n onDisconnect,\n walletMenuItems = [],\n connectButtonContent,\n connectButtonClassName,\n useGradientButton = true,\n avatar,\n displayName,\n statusLabels,\n ...topBarProps\n}) => {\n const renderAccountSection = () => {\n // Not connected - show connect button\n if (!isConnected || !walletAddress) {\n return (\n <DefaultConnectButton\n onClick={onConnect}\n content={connectButtonContent}\n className={connectButtonClassName}\n useGradient={useGradientButton}\n />\n );\n }\n\n // Connected with WalletDropdownMenu component\n if (WalletDropdownMenuComponent) {\n return (\n <WalletDropdownMenuComponent\n walletAddress={walletAddress}\n authStatus={authStatus}\n chainType={chainType}\n menuItems={walletMenuItems}\n avatar={avatar}\n displayName={displayName}\n statusLabels={statusLabels}\n />\n );\n }\n\n // Connected without WalletDropdownMenu - fallback display\n return (\n <FallbackWalletDisplay\n walletAddress={walletAddress}\n onDisconnect={onDisconnect}\n />\n );\n };\n\n return (\n <AppTopBar {...topBarProps} renderAccountSection={renderAccountSection} />\n );\n};\n\nexport default AppTopBarWithWallet;\n","import React, {\n useState,\n useRef,\n useEffect,\n useCallback,\n type ComponentType,\n} from 'react';\nimport { CalendarDaysIcon } from '@heroicons/react/24/outline';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils';\nimport { ui } from '@sudobility/design';\nimport type {\n BreadcrumbItem,\n ShareConfig,\n TalkToFounderConfig,\n LinkComponentProps,\n} from '../../types';\n\nconst breadcrumbContainerVariants = cva('border-b', {\n variants: {\n variant: {\n default: `${ui.background.surface} ${ui.border.default}`,\n transparent: 'bg-transparent border-transparent',\n subtle: `${ui.background.subtle} ${ui.border.default}`,\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n});\n\nexport interface AppBreadcrumbsProps extends VariantProps<\n typeof breadcrumbContainerVariants\n> {\n /** Breadcrumb items */\n items: BreadcrumbItem[];\n\n /** Share configuration (shows social share buttons on right) */\n shareConfig?: ShareConfig;\n\n /** Talk to founder button configuration */\n talkToFounder?: TalkToFounderConfig;\n\n /** Custom Link component */\n LinkComponent?: ComponentType<LinkComponentProps>;\n\n /** Custom className for the container */\n className?: string;\n\n /** Custom className for the inner content */\n contentClassName?: string;\n}\n\n// Social media share URL generators\nconst createShareUrl = {\n twitter: (url: string, text: string, hashtags: string[]) => {\n const hashtagStr =\n hashtags.length > 0 ? `&hashtags=${hashtags.join(',')}` : '';\n return `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}${hashtagStr}`;\n },\n facebook: (url: string) => {\n return `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`;\n },\n linkedin: (url: string) => {\n return `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`;\n },\n reddit: (url: string, title: string) => {\n return `https://reddit.com/submit?url=${encodeURIComponent(url)}&title=${encodeURIComponent(title)}`;\n },\n telegram: (url: string, text: string) => {\n return `https://t.me/share/url?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`;\n },\n email: (url: string, title: string, description: string) => {\n return `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(description + '\\n\\n' + url)}`;\n },\n};\n\n/**\n * Share dropdown component with keyboard navigation support.\n * Supports: Enter/Space to toggle, Escape to close, Arrow keys to navigate items.\n */\nconst ShareDropdown: React.FC<{ shareConfig: ShareConfig }> = ({\n shareConfig,\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const [shareUrl, setShareUrl] = useState<string>('');\n const [isPreparingShare, setIsPreparingShare] = useState(false);\n const [showCopiedFeedback, setShowCopiedFeedback] = useState(false);\n const [focusedIndex, setFocusedIndex] = useState(-1);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n useEffect(() => {\n const onBeforeShare = shareConfig.onBeforeShare;\n if (onBeforeShare) {\n const prepareUrl = async () => {\n setIsPreparingShare(true);\n try {\n const baseUrl =\n typeof window !== 'undefined' ? window.location.href : '';\n const modifiedUrl = await onBeforeShare(baseUrl);\n setShareUrl(modifiedUrl);\n } catch {\n const baseUrl =\n typeof window !== 'undefined' ? window.location.href : '';\n setShareUrl(baseUrl);\n } finally {\n setIsPreparingShare(false);\n }\n };\n prepareUrl();\n } else {\n setShareUrl('');\n }\n }, [shareConfig]);\n\n // Close dropdown on outside click\n useEffect(() => {\n if (!isOpen) return;\n const handleClickOutside = (event: MouseEvent) => {\n if (\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n setFocusedIndex(-1);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, [isOpen]);\n\n // Close on Escape, navigate with arrow keys\n useEffect(() => {\n if (!isOpen) return;\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsOpen(false);\n setFocusedIndex(-1);\n triggerRef.current?.focus();\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen]);\n\n // Focus the item at focusedIndex when it changes\n useEffect(() => {\n if (focusedIndex >= 0 && itemRefs.current[focusedIndex]) {\n itemRefs.current[focusedIndex]?.focus();\n }\n }, [focusedIndex]);\n\n const url =\n shareUrl || (typeof window !== 'undefined' ? window.location.href : '');\n\n const sharePlatforms = [\n {\n name: 'Twitter',\n url: createShareUrl.twitter(url, shareConfig.title, shareConfig.hashtags),\n color: 'text-blue-400',\n },\n {\n name: 'Facebook',\n url: createShareUrl.facebook(url),\n color: 'text-blue-600',\n },\n {\n name: 'LinkedIn',\n url: createShareUrl.linkedin(url),\n color: 'text-blue-700',\n },\n {\n name: 'Reddit',\n url: createShareUrl.reddit(url, shareConfig.title),\n color: 'text-orange-600',\n },\n {\n name: 'Telegram',\n url: createShareUrl.telegram(url, shareConfig.title),\n color: 'text-blue-500',\n },\n {\n name: 'Email',\n url: createShareUrl.email(\n url,\n shareConfig.title,\n shareConfig.description\n ),\n color: 'text-gray-600',\n },\n ];\n\n // Check if Web Share API with files is supported\n const hasImageShare = !!shareConfig.getImageDataUrl;\n const [supportsWebShare, setSupportsWebShare] = useState(false);\n\n useEffect(() => {\n if (!hasImageShare) return;\n // Check if browser supports sharing files\n if (typeof navigator !== 'undefined' && navigator.canShare) {\n const testFile = new File([''], 'test.png', { type: 'image/png' });\n try {\n setSupportsWebShare(navigator.canShare({ files: [testFile] }));\n } catch {\n setSupportsWebShare(false);\n }\n }\n }, [hasImageShare]);\n\n // Extra items: Web Share (if supported) + Download Image (if getImageDataUrl provided)\n const extraItemCount = hasImageShare ? (supportsWebShare ? 2 : 1) : 0;\n // Total items = platforms + extra image items + copy link\n const totalItems = sharePlatforms.length + extraItemCount + 1;\n\n const copyToClipboard = async () => {\n try {\n await navigator.clipboard.writeText(url);\n setShowCopiedFeedback(true);\n setTimeout(() => {\n setShowCopiedFeedback(false);\n setIsOpen(false);\n }, 1500);\n } catch {\n // Copy failed\n }\n };\n\n const handleSocialShare = (platformUrl: string) => {\n window.open(\n platformUrl,\n '_blank',\n 'noopener,noreferrer,width=600,height=400'\n );\n setIsOpen(false);\n };\n\n /** Convert a base64 data URL to a Blob */\n const dataUrlToBlob = (dataUrl: string): Blob => {\n const [header, base64] = dataUrl.split(',');\n const mime = header.match(/:(.*?);/)?.[1] ?? 'image/png';\n const bytes = atob(base64);\n const arr = new Uint8Array(bytes.length);\n for (let i = 0; i < bytes.length; i++) arr[i] = bytes.charCodeAt(i);\n return new Blob([arr], { type: mime });\n };\n\n const handleWebShare = async () => {\n if (!shareConfig.getImageDataUrl) return;\n try {\n const dataUrl = await shareConfig.getImageDataUrl();\n if (!dataUrl) return;\n const blob = dataUrlToBlob(dataUrl);\n const file = new File([blob], 'puzzle.png', { type: 'image/png' });\n await navigator.share({\n title: shareConfig.title,\n text: shareConfig.description,\n url,\n files: [file],\n });\n } catch (err) {\n if (err instanceof Error && err.name !== 'AbortError') {\n console.error('Web Share failed:', err);\n }\n }\n setIsOpen(false);\n };\n\n const handleDownloadImage = async () => {\n if (!shareConfig.getImageDataUrl) return;\n try {\n const dataUrl = await shareConfig.getImageDataUrl();\n if (!dataUrl) return;\n const blob = dataUrlToBlob(dataUrl);\n const blobUrl = URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = blobUrl;\n link.download = 'puzzle.png';\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(blobUrl);\n } catch (err) {\n console.error('Download failed:', err);\n }\n setIsOpen(false);\n };\n\n const handleToggle = () => {\n const next = !isOpen;\n setIsOpen(next);\n if (next) {\n setFocusedIndex(0);\n } else {\n setFocusedIndex(-1);\n }\n };\n\n const handleMenuKeyDown = useCallback(\n (event: React.KeyboardEvent) => {\n switch (event.key) {\n case 'ArrowDown':\n event.preventDefault();\n setFocusedIndex(prev => (prev + 1) % totalItems);\n break;\n case 'ArrowUp':\n event.preventDefault();\n setFocusedIndex(prev => (prev - 1 + totalItems) % totalItems);\n break;\n case 'Home':\n event.preventDefault();\n setFocusedIndex(0);\n break;\n case 'End':\n event.preventDefault();\n setFocusedIndex(totalItems - 1);\n break;\n case 'Tab':\n setIsOpen(false);\n setFocusedIndex(-1);\n break;\n }\n },\n [totalItems]\n );\n\n return (\n <div className='relative' ref={dropdownRef}>\n <button\n ref={triggerRef}\n onClick={handleToggle}\n disabled={isPreparingShare}\n className='flex items-center justify-center w-8 h-8 bg-blue-50 hover:bg-blue-100 dark:bg-blue-900/30 dark:hover:bg-blue-900/50 text-blue-600 dark:text-blue-400 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed'\n aria-label='Share this page'\n aria-expanded={isOpen}\n aria-haspopup='menu'\n >\n {isPreparingShare ? (\n <div className='w-4 h-4 border-2 border-blue-600 border-t-transparent rounded-full animate-spin' />\n ) : (\n <svg\n className='w-4 h-4'\n fill='none'\n stroke='currentColor'\n viewBox='0 0 24 24'\n aria-hidden='true'\n >\n <path\n strokeLinecap='round'\n strokeLinejoin='round'\n strokeWidth={2}\n d='M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z'\n />\n </svg>\n )}\n </button>\n\n {isOpen && (\n <div\n className={`absolute right-0 top-10 z-[999999] w-40 ${ui.background.surface} rounded-lg shadow-xl border ${ui.border.default} py-1`}\n role='menu'\n aria-label='Share options'\n onKeyDown={handleMenuKeyDown}\n >\n {sharePlatforms.map((platform, index) => (\n <button\n key={platform.name}\n ref={el => {\n itemRefs.current[index] = el;\n }}\n onClick={() => handleSocialShare(platform.url)}\n className='w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors focus:bg-gray-50 dark:focus:bg-gray-700 focus:outline-none'\n role='menuitem'\n tabIndex={focusedIndex === index ? 0 : -1}\n >\n <span className={`text-sm ${platform.color}`}>\n {platform.name}\n </span>\n </button>\n ))}\n <div\n className={`border-t ${ui.border.default} my-1`}\n role='separator'\n />\n {/* Image sharing options (conditional) */}\n {hasImageShare && supportsWebShare && (\n <button\n ref={el => {\n itemRefs.current[sharePlatforms.length] = el;\n }}\n onClick={handleWebShare}\n className='w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors focus:bg-gray-50 dark:focus:bg-gray-700 focus:outline-none'\n role='menuitem'\n tabIndex={focusedIndex === sharePlatforms.length ? 0 : -1}\n >\n <span className='text-sm text-purple-600 dark:text-purple-400'>\n Share with Image\n </span>\n </button>\n )}\n {hasImageShare && (\n <button\n ref={el => {\n const idx = sharePlatforms.length + (supportsWebShare ? 1 : 0);\n itemRefs.current[idx] = el;\n }}\n onClick={handleDownloadImage}\n className='w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors focus:bg-gray-50 dark:focus:bg-gray-700 focus:outline-none'\n role='menuitem'\n tabIndex={\n focusedIndex ===\n sharePlatforms.length + (supportsWebShare ? 1 : 0)\n ? 0\n : -1\n }\n >\n <span className='text-sm text-green-600 dark:text-green-400'>\n Download Image\n </span>\n </button>\n )}\n {hasImageShare && (\n <div\n className={`border-t ${ui.border.default} my-1`}\n role='separator'\n />\n )}\n <button\n ref={el => {\n itemRefs.current[sharePlatforms.length + extraItemCount] = el;\n }}\n onClick={copyToClipboard}\n className='w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors focus:bg-gray-50 dark:focus:bg-gray-700 focus:outline-none'\n role='menuitem'\n tabIndex={\n focusedIndex === sharePlatforms.length + extraItemCount ? 0 : -1\n }\n >\n <span className={`text-sm ${ui.text.label}`}>\n {showCopiedFeedback ? 'Copied!' : 'Copy Link'}\n </span>\n </button>\n </div>\n )}\n </div>\n );\n};\n\n/**\n * Talk to Founder button - matches share button style\n */\nconst TalkToFounderButton: React.FC<{ config: TalkToFounderConfig }> = ({\n config,\n}) => {\n const IconComponent = config.icon || CalendarDaysIcon;\n const buttonText = config.buttonText || 'Talk to Founder';\n\n return (\n <a\n href={config.meetingUrl}\n target='_blank'\n rel='noopener noreferrer'\n className={cn(\n 'inline-flex items-center gap-1.5 px-2.5 h-8',\n 'text-sm font-medium',\n 'text-blue-600 dark:text-blue-400',\n 'hover:text-blue-700 dark:hover:text-blue-300',\n 'bg-blue-50 dark:bg-blue-900/30',\n 'hover:bg-blue-100 dark:hover:bg-blue-900/50',\n 'rounded-lg',\n 'transition-colors'\n )}\n >\n <IconComponent className='h-4 w-4' />\n <span>{buttonText}</span>\n </a>\n );\n};\n\n/**\n * AppBreadcrumbs - Self-contained breadcrumb navigation with share and \"Talk to Founder\" button.\n *\n * @example\n * ```tsx\n * <AppBreadcrumbs\n * items={[\n * { label: 'Home', href: '/' },\n * { label: 'Products', href: '/products' },\n * { label: 'Widget', current: true },\n * ]}\n * shareConfig={{\n * title: 'Widget Page',\n * description: 'Check out this widget',\n * hashtags: ['widget'],\n * }}\n * talkToFounder={{\n * meetingUrl: 'https://calendly.com/founder',\n * }}\n * variant=\"default\"\n * />\n * ```\n */\nexport const AppBreadcrumbs: React.FC<AppBreadcrumbsProps> = ({\n items,\n shareConfig,\n talkToFounder,\n variant = 'default',\n className,\n contentClassName,\n}) => {\n // Don't render if no items\n if (!items || items.length === 0) {\n return null;\n }\n\n return (\n <div className={cn(breadcrumbContainerVariants({ variant }), className)}>\n <div className={cn('max-w-7xl mx-auto px-4 py-2', contentClassName)}>\n <div className='flex items-center justify-between'>\n {/* Breadcrumb trail */}\n <nav aria-label='Breadcrumb'>\n <ol className='flex items-center text-sm space-x-2'>\n {items.map((item, index) => (\n <React.Fragment key={index}>\n <li>\n {item.current || !item.href ? (\n <span className={ui.text.body}>{item.label}</span>\n ) : (\n <a\n href={item.href}\n className={`${ui.text.linkSubtle} transition-colors`}\n >\n {item.label}\n </a>\n )}\n </li>\n {index < items.length - 1 && (\n <li>\n <span className={ui.text.muted}>/</span>\n </li>\n )}\n </React.Fragment>\n ))}\n </ol>\n </nav>\n\n {/* Right side: Talk to Founder + Share */}\n <div className='flex items-center gap-2'>\n {talkToFounder && <TalkToFounderButton config={talkToFounder} />}\n {shareConfig && <ShareDropdown shareConfig={shareConfig} />}\n </div>\n </div>\n </div>\n </div>\n );\n};\n\nexport default AppBreadcrumbs;\n","import { type ComponentType } from 'react';\nimport type { LinkComponentProps } from '../../types';\n\n/**\n * Default link component that renders a plain anchor.\n * Shared between AppFooter and AppFooterForHomePage.\n */\nexport const DefaultLinkComponent: ComponentType<LinkComponentProps> = ({\n href,\n className,\n children,\n onClick,\n}) => (\n <a href={href} className={className} onClick={onClick}>\n {children}\n </a>\n);\n\n/**\n * Helper to get copyright year or range.\n * Shared between AppFooter and AppFooterForHomePage.\n *\n * @param startYear - The starting year for the copyright range (default: 2025)\n * @returns A string representing the year or year range\n */\nexport function getCopyrightYear(startYear = 2025): string {\n const currentYear = new Date().getFullYear();\n if (currentYear === startYear) {\n return String(startYear);\n } else if (currentYear > startYear) {\n return `${startYear}-${currentYear}`;\n }\n return String(startYear);\n}\n","import React, { useCallback, type ComponentType } from 'react';\nimport {\n Footer as FooterContainer,\n FooterCompact,\n FooterCompactLeft,\n FooterCompactRight,\n FooterVersion,\n FooterCopyright,\n} from '@sudobility/components';\nimport { ui } from '@sudobility/design';\nimport { cn } from '../../utils';\nimport type {\n StatusIndicatorConfig,\n LinkComponentProps,\n FooterLinkItem,\n AnalyticsTrackingParams,\n} from '../../types';\nimport { DefaultLinkComponent, getCopyrightYear } from './shared';\n\n/**\n * Props for the SystemStatusIndicator component from @sudobility/devops-components.\n */\nexport interface SystemStatusIndicatorProps {\n statusPageUrl: string;\n apiEndpoint?: string;\n refreshInterval?: number;\n size?: 'sm' | 'md' | 'lg';\n version?: string;\n isNetworkOnline?: boolean;\n}\n\nexport interface AppFooterProps {\n /** App version string */\n version?: string;\n\n /** Copyright year or range (e.g., \"2025\" or \"2025-2026\") */\n copyrightYear?: string;\n\n /** Company name */\n companyName: string;\n\n /** Company URL (optional - creates a link if provided) */\n companyUrl?: string;\n\n /** Rights text (e.g., \"All rights reserved\") */\n rightsText?: string;\n\n /** Status indicator config (optional) */\n statusIndicator?: StatusIndicatorConfig;\n\n /**\n * SystemStatusIndicator component from @sudobility/devops-components.\n * Pass this to enable status indicator functionality.\n */\n StatusIndicatorComponent?: ComponentType<SystemStatusIndicatorProps>;\n\n /** Right-side links (e.g., Privacy, Terms) */\n links?: FooterLinkItem[];\n\n /** Custom Link component */\n LinkComponent?: ComponentType<LinkComponentProps>;\n\n /** Sticky positioning (sticks to bottom of viewport) */\n sticky?: boolean;\n\n /** Network online status (for status indicator) */\n isNetworkOnline?: boolean;\n\n /** Custom className */\n className?: string;\n\n /** Optional analytics tracking callback */\n onTrack?: (params: AnalyticsTrackingParams) => void;\n}\n\n/**\n * AppFooter - Compact footer for app pages.\n *\n * Features:\n * - Version display\n * - Copyright with company name\n * - System status indicator (optional)\n * - Right-side links (Privacy, Terms, etc.)\n * - Sticky positioning option\n * - Dark mode support\n *\n * @example\n * ```tsx\n * import { SystemStatusIndicator } from '@sudobility/devops-components';\n *\n * <AppFooter\n * version=\"1.0.0\"\n * companyName=\"Sudobility Inc.\"\n * companyUrl=\"/\"\n * rightsText=\"All rights reserved\"\n * statusIndicator={{\n * statusPageUrl: 'https://status.example.com',\n * apiEndpoint: 'https://status.example.com/api/v1/status',\n * }}\n * StatusIndicatorComponent={SystemStatusIndicator}\n * links={[\n * { label: 'Privacy', href: '/privacy' },\n * { label: 'Terms', href: '/terms' },\n * ]}\n * sticky\n * />\n * ```\n */\nexport const AppFooter: React.FC<AppFooterProps> = ({\n version,\n copyrightYear,\n companyName,\n companyUrl,\n rightsText = 'All rights reserved',\n statusIndicator,\n StatusIndicatorComponent,\n links = [],\n LinkComponent = DefaultLinkComponent,\n sticky = true,\n isNetworkOnline = true,\n className,\n onTrack,\n}) => {\n const year = copyrightYear || getCopyrightYear();\n\n // Helper to track analytics events\n const track = useCallback(\n (label: string, params?: Record<string, unknown>) => {\n onTrack?.({\n eventType: 'link_click',\n componentName: 'AppFooter',\n label,\n params,\n });\n },\n [onTrack]\n );\n\n // Create a tracked link click handler\n const createTrackedLinkHandler = useCallback(\n (\n linkLabel: string,\n linkHref: string,\n originalOnClick?: (e: React.MouseEvent) => void\n ) =>\n (e: React.MouseEvent) => {\n track('footer_link_clicked', {\n link_label: linkLabel,\n link_href: linkHref,\n });\n originalOnClick?.(e);\n },\n [track]\n );\n\n const companyLink = companyUrl ? (\n <LinkComponent\n href={companyUrl}\n className={cn(ui.text.linkSubtle, ui.transition.default)}\n >\n {companyName}\n </LinkComponent>\n ) : undefined;\n\n return (\n <FooterContainer\n variant='compact'\n sticky={sticky}\n className={cn(className)}\n >\n <FooterCompact>\n <FooterCompactLeft>\n {version && <FooterVersion version={version} />}\n <FooterCopyright\n year={year}\n companyName={companyName}\n rightsText={rightsText}\n companyLink={companyLink}\n />\n {statusIndicator && StatusIndicatorComponent && (\n <StatusIndicatorComponent\n statusPageUrl={statusIndicator.statusPageUrl}\n apiEndpoint={statusIndicator.apiEndpoint}\n refreshInterval={statusIndicator.refreshInterval || 60000}\n size='sm'\n version={version}\n isNetworkOnline={isNetworkOnline}\n />\n )}\n </FooterCompactLeft>\n <FooterCompactRight>\n {links.map((link, index) => (\n <React.Fragment key={link.href || index}>\n {link.onClick ? (\n <button\n onClick={createTrackedLinkHandler(\n link.label,\n link.href,\n link.onClick\n )}\n className={cn(ui.text.linkMuted, ui.transition.default)}\n >\n {link.label}\n </button>\n ) : (\n <LinkComponent\n href={link.href}\n onClick={createTrackedLinkHandler(link.label, link.href)}\n className={cn(ui.text.linkMuted, ui.transition.default)}\n >\n {link.label}\n </LinkComponent>\n )}\n </React.Fragment>\n ))}\n </FooterCompactRight>\n </FooterCompact>\n </FooterContainer>\n );\n};\n\nexport default AppFooter;\n","import React, { useCallback, type ComponentType } from 'react';\nimport {\n Footer as FooterContainer,\n FooterSocialLinks,\n} from '@sudobility/components';\nimport { cn } from '../../utils';\nimport type {\n StatusIndicatorConfig,\n LinkComponentProps,\n FooterLinkSection as FooterLinkSectionConfig,\n SocialLinksConfig,\n AnalyticsTrackingParams,\n} from '../../types';\nimport type { SystemStatusIndicatorProps } from './app-footer';\nimport { DefaultLinkComponent, getCopyrightYear } from './shared';\n\nexport interface AppFooterForHomePageProps {\n /** App logo configuration */\n logo: {\n /** Logo image src (optional - if not provided, uses Logo component) */\n src?: string;\n /** App name */\n appName: string;\n };\n\n /** Footer link sections displayed as horizontal rows */\n linkSections: FooterLinkSectionConfig[];\n\n /** Social media links */\n socialLinks?: SocialLinksConfig;\n\n /** System status indicator configuration */\n statusIndicator?: StatusIndicatorConfig;\n\n /**\n * SystemStatusIndicator component from @sudobility/devops-components.\n * Pass this to enable status indicator functionality.\n */\n StatusIndicatorComponent?: ComponentType<SystemStatusIndicatorProps>;\n\n /** App version string */\n version?: string;\n\n /** Copyright year or range */\n copyrightYear?: string;\n\n /** Company name for copyright */\n companyName: string;\n\n /** Company link URL (optional) */\n companyUrl?: string;\n\n /** Footer description text (tagline below logo) */\n description?: string;\n\n /** Rights text (e.g., \"All rights reserved\") */\n rightsText?: string;\n\n /** Custom Link component */\n LinkComponent?: ComponentType<LinkComponentProps>;\n\n /** Network online status (for status indicator) */\n isNetworkOnline?: boolean;\n\n /** Custom className */\n className?: string;\n\n /** Optional analytics tracking callback */\n onTrack?: (params: AnalyticsTrackingParams) => void;\n}\n\n/**\n * AppFooterForHomePage - Full footer for home/landing pages.\n *\n * Displays link sections as horizontal rows with section title in bold,\n * followed by links that wrap to additional lines as needed.\n * Below the sitemap, shows app name, tagline, version, and copyright\n * on a single wrapping line.\n *\n * @example\n * ```tsx\n * <AppFooterForHomePage\n * logo={{ appName: 'My App' }}\n * linkSections={[\n * {\n * title: 'Product',\n * links: [\n * { label: 'Features', href: '/features' },\n * { label: 'Pricing', href: '/pricing' },\n * ],\n * },\n * ]}\n * version=\"1.0.0\"\n * companyName=\"Sudobility Inc.\"\n * description=\"Building the future\"\n * />\n * ```\n */\nexport const AppFooterForHomePage: React.FC<AppFooterForHomePageProps> = ({\n logo,\n linkSections,\n socialLinks,\n statusIndicator,\n StatusIndicatorComponent,\n version,\n copyrightYear,\n companyName,\n companyUrl,\n description,\n rightsText = 'All rights reserved',\n LinkComponent = DefaultLinkComponent,\n isNetworkOnline = true,\n className,\n onTrack,\n}) => {\n const year = copyrightYear || getCopyrightYear();\n\n const track = useCallback(\n (label: string, params?: Record<string, unknown>) => {\n onTrack?.({\n eventType: 'link_click',\n componentName: 'AppFooterForHomePage',\n label,\n params,\n });\n },\n [onTrack]\n );\n\n const createTrackedLinkHandler = useCallback(\n (\n linkLabel: string,\n linkHref: string,\n sectionTitle: string,\n originalOnClick?: (e: React.MouseEvent) => void\n ) =>\n (e: React.MouseEvent) => {\n track('footer_link_clicked', {\n link_label: linkLabel,\n link_href: linkHref,\n section_title: sectionTitle,\n });\n originalOnClick?.(e);\n },\n [track]\n );\n\n return (\n <FooterContainer variant='full' className={cn(className)}>\n <nav\n role='navigation'\n aria-label='Footer Navigation'\n className='space-y-1'\n >\n {linkSections.map((section, sectionIndex) => (\n <div\n key={section.title || sectionIndex}\n className='flex flex-wrap items-baseline gap-y-0.5'\n >\n <span className='font-bold text-xs text-gray-300 mr-2'>\n {section.title}\n </span>\n {section.links.map((link, linkIndex) => (\n <React.Fragment key={link.href || linkIndex}>\n {linkIndex > 0 && (\n <span className='text-gray-600 mx-1.5'>·</span>\n )}\n {link.onClick ? (\n <button\n onClick={createTrackedLinkHandler(\n link.label,\n link.href,\n section.title,\n link.onClick\n )}\n className='text-xs text-gray-400 hover:text-white transition-colors'\n >\n {link.label}\n </button>\n ) : (\n <LinkComponent\n href={link.href}\n onClick={createTrackedLinkHandler(\n link.label,\n link.href,\n section.title\n )}\n className='text-xs text-gray-400 hover:text-white transition-colors'\n >\n {link.label}\n </LinkComponent>\n )}\n </React.Fragment>\n ))}\n </div>\n ))}\n </nav>\n\n <div className='border-t border-gray-700 mt-4 pt-3'>\n <div className='flex flex-wrap items-center justify-center gap-x-3 gap-y-0.5 text-xs text-gray-400'>\n <span className='font-semibold text-gray-200'>{logo.appName}</span>\n {description && (\n <>\n <span className='text-gray-600'>·</span>\n <span>{description}</span>\n </>\n )}\n {version && (\n <>\n <span className='text-gray-600'>·</span>\n <span>v{version}</span>\n </>\n )}\n <span className='text-gray-600'>·</span>\n <span>\n © {year}{' '}\n {companyUrl ? (\n <LinkComponent\n href={companyUrl}\n className='text-gray-400 hover:text-white transition-colors'\n >\n {companyName}\n </LinkComponent>\n ) : (\n companyName\n )}\n . {rightsText}\n </span>\n {statusIndicator && StatusIndicatorComponent && (\n <>\n <span className='text-gray-600'>·</span>\n <StatusIndicatorComponent\n statusPageUrl={statusIndicator.statusPageUrl}\n apiEndpoint={statusIndicator.apiEndpoint}\n refreshInterval={statusIndicator.refreshInterval || 60000}\n size='sm'\n version={version}\n isNetworkOnline={isNetworkOnline}\n />\n </>\n )}\n </div>\n </div>\n\n {socialLinks && (\n <div className='flex justify-center mt-3'>\n <FooterSocialLinks\n twitterUrl={socialLinks.twitterUrl}\n discordUrl={socialLinks.discordUrl}\n linkedinUrl={socialLinks.linkedinUrl}\n githubUrl={socialLinks.githubUrl}\n redditUrl={socialLinks.redditUrl}\n farcasterUrl={socialLinks.farcasterUrl}\n telegramUrl={socialLinks.telegramUrl}\n />\n </div>\n )}\n </FooterContainer>\n );\n};\n\nexport default AppFooterForHomePage;\n","import React, { type ReactNode } from 'react';\nimport { LayoutProvider, AspectFitView } from '@sudobility/components';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils';\nimport { ui } from '@sudobility/design';\nimport {\n AppBreadcrumbs,\n type AppBreadcrumbsProps,\n} from '../breadcrumbs/app-breadcrumbs';\nimport { AppTopBar, type AppTopBarProps } from '../topbar/app-topbar';\nimport {\n AppTopBarWithFirebaseAuth,\n type AppTopBarWithFirebaseAuthProps,\n} from '../topbar/app-topbar-with-firebase-auth';\nimport {\n AppTopBarWithWallet,\n type AppTopBarWithWalletProps,\n} from '../topbar/app-topbar-with-wallet';\nimport { AppFooter, type AppFooterProps } from '../footer/app-footer';\nimport {\n AppFooterForHomePage,\n type AppFooterForHomePageProps,\n} from '../footer/app-footer-for-home-page';\nimport type { MaxWidth, ContentPadding, BackgroundVariant } from '../../types';\n\nconst layoutVariants = cva('flex flex-col', {\n variants: {\n background: {\n default: ui.background.subtle,\n white: 'bg-white dark:bg-gray-900',\n gradient:\n 'bg-gradient-to-br from-gray-50 to-blue-50 dark:from-gray-900 dark:to-gray-800',\n },\n },\n defaultVariants: {\n background: 'default',\n },\n});\n\nconst maxWidthClasses: Record<MaxWidth, string> = {\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n xl: 'max-w-xl',\n '2xl': 'max-w-2xl',\n '4xl': 'max-w-4xl',\n '7xl': 'max-w-7xl',\n full: 'max-w-full',\n};\n\nconst paddingClasses: Record<ContentPadding, string> = {\n none: '',\n sm: 'px-4 sm:px-6 py-6',\n md: 'px-4 py-8',\n lg: 'px-4 py-12',\n};\n\n/** Discriminated union for selecting which TopBar component to render. */\nexport type TopBarConfig =\n | ({ variant: 'base'; topBarVariant?: 'default' | 'app' } & Omit<\n AppTopBarProps,\n 'variant'\n >)\n | ({ variant: 'firebase'; topBarVariant?: 'default' | 'app' } & Omit<\n AppTopBarWithFirebaseAuthProps,\n 'variant'\n >)\n | ({ variant: 'wallet'; topBarVariant?: 'default' | 'app' } & Omit<\n AppTopBarWithWalletProps,\n 'variant'\n >);\n\n/** Discriminated union for selecting which Footer component to render. */\nexport type FooterConfig =\n | ({ variant: 'compact' } & AppFooterProps)\n | ({ variant: 'full' } & AppFooterForHomePageProps);\n\nfunction renderTopBar(config: TopBarConfig): ReactNode {\n const { variant, topBarVariant, ...rest } = config;\n switch (variant) {\n case 'base':\n return (\n <AppTopBar\n variant={topBarVariant}\n {...(rest as Omit<AppTopBarProps, 'variant'>)}\n />\n );\n case 'firebase':\n return (\n <AppTopBarWithFirebaseAuth\n variant={topBarVariant}\n {...(rest as Omit<AppTopBarWithFirebaseAuthProps, 'variant'>)}\n />\n );\n case 'wallet':\n return (\n <AppTopBarWithWallet\n variant={topBarVariant}\n {...(rest as Omit<AppTopBarWithWalletProps, 'variant'>)}\n />\n );\n }\n}\n\nfunction renderFooter(config: FooterConfig): ReactNode {\n const { variant, ...rest } = config;\n switch (variant) {\n case 'compact':\n return <AppFooter {...(rest as AppFooterProps)} />;\n case 'full':\n return <AppFooterForHomePage {...(rest as AppFooterForHomePageProps)} />;\n }\n}\n\n/** Page-level layout and styling options. */\nexport interface AppPageProps {\n /** Max width for content area (default: '7xl') */\n maxWidth?: MaxWidth;\n\n /** Content padding (default: 'md') */\n contentPadding?: ContentPadding;\n\n /** Background variant */\n background?: BackgroundVariant;\n\n /** Layout mode for LayoutProvider */\n layoutMode?: 'standard';\n\n /** Custom className for the layout container */\n className?: string;\n\n /** Custom className for the content area */\n contentClassName?: string;\n\n /** Custom className for the main element */\n mainClassName?: string;\n\n /** Whether the content area should be scrollable in sticky layout mode (default: true).\n * Set to false for pages with MasterDetailLayout where panels handle their own scrolling. */\n scrollable?: boolean;\n\n /** Optional aspect ratio (width / height) for content area. When set, children are placed inside a container with fixed aspect ratio using AspectFit behavior. */\n aspectRatio?: number;\n}\n\nexport interface AppPageLayoutProps {\n /** Page content */\n children: ReactNode;\n\n /** TopBar configuration - selects which TopBar component to render */\n topBar: TopBarConfig;\n\n /** Breadcrumbs configuration (optional) */\n breadcrumbs?: AppBreadcrumbsProps;\n\n /** Footer configuration - selects which Footer component to render */\n footer?: FooterConfig;\n\n /** Page-level layout and styling options */\n page?: AppPageProps;\n}\n\n/**\n * AppPageLayout - Layout wrapper combining TopBar, Breadcrumbs, Content, and Footer.\n *\n * Features:\n * - Props-based TopBar and Footer via discriminated unions\n * - Optional breadcrumbs with share and \"Talk to Founder\"\n * - Configurable content max-width and padding\n * - Background variants\n * - Dark mode support\n * - Compact footer sticks to the bottom while content scrolls independently\n * - Full footer scrolls with content (no sticky behavior)\n *\n * @example\n * ```tsx\n * <AppPageLayout\n * topBar={{\n * variant: 'firebase',\n * logo: { src: '/logo.png', appName: 'My App' },\n * menuItems: menuItems,\n * AuthActionComponent: AuthAction,\n * onLoginClick: () => navigate('/login'),\n * }}\n * breadcrumbs={{\n * items: breadcrumbItems,\n * shareConfig: { title: 'Page', description: 'Description', hashtags: [] },\n * }}\n * footer={{\n * variant: 'compact',\n * version: '1.0.0',\n * companyName: 'My Company',\n * links: [{ label: 'Privacy', href: '/privacy' }],\n * }}\n * page={{ maxWidth: '7xl', background: 'default' }}\n * >\n * <h1>Page Content</h1>\n * </AppPageLayout>\n * ```\n */\nexport const AppPageLayout: React.FC<AppPageLayoutProps> = ({\n children,\n topBar,\n breadcrumbs,\n footer,\n page,\n}) => {\n const {\n maxWidth = '7xl',\n contentPadding = 'md',\n background = 'default',\n layoutMode = 'standard',\n className,\n contentClassName,\n mainClassName,\n scrollable = true,\n aspectRatio,\n } = page ?? {};\n const isCompactFooter = footer?.variant === 'compact';\n // Compact footer: viewport-locked layout with internal scrolling\n // Full footer: natural page scrolling so footer scrolls with content\n const stickyLayout = !footer || isCompactFooter;\n const content = aspectRatio ? (\n <AspectFitView aspectRatio={aspectRatio}>{children}</AspectFitView>\n ) : (\n children\n );\n\n return (\n <LayoutProvider mode={layoutMode}>\n <div\n className={cn(\n layoutVariants({ background }),\n stickyLayout ? 'h-screen overflow-hidden' : 'min-h-screen',\n className\n )}\n >\n {/* Header Section */}\n <header>{renderTopBar(topBar)}</header>\n\n {/* Breadcrumb Section */}\n {breadcrumbs && breadcrumbs.items && breadcrumbs.items.length > 0 && (\n <AppBreadcrumbs {...breadcrumbs} />\n )}\n\n {/* Main Content */}\n <main\n className={cn(\n 'flex-1',\n stickyLayout && 'flex flex-col overflow-hidden',\n mainClassName\n )}\n >\n <div\n className={cn(\n 'mx-auto',\n maxWidthClasses[maxWidth],\n paddingClasses[contentPadding],\n stickyLayout &&\n (scrollable\n ? 'flex-1 min-h-0 overflow-auto'\n : 'flex-1 min-h-0 overflow-hidden flex flex-col'),\n contentClassName\n )}\n >\n {content}\n </div>\n </main>\n\n {/* Footer */}\n {footer && (\n <footer\n className={isCompactFooter ? 'sticky bottom-0 z-10' : undefined}\n >\n {renderFooter(footer)}\n </footer>\n )}\n </div>\n </LayoutProvider>\n );\n};\n\nexport default AppPageLayout;\n","import React from 'react';\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n Label,\n} from '@sudobility/components';\nimport { textVariants, colors, ui } from '@sudobility/design';\n\n/**\n * Theme options for appearance settings.\n */\nexport enum Theme {\n LIGHT = 'light',\n DARK = 'dark',\n SYSTEM = 'system',\n}\n\n/**\n * Font size options for appearance settings.\n */\nexport enum FontSize {\n SMALL = 'small',\n MEDIUM = 'medium',\n LARGE = 'large',\n}\n\n/**\n * Translation keys used by AppearanceSettings.\n * Provide a translation function to customize labels.\n */\nexport interface AppearanceSettingsTranslations {\n heading: string;\n description: string;\n themeLabel: string;\n themeSelectPlaceholder: string;\n themeLight: string;\n themeDark: string;\n themeSystem: string;\n themeDescription: string;\n fontSizeLabel: string;\n fontSizeSelectPlaceholder: string;\n fontSizeSmall: string;\n fontSizeMedium: string;\n fontSizeLarge: string;\n fontSizeDescription: string;\n infoHeading: string;\n infoDescription: string;\n}\n\nconst defaultTranslations: AppearanceSettingsTranslations = {\n heading: 'Appearance',\n description: 'Customize the look and feel of the application.',\n themeLabel: 'Theme',\n themeSelectPlaceholder: 'Select theme',\n themeLight: 'Light',\n themeDark: 'Dark',\n themeSystem: 'System',\n themeDescription: 'Choose your preferred color theme.',\n fontSizeLabel: 'Font Size',\n fontSizeSelectPlaceholder: 'Select font size',\n fontSizeSmall: 'Small',\n fontSizeMedium: 'Medium',\n fontSizeLarge: 'Large',\n fontSizeDescription: 'Adjust the text size for better readability.',\n infoHeading: 'About Settings',\n infoDescription:\n 'Your appearance preferences are saved locally and will be applied automatically on your next visit.',\n};\n\nexport interface AppearanceSettingsProps {\n /** Current theme value */\n theme: Theme | string;\n\n /** Current font size value */\n fontSize: FontSize | string;\n\n /** Callback when theme changes */\n onThemeChange: (theme: Theme) => void;\n\n /** Callback when font size changes */\n onFontSizeChange: (fontSize: FontSize) => void;\n\n /**\n * Optional translation function.\n * If provided, will be called with a key from AppearanceSettingsTranslations.\n * Falls back to default English strings if not provided.\n */\n t?: (key: string, fallback?: string) => string;\n\n /** Optional className for the container */\n className?: string;\n\n /** Whether to show the information box at the bottom */\n showInfoBox?: boolean;\n}\n\n/**\n * AppearanceSettings - A reusable component for theme and font size settings.\n *\n * This component can be used across different apps to provide consistent\n * appearance customization options.\n *\n * @example\n * ```tsx\n * // Basic usage with useTheme hook\n * const { theme, fontSize, setTheme, setFontSize } = useTheme();\n *\n * <AppearanceSettings\n * theme={theme}\n * fontSize={fontSize}\n * onThemeChange={setTheme}\n * onFontSizeChange={setFontSize}\n * />\n *\n * // With i18n translation\n * const { t } = useTranslation('settings');\n *\n * <AppearanceSettings\n * theme={theme}\n * fontSize={fontSize}\n * onThemeChange={setTheme}\n * onFontSizeChange={setFontSize}\n * t={(key, fallback) => t(`appearance.${key}`, fallback)}\n * />\n * ```\n */\nexport const AppearanceSettings: React.FC<AppearanceSettingsProps> = ({\n theme,\n fontSize,\n onThemeChange,\n onFontSizeChange,\n t,\n className,\n showInfoBox = true,\n}) => {\n // Helper to get translated string with fallback\n const getText = (key: keyof AppearanceSettingsTranslations): string => {\n const fallback = defaultTranslations[key];\n return t ? t(key, fallback) : fallback;\n };\n\n return (\n <div className={className}>\n <div className='space-y-6'>\n <div>\n <h2 className={`${textVariants.heading.h4()} mb-2`}>\n {getText('heading')}\n </h2>\n <p className={textVariants.body.sm()}>{getText('description')}</p>\n </div>\n\n <div className='space-y-6'>\n {/* Theme Setting */}\n <div className='space-y-2'>\n <Label\n htmlFor='theme-select'\n className={textVariants.label.default()}\n >\n {getText('themeLabel')}\n </Label>\n <Select\n value={theme}\n onValueChange={(value: string) => onThemeChange(value as Theme)}\n >\n <SelectTrigger id='theme-select'>\n <SelectValue placeholder={getText('themeSelectPlaceholder')} />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={Theme.LIGHT}>\n {getText('themeLight')}\n </SelectItem>\n <SelectItem value={Theme.DARK}>\n {getText('themeDark')}\n </SelectItem>\n <SelectItem value={Theme.SYSTEM}>\n {getText('themeSystem')}\n </SelectItem>\n </SelectContent>\n </Select>\n <p className={textVariants.body.xs()}>\n {getText('themeDescription')}\n </p>\n </div>\n\n {/* Font Size Setting */}\n <div className='space-y-2'>\n <Label\n htmlFor='font-size-select'\n className={textVariants.label.default()}\n >\n {getText('fontSizeLabel')}\n </Label>\n <Select\n value={fontSize}\n onValueChange={(value: string) =>\n onFontSizeChange(value as FontSize)\n }\n >\n <SelectTrigger id='font-size-select'>\n <SelectValue\n placeholder={getText('fontSizeSelectPlaceholder')}\n />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={FontSize.SMALL}>\n {getText('fontSizeSmall')}\n </SelectItem>\n <SelectItem value={FontSize.MEDIUM}>\n {getText('fontSizeMedium')}\n </SelectItem>\n <SelectItem value={FontSize.LARGE}>\n {getText('fontSizeLarge')}\n </SelectItem>\n </SelectContent>\n </Select>\n <p className={textVariants.body.xs()}>\n {getText('fontSizeDescription')}\n </p>\n </div>\n </div>\n\n {/* Information Box */}\n {showInfoBox && (\n <div\n className={`${colors.component.alert.info.base} ${colors.component.alert.info.dark} rounded-lg p-4 border`}\n >\n <h4 className={`${ui.text.info} text-sm mb-2`}>\n {getText('infoHeading')}\n </h4>\n <p className={`${ui.text.info} text-sm font-normal`}>\n {getText('infoDescription')}\n </p>\n </div>\n )}\n </div>\n </div>\n );\n};\n\nexport default AppearanceSettings;\n","/**\n * @fileoverview Global Settings Page\n * @description Reusable settings page with sidebar navigation.\n *\n * The consuming page is responsible for page-level layout (width constraints,\n * padding, scrollable behavior) — e.g. via useSetPageConfig or a Section wrapper.\n */\n\nimport React, {\n useState,\n useMemo,\n useCallback,\n type ReactNode,\n type ComponentType,\n} from 'react';\nimport { PaintBrushIcon } from '@heroicons/react/24/outline';\nimport { MasterDetailLayout, MasterListItem } from '@sudobility/components';\nimport { AppearanceSettings } from './appearance-settings';\nimport { Theme, FontSize } from './appearance-settings';\nimport type { AnalyticsTrackingParams } from '../../types';\n\n/**\n * Configuration for a settings section in the navigation.\n */\nexport interface SettingsSectionConfig {\n /** Unique identifier for the section */\n id: string;\n /** Icon component to display */\n icon: ComponentType<{ className?: string }>;\n /** Display label */\n label: string;\n /** Short description shown below label */\n description: string;\n /** The content to render when this section is selected */\n content: ReactNode;\n}\n\n/**\n * Translation keys used by GlobalSettingsPage.\n */\nexport interface GlobalSettingsPageTranslations {\n title: string;\n backButton: string;\n appearanceLabel: string;\n appearanceDescription: string;\n}\n\nconst defaultTranslations: GlobalSettingsPageTranslations = {\n title: 'Settings',\n backButton: 'Back',\n appearanceLabel: 'Appearance',\n appearanceDescription: 'Theme and font size settings',\n};\n\nexport interface GlobalSettingsPageProps {\n /** Current theme value */\n theme: Theme | string;\n\n /** Current font size value */\n fontSize: FontSize | string;\n\n /** Callback when theme changes */\n onThemeChange: (theme: Theme) => void;\n\n /** Callback when font size changes */\n onFontSizeChange: (fontSize: FontSize) => void;\n\n /**\n * Additional settings sections to display after Appearance.\n * Each section needs an id, icon, label, description, and content.\n */\n additionalSections?: SettingsSectionConfig[];\n\n /**\n * Optional translation function.\n * Falls back to default English strings if not provided.\n */\n t?: (key: string, fallback?: string) => string;\n\n /**\n * Translation function for AppearanceSettings.\n * If provided, will be passed to AppearanceSettings component.\n */\n appearanceT?: (key: string, fallback?: string) => string;\n\n /** Optional className for the container */\n className?: string;\n\n /** Whether to show the info box in appearance settings */\n showAppearanceInfoBox?: boolean;\n\n /** Optional analytics tracking callback */\n onTrack?: (params: AnalyticsTrackingParams) => void;\n}\n\n/**\n * GlobalSettingsPage - A reusable settings page with master-detail layout.\n *\n * Features:\n * - Appearance settings built-in as the first section\n * - Extensible via additionalSections prop\n * - Responsive master-detail layout\n * - Mobile-friendly with back navigation\n *\n * @example\n * ```tsx\n * // Basic usage\n * <GlobalSettingsPage\n * theme={theme}\n * fontSize={fontSize}\n * onThemeChange={setTheme}\n * onFontSizeChange={setFontSize}\n * />\n *\n * // With additional sections\n * <GlobalSettingsPage\n * theme={theme}\n * fontSize={fontSize}\n * onThemeChange={setTheme}\n * onFontSizeChange={setFontSize}\n * additionalSections={[\n * {\n * id: 'notifications',\n * icon: BellIcon,\n * label: 'Notifications',\n * description: 'Manage notification preferences',\n * content: <NotificationSettings />,\n * },\n * ]}\n * />\n * ```\n */\nexport const GlobalSettingsPage: React.FC<GlobalSettingsPageProps> = ({\n theme,\n fontSize,\n onThemeChange,\n onFontSizeChange,\n additionalSections = [],\n t,\n appearanceT,\n showAppearanceInfoBox = true,\n onTrack,\n}) => {\n // Development-only warnings for common misconfigurations\n if (process.env.NODE_ENV !== 'production') {\n const ids = additionalSections.map(s => s.id);\n const duplicateIds = ids.filter((id, i) => ids.indexOf(id) !== i);\n if (duplicateIds.length > 0) {\n console.warn(\n `[GlobalSettingsPage] Duplicate section IDs found: ${duplicateIds.join(', ')}. ` +\n 'Each section must have a unique id.'\n );\n }\n if (ids.includes('appearance')) {\n console.warn(\n '[GlobalSettingsPage] additionalSections contains a section with id \"appearance\" which conflicts with the built-in Appearance section. ' +\n 'Use a different id to avoid unexpected behavior.'\n );\n }\n }\n const [selectedSection, setSelectedSection] = useState('appearance');\n const [mobileView, setMobileView] = useState<'navigation' | 'content'>(\n 'navigation'\n );\n\n // Helper to track analytics events\n const track = useCallback(\n (label: string, params?: Record<string, unknown>) => {\n onTrack?.({\n eventType: 'settings_change',\n componentName: 'GlobalSettingsPage',\n label,\n params,\n });\n },\n [onTrack]\n );\n\n // Wrapped handlers with tracking\n const handleThemeChange = useCallback(\n (newTheme: Theme) => {\n track('theme_changed', { theme: newTheme });\n onThemeChange(newTheme);\n },\n [track, onThemeChange]\n );\n\n const handleFontSizeChange = useCallback(\n (newFontSize: FontSize) => {\n track('font_size_changed', { font_size: newFontSize });\n onFontSizeChange(newFontSize);\n },\n [track, onFontSizeChange]\n );\n\n // Helper to get translated string with fallback\n const getText = useCallback(\n (key: keyof GlobalSettingsPageTranslations): string => {\n const fallback = defaultTranslations[key];\n return t ? t(key, fallback) : fallback;\n },\n [t]\n );\n\n // Build all sections with appearance first\n const allSections: SettingsSectionConfig[] = useMemo(\n () => [\n {\n id: 'appearance',\n icon: PaintBrushIcon,\n label: getText('appearanceLabel'),\n description: getText('appearanceDescription'),\n content: (\n <AppearanceSettings\n theme={theme}\n fontSize={fontSize}\n onThemeChange={handleThemeChange}\n onFontSizeChange={handleFontSizeChange}\n t={appearanceT}\n showInfoBox={showAppearanceInfoBox}\n />\n ),\n },\n ...additionalSections,\n ],\n [\n additionalSections,\n getText,\n theme,\n fontSize,\n handleThemeChange,\n handleFontSizeChange,\n appearanceT,\n showAppearanceInfoBox,\n ]\n );\n\n const currentSection =\n allSections.find(s => s.id === selectedSection) || allSections[0];\n\n const handleSectionSelect = (sectionId: string) => {\n track('section_selected', { section_id: sectionId });\n setSelectedSection(sectionId);\n setMobileView('content');\n };\n\n const handleBackToNavigation = () => {\n track('back_to_navigation');\n setMobileView('navigation');\n };\n\n // Navigation list using MasterListItem\n const navigationList = (\n <div>\n {allSections.map(section => (\n <MasterListItem\n key={section.id}\n isSelected={selectedSection === section.id}\n onClick={() => handleSectionSelect(section.id)}\n icon={section.icon}\n label={section.label}\n description={section.description}\n />\n ))}\n </div>\n );\n\n return (\n <MasterDetailLayout\n masterTitle={getText('title')}\n backButtonText={getText('backButton')}\n masterContent={navigationList}\n detailContent={currentSection.content}\n detailTitle={currentSection.label}\n mobileView={mobileView}\n onBackToNavigation={handleBackToNavigation}\n masterWidth={280}\n stickyMaster={true}\n enableAnimations={true}\n />\n );\n};\n\nexport default GlobalSettingsPage;\n","/**\n * @fileoverview App Sitemap Page\n * @description Reusable sitemap page component with categorized links.\n *\n * This component uses Section internally for proper page layout.\n * Do NOT wrap this component in a Section when consuming it.\n */\n\nimport React, { type ComponentType, type ReactNode } from 'react';\nimport {\n ChevronRightIcon,\n HomeIcon,\n DocumentTextIcon,\n EnvelopeIcon,\n CogIcon,\n LanguageIcon,\n} from '@heroicons/react/24/outline';\nimport { Section } from '@sudobility/components';\nimport { cn } from '../../utils';\nimport { ui, colors, buttonVariant } from '@sudobility/design';\nimport type { LinkComponentProps } from '../../types';\n\n/**\n * Configuration for a single sitemap link\n */\nexport interface SitemapLink {\n /** URL path */\n path: string;\n /** Display label */\n label: string;\n /** Optional description */\n description?: string;\n}\n\n/**\n * Configuration for a sitemap section\n */\nexport interface SitemapSection {\n /** Section title */\n title: string;\n /** Section icon type (optional) */\n icon?: 'home' | 'document' | 'envelope' | 'cog' | 'language';\n /** Links in this section */\n links: SitemapLink[];\n}\n\n/**\n * Configuration for a language option\n */\nexport interface LanguageOption {\n /** Language code (e.g., 'en', 'es') */\n code: string;\n /** Display name */\n name: string;\n /** Flag emoji */\n flag: string;\n}\n\n/**\n * Configuration for quick action buttons\n */\nexport interface QuickLink {\n /** URL path */\n path: string;\n /** Display label */\n label: string;\n /** Button variant */\n variant: 'primary' | 'secondary' | 'outline';\n /** Optional icon */\n icon?: 'envelope' | 'document';\n}\n\n/**\n * Text content for the sitemap page\n */\nexport interface SitemapPageText {\n /** Page title */\n title: string;\n /** Page subtitle */\n subtitle: string;\n /** Languages section title */\n languagesSectionTitle: string;\n /** Languages section description */\n languagesDescription: string;\n /** Quick links section title */\n quickLinksTitle: string;\n}\n\n/**\n * Props for AppSitemapPage component\n */\nexport interface AppSitemapPageProps {\n /** All text content (must be provided by consumer) */\n text: SitemapPageText;\n /** Sitemap sections */\n sections: SitemapSection[];\n /** Available languages */\n languages: LanguageOption[];\n /** Quick action links */\n quickLinks?: QuickLink[];\n /** Custom Link component for navigation */\n LinkComponent: ComponentType<LinkComponentProps & { language?: string }>;\n /** Optional wrapper component for the page layout */\n PageWrapper?: ComponentType<{ children: ReactNode }>;\n /** Path to use for language switcher links (defaults to current page path via window.location) */\n languageLinkPath?: string;\n /** Optional className for the container */\n className?: string;\n}\n\n/**\n * Get icon component based on icon type\n */\nconst getIcon = (icon?: string) => {\n switch (icon) {\n case 'home':\n return <HomeIcon className='w-5 h-5 mr-2' />;\n case 'document':\n return <DocumentTextIcon className='w-5 h-5 mr-2' />;\n case 'envelope':\n return <EnvelopeIcon className='w-5 h-5 mr-2' />;\n case 'cog':\n return <CogIcon className='w-5 h-5 mr-2' />;\n case 'language':\n return <LanguageIcon className='w-5 h-5 mr-2' />;\n default:\n return null;\n }\n};\n\n/**\n * AppSitemapPage - A reusable sitemap page component\n *\n * Displays a comprehensive sitemap with:\n * - Language selector\n * - Organized sections with links\n * - Quick action buttons\n *\n * All text content must be provided by the consumer app.\n *\n * @example\n * ```tsx\n * <AppSitemapPage\n * text={{\n * title: \"Sitemap\",\n * subtitle: \"Explore all pages\",\n * languagesSectionTitle: \"Languages\",\n * languagesDescription: \"Available in multiple languages\",\n * quickLinksTitle: \"Quick Links\"\n * }}\n * sections={[\n * { title: \"Main\", icon: \"home\", links: [{ path: \"/\", label: \"Home\" }] }\n * ]}\n * languages={[{ code: \"en\", name: \"English\", flag: \"🇺🇸\" }]}\n * LinkComponent={LocalizedLink}\n * />\n * ```\n */\nexport const AppSitemapPage: React.FC<AppSitemapPageProps> = ({\n text,\n sections,\n languages,\n quickLinks = [],\n LinkComponent,\n PageWrapper,\n languageLinkPath,\n className,\n}) => {\n const content = (\n <Section spacing='3xl' maxWidth='6xl' className={cn(className)}>\n {/* Header */}\n <div className='text-center mb-12'>\n <h1 className={`text-4xl font-bold ${ui.text.strong} mb-4`}>\n {text.title}\n </h1>\n <p className={`text-xl ${ui.text.muted}`}>{text.subtitle}</p>\n </div>\n\n {/* Language Section */}\n {languages.length > 0 && (\n <div\n className={`mb-12 p-6 ${colors.component.alert.info.base} ${colors.component.alert.info.dark} rounded-lg`}\n >\n <h2\n className={`text-xl font-semibold ${ui.text.strong} mb-4 flex items-center`}\n >\n <LanguageIcon className='w-6 h-6 mr-2' />\n {text.languagesSectionTitle}\n </h2>\n <p className={`${ui.text.body} mb-6`}>{text.languagesDescription}</p>\n <div className='grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 gap-4'>\n {languages.map(lang => (\n <LinkComponent\n key={lang.code}\n href={languageLinkPath ?? '/'}\n language={lang.code}\n className={`flex items-center space-x-2 p-3 ${ui.background.surface} rounded-lg hover:shadow-md transition-shadow`}\n >\n <span className='text-2xl'>{lang.flag}</span>\n <div className={`font-medium ${ui.text.strong}`}>\n {lang.name}\n </div>\n </LinkComponent>\n ))}\n </div>\n </div>\n )}\n\n {/* Sitemap Grid */}\n <div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8'>\n {sections.map((section, index) => (\n <div\n key={index}\n className={`${ui.background.surface} rounded-lg shadow-sm p-6`}\n >\n <h2\n className={`text-lg font-semibold ${ui.text.strong} mb-4 flex items-center`}\n >\n {getIcon(section.icon)}\n {section.title}\n </h2>\n <ul className='space-y-2'>\n {section.links.map((link, linkIndex) => (\n <li key={linkIndex}>\n <LinkComponent\n href={link.path}\n className={`group flex items-start text-sm ${ui.text.linkSubtle} transition-colors`}\n >\n <ChevronRightIcon\n className={`w-4 h-4 mt-0.5 mr-2 flex-shrink-0 ${ui.text.muted} group-hover:text-blue-600 dark:group-hover:text-blue-400`}\n />\n <div>\n <span\n className={`font-medium ${ui.text.label} group-hover:text-blue-600 dark:group-hover:text-blue-400`}\n >\n {link.label}\n </span>\n {link.description && (\n <span\n className={`block text-xs ${ui.text.muted} mt-0.5`}\n >\n {link.description}\n </span>\n )}\n </div>\n </LinkComponent>\n </li>\n ))}\n </ul>\n </div>\n ))}\n </div>\n\n {/* Quick Links Section */}\n {quickLinks.length > 0 && (\n <div className={`mt-12 p-6 ${ui.background.subtle} rounded-lg`}>\n <h3 className={`text-lg font-semibold ${ui.text.strong} mb-4`}>\n {text.quickLinksTitle}\n </h3>\n <div className='flex flex-wrap gap-3'>\n {quickLinks.map((link, index) => {\n const baseClasses =\n 'inline-flex items-center px-4 py-2 rounded-lg';\n const variantClasses = buttonVariant(\n link.variant === 'primary'\n ? 'primary'\n : link.variant === 'secondary'\n ? 'secondary'\n : 'outline'\n );\n\n return (\n <LinkComponent\n key={index}\n href={link.path}\n className={cn(baseClasses, variantClasses)}\n >\n {link.icon === 'envelope' && (\n <EnvelopeIcon className='w-5 h-5 mr-2' />\n )}\n {link.icon === 'document' && (\n <DocumentTextIcon className='w-5 h-5 mr-2' />\n )}\n {link.label}\n </LinkComponent>\n );\n })}\n </div>\n </div>\n )}\n </Section>\n );\n\n if (PageWrapper) {\n return <PageWrapper>{content}</PageWrapper>;\n }\n\n return content;\n};\n\nexport default AppSitemapPage;\n","/**\n * @fileoverview App Text Page\n * @description Reusable page component for text-heavy content like Privacy Policy, Terms, etc.\n *\n * This component uses Section internally for proper page layout.\n * Do NOT wrap this component in a Section when consuming it.\n */\n\nimport React, { type ReactNode, type ComponentType } from 'react';\nimport { Section } from '@sudobility/components';\nimport { cn } from '../../utils';\nimport { ui, colors } from '@sudobility/design';\n\n/**\n * Configuration for a text section with paragraph content\n */\nexport interface TextSectionWithContent {\n /** Section title */\n title: string;\n /** Paragraph content */\n content: string;\n /** Whether content contains HTML that should be rendered */\n isHtml?: boolean;\n}\n\n/**\n * Configuration for a text section with a list\n */\nexport interface TextSectionWithList {\n /** Section title */\n title: string;\n /** Optional description before the list */\n description?: string;\n /** List items */\n items: string[];\n /** Optional additional content after the list */\n additionalContent?: string;\n}\n\n/**\n * Configuration for a text section with subsections (e.g., \"Information You Provide\" and \"Information Collected Automatically\")\n */\nexport interface TextSectionWithSubsections {\n /** Section title */\n title: string;\n /** Subsections, each with a title and list items */\n subsections: Array<{\n title: string;\n items: string[];\n }>;\n}\n\n/**\n * Union type for all section types\n */\nexport type TextSection =\n | TextSectionWithContent\n | TextSectionWithList\n | TextSectionWithSubsections;\n\n/**\n * Contact information configuration\n */\nexport interface TextPageContactInfo {\n /** Email label (e.g., \"Email:\") */\n emailLabel: string;\n /** Email address */\n email: string;\n /** Website label (e.g., \"Website:\") */\n websiteLabel: string;\n /** Website URL */\n websiteUrl: string;\n /** Data Protection Officer label (optional, for privacy pages) */\n dpoLabel?: string;\n /** DPO email (optional, for privacy pages) */\n dpoEmail?: string;\n}\n\n/**\n * GDPR notice configuration (optional, for privacy pages)\n */\nexport interface GdprNotice {\n /** GDPR section title */\n title: string;\n /** GDPR section content */\n content: string;\n}\n\n/**\n * Contact section configuration\n */\nexport interface TextPageContact {\n /** Section title */\n title: string;\n /** Section description */\n description: string;\n /** Whether description contains HTML */\n isHtml?: boolean;\n /** Contact details */\n info: TextPageContactInfo;\n /** Optional GDPR notice (for privacy pages) */\n gdprNotice?: GdprNotice;\n}\n\n/**\n * All text content for the text page\n */\nexport interface TextPageContent {\n /** Page title */\n title: string;\n /** Last updated text (use {{date}} as placeholder for the date) */\n lastUpdated?: string;\n /** All sections in order */\n sections: TextSection[];\n /** Contact information (optional) */\n contact?: TextPageContact;\n}\n\n/**\n * Props for AppTextPage component\n */\nexport interface AppTextPageProps {\n /** All text content (must be provided by consumer) */\n text: TextPageContent;\n /** Current date for \"last updated\" display */\n lastUpdatedDate?: string;\n /** Optional wrapper component for the page layout */\n PageWrapper?: ComponentType<{ children: ReactNode }>;\n /** Optional className for the container */\n className?: string;\n}\n\n/**\n * Type guard to check if section has items (is a list section)\n */\nfunction isSectionWithList(\n section: TextSection\n): section is TextSectionWithList {\n return 'items' in section && Array.isArray(section.items);\n}\n\n/**\n * Type guard to check if section has subsections\n */\nfunction isSectionWithSubsections(\n section: TextSection\n): section is TextSectionWithSubsections {\n return 'subsections' in section && Array.isArray(section.subsections);\n}\n\n/**\n * Heading component for h2 sections\n */\nconst SectionHeading: React.FC<{ children: ReactNode }> = ({ children }) => (\n <h2 className={`text-2xl font-bold ${ui.text.strong} mt-8 mb-4`}>\n {children}\n </h2>\n);\n\n/**\n * Heading component for h3 subsections\n */\nconst SubsectionHeading: React.FC<{ children: ReactNode }> = ({ children }) => (\n <h3 className={`text-xl font-semibold ${ui.text.strong} mt-6 mb-3`}>\n {children}\n </h3>\n);\n\n/**\n * Paragraph component\n */\nconst Paragraph: React.FC<{ children: ReactNode; className?: string }> = ({\n children,\n className = '',\n}) => <p className={cn(ui.text.body, 'mb-6', className)}>{children}</p>;\n\n/**\n * List component - renders items with HTML support\n */\nconst List: React.FC<{ items: string[] }> = ({ items }) => (\n <ul className={`list-disc list-inside ${ui.text.body} mb-6 space-y-1`}>\n {items.map((item, index) => (\n <li key={index} dangerouslySetInnerHTML={{ __html: item }} />\n ))}\n </ul>\n);\n\n/**\n * AppTextPage - A reusable text page component for legal/informational pages\n *\n * Displays a text-heavy page with:\n * - Flexible section structure (content, list, or subsections)\n * - Optional contact information\n * - Optional GDPR notice\n *\n * Use this for Privacy Policy, Terms of Service, Cookie Policy, etc.\n *\n * @example\n * ```tsx\n * <AppTextPage\n * text={{\n * title: \"Privacy Policy\",\n * lastUpdated: \"Last updated: {{date}}\",\n * sections: [\n * { title: \"Introduction\", content: \"We respect your privacy...\" },\n * { title: \"Data We Collect\", items: [\"Email\", \"Usage data\"] },\n * {\n * title: \"Information We Collect\",\n * subsections: [\n * { title: \"You Provide\", items: [\"Email\", \"Name\"] },\n * { title: \"Automatic\", items: [\"IP\", \"Browser\"] }\n * ]\n * }\n * ],\n * contact: {\n * title: \"Contact\",\n * description: \"Questions?\",\n * info: { emailLabel: \"Email:\", email: \"support@example.com\", ... }\n * }\n * }}\n * lastUpdatedDate=\"January 1, 2025\"\n * />\n * ```\n */\nexport const AppTextPage: React.FC<AppTextPageProps> = ({\n text,\n lastUpdatedDate = new Date().toLocaleDateString(),\n PageWrapper,\n className,\n}) => {\n const content = (\n <Section spacing='3xl' maxWidth='4xl' className={cn(className)}>\n <h1 className={`text-4xl font-bold ${ui.text.strong} mb-8`}>\n {text.title}\n </h1>\n\n <div className='prose prose-lg dark:prose-invert max-w-none'>\n {text.lastUpdated && (\n <Paragraph className='mb-6'>\n {text.lastUpdated.replace('{{date}}', lastUpdatedDate)}\n </Paragraph>\n )}\n\n {/* Render all sections */}\n {text.sections.map((section, index) => (\n <React.Fragment key={index}>\n <SectionHeading>{section.title}</SectionHeading>\n\n {isSectionWithSubsections(section) ? (\n // Section with subsections (h3 + lists)\n <>\n {section.subsections.map((subsection, subIndex) => (\n <React.Fragment key={subIndex}>\n <SubsectionHeading>{subsection.title}</SubsectionHeading>\n <List items={subsection.items} />\n </React.Fragment>\n ))}\n </>\n ) : isSectionWithList(section) ? (\n // Section with list\n <>\n {section.description && (\n <Paragraph className='mb-4'>{section.description}</Paragraph>\n )}\n <List items={section.items} />\n {section.additionalContent && (\n <Paragraph>{section.additionalContent}</Paragraph>\n )}\n </>\n ) : section.isHtml ? (\n // Section with HTML content\n <Paragraph>\n <span dangerouslySetInnerHTML={{ __html: section.content }} />\n </Paragraph>\n ) : (\n // Section with plain text content\n <Paragraph>{section.content}</Paragraph>\n )}\n </React.Fragment>\n ))}\n\n {/* Contact Section */}\n {text.contact && (\n <>\n <SectionHeading>{text.contact.title}</SectionHeading>\n {text.contact.isHtml ? (\n <Paragraph>\n <span\n dangerouslySetInnerHTML={{ __html: text.contact.description }}\n />\n </Paragraph>\n ) : (\n <Paragraph>{text.contact.description}</Paragraph>\n )}\n <div className={`${ui.background.subtle} p-4 rounded-lg`}>\n <p className={ui.text.body}>\n {text.contact.info.emailLabel}{' '}\n <a\n href={`mailto:${text.contact.info.email}`}\n className={ui.text.link}\n >\n {text.contact.info.email}\n </a>\n <br />\n {text.contact.info.websiteLabel}{' '}\n <a href={text.contact.info.websiteUrl} className={ui.text.link}>\n {text.contact.info.websiteUrl}\n </a>\n {text.contact.info.dpoLabel && text.contact.info.dpoEmail && (\n <>\n <br />\n {text.contact.info.dpoLabel}{' '}\n <a\n href={`mailto:${text.contact.info.dpoEmail}`}\n className={ui.text.link}\n >\n {text.contact.info.dpoEmail}\n </a>\n </>\n )}\n </p>\n </div>\n\n {/* GDPR Notice */}\n {text.contact.gdprNotice && (\n <div\n className={`mt-8 p-4 ${colors.component.alert.info.base} ${colors.component.alert.info.dark} rounded-lg`}\n >\n <h3 className={`text-lg font-semibold ${ui.text.info} mb-2`}>\n {text.contact.gdprNotice.title}\n </h3>\n <p className={ui.text.info}>\n {text.contact.gdprNotice.content}{' '}\n {text.contact.info.dpoEmail && (\n <a\n href={`mailto:${text.contact.info.dpoEmail}`}\n className={ui.text.link}\n >\n {text.contact.info.dpoEmail}\n </a>\n )}\n </p>\n </div>\n )}\n </>\n )}\n </div>\n </Section>\n );\n\n if (PageWrapper) {\n return <PageWrapper>{content}</PageWrapper>;\n }\n\n return content;\n};\n\nexport default AppTextPage;\n","import React, { useState, useEffect, useRef, type ReactNode } from 'react';\nimport { cn } from '../../utils';\nimport {\n buttonVariant,\n focusRing,\n colors as designColors,\n ui,\n} from '@sudobility/design';\n\n/**\n * Google logo SVG component\n */\nfunction GoogleIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox='0 0 24 24' aria-hidden='true'>\n <path\n d='M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z'\n fill='#4285F4'\n />\n <path\n d='M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z'\n fill='#34A853'\n />\n <path\n d='M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z'\n fill='#FBBC05'\n />\n <path\n d='M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z'\n fill='#EA4335'\n />\n </svg>\n );\n}\n\n/**\n * Auth error info passed to onAuthError callback\n */\nexport interface AuthErrorInfo {\n /** Firebase error code (e.g., 'auth/popup-closed-by-user') */\n code: string;\n /** Error message */\n message: string;\n /** Whether this is a user-initiated action (like closing popup) vs actual error */\n isUserAction: boolean;\n}\n\n/**\n * Color variant for the LoginPage.\n * Each variant maps to a set of static, JIT-safe Tailwind classes.\n */\nexport type LoginPageColorVariant =\n | 'primary'\n | 'blue'\n | 'indigo'\n | 'violet'\n | 'orange'\n | 'emerald'\n | 'rose';\n\n/**\n * Props for the LoginPage component\n *\n * LoginPage is a presentational component that accepts auth handler callbacks.\n * The consumer must provide the actual auth logic (e.g., Firebase signIn).\n */\nexport interface LoginPageProps {\n /** Application name displayed as the main title */\n appName: string;\n /** Optional logo element to display above the title */\n logo?: ReactNode;\n /**\n * Handler for email/password sign-in.\n * Called with email and password; should throw on error.\n * The error object should have `code` and `message` properties for proper error display.\n */\n onEmailSignIn: (email: string, password: string) => Promise<void>;\n /**\n * Handler for email/password sign-up (account creation).\n * Called with email and password; should throw on error.\n * Only used when `showSignUp` is true.\n */\n onEmailSignUp?: (email: string, password: string) => Promise<void>;\n /**\n * Handler for Google sign-in.\n * Should perform the Google OAuth flow; should throw on error.\n * Only used when `showGoogleSignIn` is true.\n */\n onGoogleSignIn?: () => Promise<void>;\n /** Callback fired on successful authentication */\n onSuccess: () => void;\n /** Callback fired on auth errors - if provided, errors won't be shown inline */\n onAuthError?: (error: AuthErrorInfo) => void;\n /** Whether to show Google sign-in option (default: true) */\n showGoogleSignIn?: boolean;\n /** Whether to show sign-up option (default: true) */\n showSignUp?: boolean;\n /** Custom text overrides for localization. Falls back to English defaults for any omitted keys. */\n text?: Partial<LoginPageText>;\n /** Custom className for the container */\n className?: string;\n /**\n * Color variant for themed elements (default: 'primary').\n * Uses static Tailwind classes to ensure JIT compatibility.\n */\n colorVariant?: LoginPageColorVariant;\n}\n\n/**\n * Text content for the LoginPage\n */\nexport interface LoginPageText {\n signIn: string;\n signUp: string;\n createAccount: string;\n signInToAccount: string;\n emailLabel: string;\n emailPlaceholder: string;\n passwordLabel: string;\n passwordPlaceholder: string;\n orContinueWith: string;\n signInWithGoogle: string;\n alreadyHaveAccount: string;\n dontHaveAccount: string;\n}\n\nconst defaultText: LoginPageText = {\n signIn: 'Sign in',\n signUp: 'Sign up',\n createAccount: 'Create your account',\n signInToAccount: 'Sign in to your account',\n emailLabel: 'Email address',\n emailPlaceholder: '',\n passwordLabel: 'Password',\n passwordPlaceholder: '',\n orContinueWith: 'Or continue with',\n signInWithGoogle: 'Sign in with Google',\n alreadyHaveAccount: 'Already have an account?',\n dontHaveAccount: \"Don't have an account?\",\n};\n\n// Error codes that represent user actions rather than actual errors\nconst USER_ACTION_ERROR_CODES = [\n 'auth/popup-closed-by-user',\n 'auth/cancelled-popup-request',\n 'auth/user-cancelled',\n];\n\n/**\n * Static Tailwind class mappings for text elements per color variant.\n * Button and input styles come from @sudobility/design system.\n */\nconst colorVariantClasses: Record<\n LoginPageColorVariant,\n {\n title: string;\n toggleLink: string;\n }\n> = {\n primary: {\n title: 'text-blue-600',\n toggleLink: 'text-blue-600 hover:text-blue-500',\n },\n blue: {\n title: 'text-blue-600',\n toggleLink: 'text-blue-600 hover:text-blue-500',\n },\n indigo: {\n title: 'text-indigo-600',\n toggleLink: 'text-indigo-600 hover:text-indigo-500',\n },\n violet: {\n title: 'text-violet-600',\n toggleLink: 'text-violet-600 hover:text-violet-500',\n },\n orange: {\n title: 'text-orange-600',\n toggleLink: 'text-orange-600 hover:text-orange-500',\n },\n emerald: {\n title: 'text-emerald-600',\n toggleLink: 'text-emerald-600 hover:text-emerald-500',\n },\n rose: {\n title: 'text-rose-600',\n toggleLink: 'text-rose-600 hover:text-rose-500',\n },\n};\n\n/**\n * A reusable login page component with email/password and Google sign-in support.\n *\n * This component is fully decoupled from any auth provider. The consumer provides\n * auth handler callbacks (`onEmailSignIn`, `onEmailSignUp`, `onGoogleSignIn`).\n *\n * @example\n * ```tsx\n * import { LoginPage } from '@sudobility/building_blocks';\n * import { signInWithEmailAndPassword, createUserWithEmailAndPassword, GoogleAuthProvider, signInWithPopup } from 'firebase/auth';\n * import { getFirebaseAuth } from '@sudobility/auth_lib';\n *\n * function MyLoginPage() {\n * const navigate = useNavigate();\n * const auth = getFirebaseAuth();\n *\n * return (\n * <LoginPage\n * appName=\"My App\"\n * onEmailSignIn={async (email, password) => {\n * await signInWithEmailAndPassword(auth, email, password);\n * }}\n * onEmailSignUp={async (email, password) => {\n * await createUserWithEmailAndPassword(auth, email, password);\n * }}\n * onGoogleSignIn={async () => {\n * await signInWithPopup(auth, new GoogleAuthProvider());\n * }}\n * onSuccess={() => navigate('/')}\n * />\n * );\n * }\n * ```\n */\nexport function LoginPage({\n appName,\n logo,\n onEmailSignIn,\n onEmailSignUp,\n onGoogleSignIn,\n onSuccess,\n onAuthError,\n text: textOverrides,\n showGoogleSignIn = true,\n showSignUp = true,\n className = '',\n colorVariant = 'primary',\n}: LoginPageProps) {\n // Development-only warnings for common misconfigurations\n if (process.env.NODE_ENV !== 'production') {\n if (showSignUp && !onEmailSignUp) {\n console.warn(\n '[LoginPage] showSignUp is true but onEmailSignUp handler is not provided. ' +\n 'Sign-up will fall back to onEmailSignIn. Provide onEmailSignUp for proper account creation.'\n );\n }\n if (showGoogleSignIn && !onGoogleSignIn) {\n console.warn(\n '[LoginPage] showGoogleSignIn is true but onGoogleSignIn handler is not provided. ' +\n 'Google sign-in button will not be rendered. Provide onGoogleSignIn or set showGoogleSignIn to false.'\n );\n }\n }\n const [isSignUp, setIsSignUp] = useState(false);\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [isLoading, setIsLoading] = useState(false);\n const [isGoogleSignInPending, setIsGoogleSignInPending] = useState(false);\n const googleSignInStartTime = useRef<number | null>(null);\n\n const colors = colorVariantClasses[colorVariant];\n\n // Reset Google sign-in state when window regains focus\n // This handles the case where browser opens a new tab instead of popup\n useEffect(() => {\n const handleFocus = () => {\n if (isGoogleSignInPending && googleSignInStartTime.current) {\n // If more than 2 seconds have passed since sign-in started,\n // and we're back in focus, the user likely closed the tab/popup\n const elapsed = Date.now() - googleSignInStartTime.current;\n if (elapsed > 2000) {\n setIsLoading(false);\n setIsGoogleSignInPending(false);\n googleSignInStartTime.current = null;\n }\n }\n };\n\n window.addEventListener('focus', handleFocus);\n return () => window.removeEventListener('focus', handleFocus);\n }, [isGoogleSignInPending]);\n\n const handleAuthError = (err: unknown) => {\n const firebaseError = err as { code?: string; message?: string };\n const code = firebaseError.code || 'unknown';\n const message = firebaseError.message || 'Authentication failed';\n const isUserAction = USER_ACTION_ERROR_CODES.includes(code);\n\n if (onAuthError) {\n onAuthError({ code, message, isUserAction });\n } else if (!isUserAction) {\n // Only show inline error for actual errors, not user actions\n setError(message);\n }\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n setError(null);\n setIsLoading(true);\n\n try {\n if (isSignUp && showSignUp && onEmailSignUp) {\n await onEmailSignUp(email, password);\n } else {\n await onEmailSignIn(email, password);\n }\n onSuccess();\n } catch (err) {\n handleAuthError(err);\n } finally {\n setIsLoading(false);\n }\n };\n\n const handleGoogleSignIn = async () => {\n if (!onGoogleSignIn) return;\n\n setError(null);\n setIsLoading(true);\n setIsGoogleSignInPending(true);\n googleSignInStartTime.current = Date.now();\n\n try {\n await onGoogleSignIn();\n onSuccess();\n } catch (err) {\n handleAuthError(err);\n } finally {\n setIsLoading(false);\n setIsGoogleSignInPending(false);\n googleSignInStartTime.current = null;\n }\n };\n\n const text = { ...defaultText, ...textOverrides };\n\n return (\n <div\n className={cn(\n `min-h-screen flex items-center justify-center ${ui.background.subtle} py-12 px-4 sm:px-6 lg:px-8`,\n className\n )}\n >\n <div className='max-w-md w-full space-y-8'>\n <div>\n {logo && <div className='flex justify-center mb-4'>{logo}</div>}\n <h1 className={cn('text-center text-3xl font-bold', colors.title)}>\n {appName}\n </h1>\n <h2\n className={`mt-6 text-center text-2xl font-semibold ${ui.text.strong}`}\n >\n {isSignUp && showSignUp ? text.createAccount : text.signInToAccount}\n </h2>\n </div>\n\n <form className='mt-8 space-y-6' onSubmit={handleSubmit}>\n {error && (\n <div\n className={`${designColors.component.alert.error.base} ${designColors.component.alert.error.dark} border px-4 py-3 rounded-md text-sm`}\n role='alert'\n >\n {error}\n </div>\n )}\n\n <div className='space-y-4'>\n <div>\n <label htmlFor='login-email' className={`block ${ui.text.label}`}>\n {text.emailLabel}\n </label>\n <input\n id='login-email'\n name='email'\n type='email'\n autoComplete='email'\n required\n value={email}\n onChange={e => setEmail(e.target.value)}\n placeholder={text.emailPlaceholder}\n className={cn(\n `mt-1 appearance-none block w-full px-3 py-2 border rounded-md shadow-sm sm:text-sm ${designColors.component.input.default.base} ${designColors.component.input.default.dark}`,\n focusRing\n )}\n />\n </div>\n\n <div>\n <label\n htmlFor='login-password'\n className={`block ${ui.text.label}`}\n >\n {text.passwordLabel}\n </label>\n <input\n id='login-password'\n name='password'\n type='password'\n autoComplete={isSignUp ? 'new-password' : 'current-password'}\n required\n value={password}\n onChange={e => setPassword(e.target.value)}\n placeholder={text.passwordPlaceholder}\n className={cn(\n `mt-1 appearance-none block w-full px-3 py-2 border rounded-md shadow-sm sm:text-sm ${designColors.component.input.default.base} ${designColors.component.input.default.dark}`,\n focusRing\n )}\n />\n </div>\n </div>\n\n <div>\n <button\n type='submit'\n disabled={isLoading}\n className={cn(\n 'w-full inline-flex items-center justify-center font-medium rounded-md px-4 py-2 text-sm',\n buttonVariant('primary'),\n 'disabled:opacity-50 disabled:cursor-not-allowed'\n )}\n >\n {isLoading && (\n <svg\n className='animate-spin -ml-1 mr-2 h-4 w-4'\n xmlns='http://www.w3.org/2000/svg'\n fill='none'\n viewBox='0 0 24 24'\n aria-hidden='true'\n >\n <circle\n className='opacity-25'\n cx='12'\n cy='12'\n r='10'\n stroke='currentColor'\n strokeWidth='4'\n />\n <path\n className='opacity-75'\n fill='currentColor'\n d='M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z'\n />\n </svg>\n )}\n {isSignUp && showSignUp ? text.signUp : text.signIn}\n </button>\n </div>\n\n {showGoogleSignIn && onGoogleSignIn && (\n <>\n <div className='relative'>\n <div className='absolute inset-0 flex items-center'>\n <div className={`w-full border-t ${ui.border.default}`} />\n </div>\n <div className='relative flex justify-center text-sm'>\n <span\n className={`px-2 ${ui.background.subtle} ${ui.text.muted}`}\n >\n {text.orContinueWith}\n </span>\n </div>\n </div>\n\n <div>\n <button\n type='button'\n onClick={handleGoogleSignIn}\n disabled={isLoading}\n className={cn(\n 'w-full inline-flex items-center justify-center font-medium rounded-md px-4 py-2 text-sm',\n buttonVariant('outline'),\n `${ui.background.surface} ${ui.text.label} disabled:opacity-50 disabled:cursor-not-allowed`\n )}\n >\n {isLoading ? (\n <svg\n className='animate-spin -ml-1 mr-2 h-5 w-5'\n xmlns='http://www.w3.org/2000/svg'\n fill='none'\n viewBox='0 0 24 24'\n aria-hidden='true'\n >\n <circle\n className='opacity-25'\n cx='12'\n cy='12'\n r='10'\n stroke='currentColor'\n strokeWidth='4'\n />\n <path\n className='opacity-75'\n fill='currentColor'\n d='M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z'\n />\n </svg>\n ) : (\n <GoogleIcon className='h-5 w-5 mr-2' />\n )}\n {text.signInWithGoogle}\n </button>\n </div>\n </>\n )}\n </form>\n\n {showSignUp && (\n <p className={`text-center text-sm ${ui.text.muted}`}>\n {isSignUp ? text.alreadyHaveAccount : text.dontHaveAccount}{' '}\n <button\n type='button'\n onClick={() => setIsSignUp(!isSignUp)}\n className={cn('font-medium', colors.toggleLink)}\n >\n {isSignUp ? text.signIn : text.signUp}\n </button>\n </p>\n )}\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport { buttonVariant, ui } from '@sudobility/design';\nimport { cn } from '../../utils';\n\nexport interface EmptyStateProps {\n /** Message text displayed in the empty state */\n message: string;\n /** Label for the primary action button */\n buttonLabel: string;\n /** Callback fired when the button is pressed */\n onPress: () => void;\n}\n\n/**\n * EmptyState - Centered message with a primary action button.\n *\n * Use this when a list or page has no content to display.\n *\n * @example\n * ```tsx\n * <EmptyState\n * message=\"No items found\"\n * buttonLabel=\"Create Item\"\n * onPress={() => navigate('/new')}\n * />\n * ```\n */\nexport const EmptyState: React.FC<EmptyStateProps> = ({\n message,\n buttonLabel,\n onPress,\n}) => {\n return (\n <div className='flex-1 flex flex-col items-center justify-center px-8'>\n <p\n className={cn(\n ui.text.muted,\n 'text-center text-[15px] leading-relaxed mb-5'\n )}\n >\n {message}\n </p>\n <button\n type='button'\n onClick={onPress}\n className={cn(\n buttonVariant('primary'),\n 'rounded-md px-6 py-2 text-sm font-medium min-h-[44px]'\n )}\n >\n {buttonLabel}\n </button>\n </div>\n );\n};\n\nexport default EmptyState;\n","/**\n * Default i18n configuration for Sudobility apps\n *\n * Creates a pre-configured i18next instance with:\n * - HTTP backend for loading translations from /locales/\n * - Language detection from URL path, localStorage, navigator\n * - React integration\n */\n\nimport i18n from 'i18next';\nimport { initReactI18next } from 'react-i18next';\nimport Backend from 'i18next-http-backend';\nimport LanguageDetector from 'i18next-browser-languagedetector';\n\n// Default supported languages\nconst DEFAULT_SUPPORTED_LANGUAGES = ['en'];\n\n// Default namespaces\nconst DEFAULT_NAMESPACES = [\n 'common',\n 'home',\n 'pricing',\n 'docs',\n 'dashboard',\n 'auth',\n 'privacy',\n 'terms',\n 'settings',\n];\n\n/**\n * Detect language from URL path first, then localStorage\n */\nfunction detectLanguageFromPath(supportedLanguages: string[]): string {\n if (typeof window === 'undefined') {\n return 'en';\n }\n\n // Check URL path first\n const pathLang = window.location.pathname.split('/')[1];\n if (pathLang && supportedLanguages.includes(pathLang)) {\n return pathLang;\n }\n\n // Fall back to localStorage\n try {\n const stored = localStorage.getItem('language');\n if (stored && supportedLanguages.includes(stored)) {\n return stored;\n }\n } catch {\n // localStorage may throw in Safari private browsing\n }\n\n return 'en';\n}\n\nexport interface I18nConfig {\n /**\n * Supported language codes.\n * Defaults to [\"en\"].\n */\n supportedLanguages?: string[];\n\n /**\n * Translation namespaces to load.\n * Defaults to common app namespaces.\n */\n namespaces?: string[];\n\n /**\n * Default namespace.\n * Defaults to \"common\".\n */\n defaultNamespace?: string;\n\n /**\n * Path pattern for loading translations.\n * Defaults to \"/locales/{{lng}}/{{ns}}.json\".\n */\n loadPath?: string;\n\n /**\n * Enable debug logging.\n * Defaults to false.\n */\n debug?: boolean;\n}\n\nlet initialized = false;\n\n/**\n * Initialize the default i18n instance.\n * Safe to call multiple times - only initializes once.\n */\nexport function initializeI18n(config: I18nConfig = {}): typeof i18n {\n if (initialized) {\n return i18n;\n }\n initialized = true;\n\n const {\n supportedLanguages = DEFAULT_SUPPORTED_LANGUAGES,\n namespaces = DEFAULT_NAMESPACES,\n defaultNamespace = 'common',\n loadPath = '/locales/{{lng}}/{{ns}}.json',\n debug = false,\n } = config;\n\n i18n\n .use(Backend)\n .use(LanguageDetector)\n .use(initReactI18next)\n .init({\n lng: detectLanguageFromPath(supportedLanguages),\n fallbackLng: {\n zh: ['zh', 'en'],\n 'zh-hant': ['zh-hant', 'zh', 'en'],\n default: ['en'],\n },\n initImmediate: false,\n supportedLngs: supportedLanguages,\n debug,\n nonExplicitSupportedLngs: true,\n\n interpolation: {\n escapeValue: false,\n },\n\n backend: {\n loadPath,\n },\n\n detection: {\n order: ['path', 'localStorage', 'navigator'],\n caches: ['localStorage'],\n lookupLocalStorage: 'language',\n lookupFromPathIndex: 0,\n },\n\n load: 'languageOnly',\n preload: [],\n cleanCode: false,\n lowerCaseLng: false,\n\n defaultNS: defaultNamespace,\n ns: namespaces,\n });\n\n return i18n;\n}\n\n/**\n * Get the i18n instance.\n * Initializes with defaults if not already initialized.\n */\nexport function getI18n(): typeof i18n {\n if (!initialized) {\n initializeI18n();\n }\n return i18n;\n}\n\nexport { i18n };\nexport default i18n;\n"],"names":["a","b","DefaultLinkComponent","className","AuthStatus","ChainType","FooterContainer","Theme","FontSize","defaultTranslations","colors","designColors"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sudobility/building_blocks",
3
- "version": "0.0.205",
3
+ "version": "0.0.207",
4
4
  "description": "Higher-level shared UI building blocks for Sudobility apps",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -38,7 +38,7 @@
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@heroicons/react": "^2.0.0",
41
- "@sudobility/components": "^5.0.53",
41
+ "@sudobility/components": "^5.0.54",
42
42
  "@sudobility/design": "^1.1.27",
43
43
  "@tanstack/react-query": "^5.0.0",
44
44
  "class-variance-authority": "^0.7.0",
@@ -97,7 +97,7 @@
97
97
  "@heroicons/react": "^2.2.0",
98
98
  "@sudobility/auth-components": "^1.0.10",
99
99
  "@sudobility/auth_lib": "^0.0.68",
100
- "@sudobility/components": "^5.0.53",
100
+ "@sudobility/components": "^5.0.54",
101
101
  "@sudobility/design": "^1.1.27",
102
102
  "@sudobility/devops-components": "^2.0.19",
103
103
  "@sudobility/di": "^1.5.52",