@inf-monkeys-tech/monkeys-design 0.4.34 → 0.4.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +226 -226
- package/dist/components/base/index.js.map +1 -1
- package/dist/components/base/index.mjs.map +1 -1
- package/dist/components/data-explorer/index.js.map +1 -1
- package/dist/components/data-explorer/index.mjs.map +1 -1
- package/dist/components/layout/index.js.map +1 -1
- package/dist/components/layout/index.mjs.map +1 -1
- package/dist/components/login/index.js.map +1 -1
- package/dist/components/login/index.mjs.map +1 -1
- package/dist/components/toast/index.d.mts +75 -0
- package/dist/components/toast/index.d.ts +75 -0
- package/dist/components/toast/index.js +283 -0
- package/dist/components/toast/index.js.map +1 -0
- package/dist/components/toast/index.mjs +273 -0
- package/dist/components/toast/index.mjs.map +1 -0
- package/dist/components/toolbar/index.js.map +1 -1
- package/dist/components/toolbar/index.mjs.map +1 -1
- package/dist/components/workbench/index.js.map +1 -1
- package/dist/components/workbench/index.mjs.map +1 -1
- package/dist/icons/oauth/index.js.map +1 -1
- package/dist/icons/oauth/index.mjs.map +1 -1
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +284 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +276 -11
- package/dist/index.mjs.map +1 -1
- package/dist/palette/index.js.map +1 -1
- package/dist/palette/index.mjs.map +1 -1
- package/dist/registry/index.js.map +1 -1
- package/dist/registry/index.mjs.map +1 -1
- package/dist/styles/artist-login.scss +374 -374
- package/dist/styles/global.scss +21 -21
- package/dist/styles/workflow-board.scss +440 -440
- package/dist/styles/workflow-nodes.css +340 -340
- package/dist/theme-system/index.js.map +1 -1
- package/dist/theme-system/index.mjs.map +1 -1
- package/dist/themes/artist/index.js.map +1 -1
- package/dist/themes/artist/index.mjs.map +1 -1
- package/dist/themes/bsd/index.js.map +1 -1
- package/dist/themes/bsd/index.mjs.map +1 -1
- package/dist/themes/concept/index.js.map +1 -1
- package/dist/themes/concept/index.mjs.map +1 -1
- package/dist/themes/default/index.js.map +1 -1
- package/dist/themes/default/index.mjs.map +1 -1
- package/package.json +146 -139
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/toast/index.tsx"],"names":["sonnerToast","SonnerToaster"],"mappings":"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","file":"index.mjs","sourcesContent":["import {\n isValidElement,\n type ReactElement,\n type ReactNode,\n useCallback,\n useEffect,\n useRef,\n} from 'react';\nimport {\n Toaster as SonnerToaster,\n toast as sonnerToast,\n type ExternalToast,\n type ToastT,\n type ToastToDismiss,\n type ToasterProps,\n} from 'sonner';\n\nexport type ToastVariant = 'error' | 'warning' | 'success' | 'info';\n\nexport type ToastInput = Omit<ExternalToast, 'description'> & {\n title?: ReactNode;\n description?: ReactNode;\n variant?: ToastVariant;\n};\n\nexport type MonkeysToasterProps = ToasterProps & {\n useThemeClassNames?: boolean;\n};\n\nexport type MonkeysToastProviderProps = {\n children: ReactNode;\n toasterProps?: MonkeysToasterProps;\n};\n\ntype ToastValue =\n | Error\n | string\n | {\n message?: unknown;\n title?: unknown;\n }\n | null\n | undefined;\n\ntype ToastResolver<T> = T | ((value: ToastValue) => T);\ntype ToastTranslate = (value: string, params?: Record<string, unknown>) => string;\n\ntype ToastValueOptions = {\n variant?: ToastResolver<ToastVariant | undefined>;\n title?: ToastResolver<string | undefined>;\n description?: ToastResolver<string | undefined>;\n fallbackDescription?: ToastResolver<string | undefined>;\n signature?: ToastResolver<string | undefined>;\n duration?: ToastResolver<number | undefined>;\n translate?: ToastTranslate;\n messages?: Partial<ToastDefaultMessages>;\n};\n\ntype ToastFeedEntry =\n | {\n variant?: ToastVariant;\n title?: string;\n description?: string;\n duration?: number;\n signature?: string;\n }\n | null\n | undefined;\n\ntype ToastDefaultMessages = {\n errorTitle: string;\n warningTitle: string;\n defaultErrorDescription: string;\n defaultWarningDescription: string;\n};\n\ntype ToastPromiseInput<T = unknown> = Promise<T> | (() => Promise<T>);\ntype ToastPromiseReturn<T = unknown> = string | number | { unwrap: () => Promise<T> };\n\nexport type MonkeysToastApi = {\n (message: ReactNode, options?: ExternalToast): string | number;\n show: (input: ToastInput) => string | number | undefined;\n error: (input: ReactNode | ToastInput, options?: ExternalToast) => string | number | undefined;\n warning: (input: ReactNode | ToastInput, options?: ExternalToast) => string | number | undefined;\n success: (input: ReactNode | ToastInput, options?: ExternalToast) => string | number | undefined;\n info: (input: ReactNode | ToastInput, options?: ExternalToast) => string | number | undefined;\n message: (message: ReactNode, options?: ExternalToast) => string | number;\n promise: <T = unknown>(promise: ToastPromiseInput<T>, data?: unknown) => ToastPromiseReturn<T>;\n dismiss: (id?: number | string) => string | number;\n loading: (message: ReactNode, options?: ExternalToast) => string | number;\n custom: (jsx: (id: number | string) => ReactElement, data?: ExternalToast) => string | number;\n getHistory: () => Array<ToastT | ToastToDismiss>;\n getToasts: () => Array<ToastT | ToastToDismiss>;\n};\n\nconst DEFAULT_TOAST_DURATION = 5200;\nconst TOAST_DEDUPE_WINDOW = 1200;\n\nconst DEFAULT_MESSAGES: ToastDefaultMessages = {\n errorTitle: 'Error',\n warningTitle: 'Warning',\n defaultErrorDescription: 'Something went wrong.',\n defaultWarningDescription: 'Please check and try again.',\n};\n\nconst ACTIONABLE_TOAST_PATTERNS = [\n /^(please|select|enter|provide|write|choose|confirm|fill)\\b/i,\n /^(请|请选择|请先|请输入|请填写|请确认|请留意)/,\n];\n\nconst DEFAULT_TOAST_CLASS_NAMES = {\n toast:\n 'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg',\n description: 'group-[.toast]:text-muted-foreground',\n actionButton: 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground',\n cancelButton: 'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground',\n};\n\nconst recentToastSignatures = new Map<string, number>();\n\nfunction cn(...classNames: Array<string | undefined | false>) {\n return classNames.filter(Boolean).join(' ');\n}\n\nfunction isToastInput(input: unknown): input is ToastInput {\n if (!input || typeof input !== 'object' || isValidElement(input)) {\n return false;\n }\n\n return 'title' in input || 'description' in input || 'variant' in input;\n}\n\nfunction isEmptyToastContent(value: ReactNode) {\n return value == null || (typeof value === 'string' && !value.trim());\n}\n\nfunction normalizeToastInput(input: ReactNode | ToastInput, variant: ToastVariant, options?: ExternalToast): ToastInput {\n const { description: _description, ...baseOptions } = options ?? {};\n\n if (isToastInput(input)) {\n return {\n ...baseOptions,\n ...input,\n variant: input.variant ?? variant,\n };\n }\n\n return {\n ...baseOptions,\n title: input,\n variant,\n };\n}\n\nfunction resolveValue<T>(candidate: ToastResolver<T> | undefined, value: ToastValue) {\n if (typeof candidate === 'function') {\n return (candidate as (input: ToastValue) => T)(value);\n }\n\n return candidate;\n}\n\nfunction shouldEmitToast(signature: string) {\n const now = Date.now();\n\n for (const [key, timestamp] of recentToastSignatures.entries()) {\n if (now - timestamp > TOAST_DEDUPE_WINDOW) {\n recentToastSignatures.delete(key);\n }\n }\n\n const previousTimestamp = recentToastSignatures.get(signature);\n if (previousTimestamp && now - previousTimestamp < TOAST_DEDUPE_WINDOW) {\n return false;\n }\n\n recentToastSignatures.set(signature, now);\n return true;\n}\n\nfunction translateMessage(translate: ToastTranslate | undefined, value: string) {\n return translate ? translate(value, { defaultValue: value }) : value;\n}\n\nfunction getDefaultMessage(messages: Partial<ToastDefaultMessages> | undefined, key: keyof ToastDefaultMessages) {\n return messages?.[key] ?? DEFAULT_MESSAGES[key];\n}\n\nfunction emitToast(input: ToastInput) {\n const { title, description, duration, variant = 'info', ...options } = input;\n const message = isEmptyToastContent(title) ? description : title;\n\n if (isEmptyToastContent(message)) {\n return undefined;\n }\n\n const descriptionValue =\n !isEmptyToastContent(description) && description !== message ? description : undefined;\n const sonnerOptions: ExternalToast = {\n ...options,\n description: descriptionValue,\n duration: duration ?? DEFAULT_TOAST_DURATION,\n };\n\n switch (variant) {\n case 'error':\n return sonnerToast.error(message, sonnerOptions);\n case 'warning':\n return sonnerToast.warning(message, sonnerOptions);\n case 'success':\n return sonnerToast.success(message, sonnerOptions);\n default:\n return sonnerToast(message, sonnerOptions);\n }\n}\n\nexport function extractToastMessage(value: ToastValue, fallback = '') {\n if (!value) return fallback;\n\n if (typeof value === 'string') {\n const nextMessage = value.trim();\n return nextMessage || fallback;\n }\n\n if (value instanceof Error) {\n const nextMessage = String(value.message || '').trim();\n return nextMessage || fallback;\n }\n\n if (typeof value === 'object' && typeof value.message === 'string') {\n const nextMessage = value.message.trim();\n if (nextMessage) return nextMessage;\n }\n\n if (typeof value === 'object' && typeof value.title === 'string') {\n const nextTitle = value.title.trim();\n if (nextTitle) return nextTitle;\n }\n\n return fallback;\n}\n\nexport function resolveToastVariantForMessage(value: ToastValue): ToastVariant {\n const message = extractToastMessage(value);\n\n if (ACTIONABLE_TOAST_PATTERNS.some((pattern) => pattern.test(message))) {\n return 'warning';\n }\n\n return 'error';\n}\n\nexport function MonkeysToaster({\n className,\n closeButton = true,\n position = 'bottom-right',\n richColors = true,\n toastOptions,\n useThemeClassNames = true,\n visibleToasts = 10,\n ...props\n}: MonkeysToasterProps) {\n return (\n <SonnerToaster\n className={cn('pointer-events-auto toaster group', className)}\n closeButton={closeButton}\n position={position}\n richColors={richColors}\n toastOptions={{\n ...toastOptions,\n classNames: useThemeClassNames\n ? {\n ...DEFAULT_TOAST_CLASS_NAMES,\n ...toastOptions?.classNames,\n }\n : toastOptions?.classNames,\n }}\n visibleToasts={visibleToasts}\n {...props}\n />\n );\n}\n\nexport function MonkeysToastProvider({ children, toasterProps }: MonkeysToastProviderProps) {\n return (\n <>\n {children}\n <MonkeysToaster {...toasterProps} />\n </>\n );\n}\n\nexport function useToastOnValue(value: ToastValue, options: ToastValueOptions = {}) {\n const previousSignatureRef = useRef<string | null>(null);\n const translate = options.translate;\n\n useEffect(() => {\n if (!value) {\n previousSignatureRef.current = null;\n return;\n }\n\n const variant = resolveValue(options.variant, value) ?? 'error';\n const rawTitle = resolveValue(options.title, value);\n const rawFallbackDescription = resolveValue(options.fallbackDescription, value);\n const rawDescription =\n resolveValue(options.description, value) ?? extractToastMessage(value, rawFallbackDescription || '');\n const title = translateMessage(\n translate,\n rawTitle || getDefaultMessage(options.messages, variant === 'warning' ? 'warningTitle' : 'errorTitle'),\n );\n const description = translateMessage(\n translate,\n rawDescription ||\n getDefaultMessage(\n options.messages,\n variant === 'warning' ? 'defaultWarningDescription' : 'defaultErrorDescription',\n ),\n );\n const signature = resolveValue(options.signature, value) || [variant, title, description].join('|');\n\n if (previousSignatureRef.current === signature) {\n return;\n }\n\n previousSignatureRef.current = signature;\n\n if (!shouldEmitToast(signature)) {\n return;\n }\n\n toast.show({\n variant,\n title,\n description,\n duration: resolveValue(options.duration, value),\n });\n }, [\n options.description,\n options.duration,\n options.fallbackDescription,\n options.messages,\n options.signature,\n options.title,\n options.variant,\n translate,\n value,\n ]);\n}\n\nexport function useToastFeed(items: ToastFeedEntry[], options: Pick<ToastValueOptions, 'messages' | 'translate'> = {}) {\n const previousVisibleSignaturesRef = useRef<Set<string>>(new Set());\n const translate = options.translate;\n const emitItem = useCallback(\n (item: NonNullable<ToastFeedEntry>, index: number, visibleSignatures: Set<string>) => {\n const variant = item.variant ?? 'info';\n const title = translateMessage(\n translate,\n item.title || getDefaultMessage(options.messages, variant === 'warning' ? 'warningTitle' : 'errorTitle'),\n );\n const description = translateMessage(\n translate,\n item.description ||\n getDefaultMessage(\n options.messages,\n variant === 'warning' ? 'defaultWarningDescription' : 'defaultErrorDescription',\n ),\n );\n const signature = item.signature || [variant, title, description, index].join('|');\n\n visibleSignatures.add(signature);\n\n if (previousVisibleSignaturesRef.current.has(signature) || !shouldEmitToast(signature)) {\n return;\n }\n\n toast.show({\n variant,\n title,\n description,\n duration: item.duration,\n });\n },\n [options.messages, translate],\n );\n\n useEffect(() => {\n const visibleSignatures = new Set<string>();\n\n items.forEach((item, index) => {\n if (item) {\n emitItem(item, index, visibleSignatures);\n }\n });\n\n previousVisibleSignaturesRef.current = visibleSignatures;\n }, [emitItem, items]);\n}\n\nexport const toast: MonkeysToastApi = Object.assign(\n (message: ReactNode, options?: ExternalToast) => sonnerToast(message, options),\n {\n show: emitToast,\n error: (input: ReactNode | ToastInput, options?: ExternalToast) =>\n emitToast(normalizeToastInput(input, 'error', options)),\n warning: (input: ReactNode | ToastInput, options?: ExternalToast) =>\n emitToast(normalizeToastInput(input, 'warning', options)),\n success: (input: ReactNode | ToastInput, options?: ExternalToast) =>\n emitToast(normalizeToastInput(input, 'success', options)),\n info: (input: ReactNode | ToastInput, options?: ExternalToast) =>\n emitToast(normalizeToastInput(input, 'info', options)),\n message: sonnerToast.message,\n promise: sonnerToast.promise as MonkeysToastApi['promise'],\n dismiss: sonnerToast.dismiss,\n loading: sonnerToast.loading,\n custom: sonnerToast.custom as (jsx: (id: number | string) => ReactElement, data?: ExternalToast) => string | number,\n getHistory: sonnerToast.getHistory,\n getToasts: sonnerToast.getToasts,\n },\n);\n\nexport { MonkeysToaster as Toaster, MonkeysToastProvider as ToastProvider };\nexport type { ExternalToast, ToasterProps };\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/toolbar/DarkModeSelector.tsx","../../../src/components/toolbar/I18nSelector.tsx","../../../src/components/toolbar/useDarkMode.ts"],"names":["jsxs","jsx","DropdownMenu","Tooltip","cn","DropdownMenu2","Tooltip2","useState","useCallback","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import * as React from 'react';\r\nimport * as DropdownMenu from '@radix-ui/react-dropdown-menu';\r\nimport * as Tooltip from '@radix-ui/react-tooltip';\r\n\r\nfunction cn(...inputs: (string | undefined | null | false)[]): string {\r\n return inputs.filter(Boolean).join(' ');\r\n}\r\n\r\n// ---------- Inline SVG Icons ----------\r\n\r\nfunction SunIcon({ className }: { className?: string }) {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\r\n <path d=\"M12 2v2\" /><path d=\"M12 20v2\" />\r\n <path d=\"m4.93 4.93 1.41 1.41\" /><path d=\"m17.66 17.66 1.41 1.41\" />\r\n <path d=\"M2 12h2\" /><path d=\"M20 12h2\" />\r\n <path d=\"m6.34 17.66-1.41 1.41\" /><path d=\"m19.07 4.93-1.41 1.41\" />\r\n </svg>\r\n );\r\n}\r\n\r\nfunction MoonIcon({ className }: { className?: string }) {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\" />\r\n </svg>\r\n );\r\n}\r\n\r\nfunction MonitorIcon({ className }: { className?: string }) {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\r\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\r\n </svg>\r\n );\r\n}\r\n\r\n// ---------- Component ----------\r\n\r\nexport type DarkModeValue = 'auto' | 'light' | 'dark';\r\n\r\nexport interface DarkModeSelectorProps {\r\n mode: DarkModeValue;\r\n onModeChange: (mode: DarkModeValue) => void;\r\n labels?: { auto?: string; light?: string; dark?: string };\r\n tooltip?: string;\r\n className?: string;\r\n}\r\n\r\nconst triggerIconMap: Record<DarkModeValue, React.FC<{ className?: string }>> = {\r\n light: SunIcon,\r\n dark: MoonIcon,\r\n auto: MonitorIcon,\r\n};\r\n\r\nexport function DarkModeSelector({\r\n mode,\r\n onModeChange,\r\n labels = {},\r\n tooltip,\r\n className,\r\n}: DarkModeSelectorProps) {\r\n const TriggerIcon = triggerIconMap[mode];\r\n const resolvedLabels = {\r\n auto: labels.auto ?? 'Auto',\r\n light: labels.light ?? 'Light',\r\n dark: labels.dark ?? 'Dark',\r\n };\r\n\r\n const options: { value: DarkModeValue; label: string; Icon: React.FC<{ className?: string }> }[] = [\r\n { value: 'auto', label: resolvedLabels.auto, Icon: MonitorIcon },\r\n { value: 'light', label: resolvedLabels.light, Icon: SunIcon },\r\n { value: 'dark', label: resolvedLabels.dark, Icon: MoonIcon },\r\n ];\r\n\r\n const trigger = (\r\n <DropdownMenu.Trigger asChild>\r\n <button\r\n className={cn(\r\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] transition-colors focus-visible:outline-none',\r\n className,\r\n )}\r\n >\r\n <TriggerIcon />\r\n <span className=\"sr-only\">{tooltip ?? 'Toggle theme'}</span>\r\n </button>\r\n </DropdownMenu.Trigger>\r\n );\r\n\r\n return (\r\n <DropdownMenu.Root>\r\n {tooltip ? (\r\n <Tooltip.Provider delayDuration={300}>\r\n <Tooltip.Root>\r\n <Tooltip.Trigger asChild>{trigger}</Tooltip.Trigger>\r\n <Tooltip.Portal>\r\n <Tooltip.Content\r\n className=\"rounded-md bg-[hsl(var(--popover))] px-3 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-md border border-[hsl(var(--border))] animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={5}\r\n >\r\n {tooltip}\r\n <Tooltip.Arrow className=\"fill-[hsl(var(--popover))]\" />\r\n </Tooltip.Content>\r\n </Tooltip.Portal>\r\n </Tooltip.Root>\r\n </Tooltip.Provider>\r\n ) : (\r\n trigger\r\n )}\r\n\r\n <DropdownMenu.Portal>\r\n <DropdownMenu.Content\r\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={5}\r\n align=\"end\"\r\n >\r\n {options.map(({ value, label, Icon }) => (\r\n <DropdownMenu.Item\r\n key={value}\r\n className={cn(\r\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))]',\r\n mode === value && 'bg-[hsl(var(--accent))]',\r\n )}\r\n onSelect={() => onModeChange(value)}\r\n >\r\n <Icon className=\"h-4 w-4\" />\r\n {label}\r\n </DropdownMenu.Item>\r\n ))}\r\n </DropdownMenu.Content>\r\n </DropdownMenu.Portal>\r\n </DropdownMenu.Root>\r\n );\r\n}\r\n\r\n// ---------- Sub-menu variant (for embedding in user dropdown) ----------\r\n\r\nfunction SunMoonIcon({ className }: { className?: string }) {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <path d=\"M12 8a2.83 2.83 0 0 0 4 4 4 4 0 1 1-4-4\" />\r\n <path d=\"M12 2v2\" /><path d=\"M12 20v2\" />\r\n <path d=\"m4.9 4.9 1.4 1.4\" /><path d=\"m17.7 17.7 1.4 1.4\" />\r\n <path d=\"M2 12h2\" /><path d=\"M20 12h2\" />\r\n <path d=\"m6.3 17.7-1.4 1.4\" /><path d=\"m19.1 4.9-1.4 1.4\" />\r\n </svg>\r\n );\r\n}\r\n\r\nexport interface DarkModeSubMenuProps {\r\n mode: DarkModeValue;\r\n onModeChange: (mode: DarkModeValue) => void;\r\n label?: string;\r\n labels?: { auto?: string; light?: string; dark?: string };\r\n}\r\n\r\n/**\r\n * A DropdownMenuSub component for embedding dark mode selector\r\n * inside a Radix DropdownMenu (e.g. user avatar menu).\r\n * Must be rendered as a child of DropdownMenu.Group / DropdownMenu.Content.\r\n */\r\nexport function DarkModeSubMenu({\r\n mode,\r\n onModeChange,\r\n label = '外观',\r\n labels = {},\r\n}: DarkModeSubMenuProps) {\r\n const resolvedLabels = {\r\n auto: labels.auto ?? '跟随系统',\r\n light: labels.light ?? '浅色模式',\r\n dark: labels.dark ?? '深色模式',\r\n };\r\n\r\n const currentLabel = mode === 'auto' ? resolvedLabels.auto : mode === 'dark' ? resolvedLabels.dark : resolvedLabels.light;\r\n\r\n const options: { value: DarkModeValue; label: string; Icon: React.FC<{ className?: string }> }[] = [\r\n { value: 'auto', label: resolvedLabels.auto, Icon: MonitorIcon },\r\n { value: 'light', label: resolvedLabels.light, Icon: SunIcon },\r\n { value: 'dark', label: resolvedLabels.dark, Icon: MoonIcon },\r\n ];\r\n\r\n return (\r\n <DropdownMenu.Sub>\r\n <DropdownMenu.SubTrigger className=\"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[state=open]:bg-[hsl(var(--accent))]\">\r\n <SunMoonIcon className=\"h-4 w-4\" />\r\n <span>{label}</span>\r\n <span className=\"ml-auto text-xs text-[hsl(var(--muted-foreground))]\">{currentLabel}</span>\r\n </DropdownMenu.SubTrigger>\r\n <DropdownMenu.Portal>\r\n <DropdownMenu.SubContent\r\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={8}\r\n >\r\n {options.map(({ value, label: optLabel, Icon }) => (\r\n <DropdownMenu.CheckboxItem\r\n key={value}\r\n checked={mode === value}\r\n disabled={mode === value}\r\n className={cn(\r\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 pl-7 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\r\n )}\r\n onCheckedChange={() => onModeChange(value)}\r\n >\r\n <DropdownMenu.ItemIndicator className=\"absolute left-2 inline-flex items-center justify-center\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>\r\n </DropdownMenu.ItemIndicator>\r\n <Icon className=\"h-4 w-4\" />\r\n {optLabel}\r\n </DropdownMenu.CheckboxItem>\r\n ))}\r\n </DropdownMenu.SubContent>\r\n </DropdownMenu.Portal>\r\n </DropdownMenu.Sub>\r\n );\r\n}\r\n","import * as React from 'react';\r\nimport * as DropdownMenu from '@radix-ui/react-dropdown-menu';\r\nimport * as Tooltip from '@radix-ui/react-tooltip';\r\n\r\nfunction cn(...inputs: (string | undefined | null | false)[]): string {\r\n return inputs.filter(Boolean).join(' ');\r\n}\r\n\r\n// ---------- Inline SVG Icon ----------\r\n\r\nfunction GlobeIcon({ className }: { className?: string }) {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\r\n <path d=\"M2 12h20\" />\r\n </svg>\r\n );\r\n}\r\n\r\n// ---------- Component ----------\r\n\r\nexport interface I18nLanguage {\r\n code: string;\r\n label: string;\r\n}\r\n\r\nexport interface I18nSelectorProps {\r\n languages: I18nLanguage[];\r\n currentLanguage: string;\r\n onLanguageChange: (code: string) => void;\r\n tooltip?: string;\r\n className?: string;\r\n}\r\n\r\nexport function I18nSelector({\r\n languages,\r\n currentLanguage,\r\n onLanguageChange,\r\n tooltip,\r\n className,\r\n}: I18nSelectorProps) {\r\n const trigger = (\r\n <DropdownMenu.Trigger asChild>\r\n <button\r\n className={cn(\r\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] transition-colors focus-visible:outline-none',\r\n className,\r\n )}\r\n >\r\n <GlobeIcon />\r\n <span className=\"sr-only\">{tooltip ?? 'Switch language'}</span>\r\n </button>\r\n </DropdownMenu.Trigger>\r\n );\r\n\r\n return (\r\n <DropdownMenu.Root>\r\n {tooltip ? (\r\n <Tooltip.Provider delayDuration={300}>\r\n <Tooltip.Root>\r\n <Tooltip.Trigger asChild>{trigger}</Tooltip.Trigger>\r\n <Tooltip.Portal>\r\n <Tooltip.Content\r\n className=\"rounded-md bg-[hsl(var(--popover))] px-3 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-md border border-[hsl(var(--border))] animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={5}\r\n >\r\n {tooltip}\r\n <Tooltip.Arrow className=\"fill-[hsl(var(--popover))]\" />\r\n </Tooltip.Content>\r\n </Tooltip.Portal>\r\n </Tooltip.Root>\r\n </Tooltip.Provider>\r\n ) : (\r\n trigger\r\n )}\r\n\r\n <DropdownMenu.Portal>\r\n <DropdownMenu.Content\r\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={5}\r\n align=\"end\"\r\n >\r\n {languages.map(({ code, label }) => (\r\n <DropdownMenu.Item\r\n key={code}\r\n className={cn(\r\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))]',\r\n currentLanguage === code && 'bg-[hsl(var(--accent))]',\r\n )}\r\n onSelect={() => onLanguageChange(code)}\r\n >\r\n {label}\r\n </DropdownMenu.Item>\r\n ))}\r\n </DropdownMenu.Content>\r\n </DropdownMenu.Portal>\r\n </DropdownMenu.Root>\r\n );\r\n}\r\n\r\n// ---------- Sub-menu variant (for embedding in user dropdown) ----------\r\n\r\nexport interface I18nSubMenuProps {\r\n languages: I18nLanguage[];\r\n currentLanguage: string;\r\n onLanguageChange: (code: string) => void;\r\n label?: string;\r\n}\r\n\r\n/**\r\n * A DropdownMenuSub component for embedding language selector\r\n * inside a Radix DropdownMenu (e.g. user avatar menu).\r\n * Must be rendered as a child of DropdownMenu.Group / DropdownMenu.Content.\r\n */\r\nexport function I18nSubMenu({\r\n languages,\r\n currentLanguage,\r\n onLanguageChange,\r\n label = '语言',\r\n}: I18nSubMenuProps) {\r\n const currentLabel = languages.find((l) => l.code === currentLanguage)?.label ?? currentLanguage;\r\n\r\n return (\r\n <DropdownMenu.Sub>\r\n <DropdownMenu.SubTrigger className=\"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[state=open]:bg-[hsl(var(--accent))]\">\r\n <GlobeIcon className=\"h-4 w-4\" />\r\n <span>{label}</span>\r\n <span className=\"ml-auto text-xs text-[hsl(var(--muted-foreground))]\">{currentLabel}</span>\r\n </DropdownMenu.SubTrigger>\r\n <DropdownMenu.Portal>\r\n <DropdownMenu.SubContent\r\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={8}\r\n >\r\n {languages.map(({ code, label: langLabel }) => (\r\n <DropdownMenu.CheckboxItem\r\n key={code}\r\n checked={currentLanguage === code}\r\n disabled={currentLanguage === code}\r\n className={cn(\r\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 pl-7 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\r\n )}\r\n onCheckedChange={() => onLanguageChange(code)}\r\n >\r\n <DropdownMenu.ItemIndicator className=\"absolute left-2 inline-flex items-center justify-center\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>\r\n </DropdownMenu.ItemIndicator>\r\n {langLabel}\r\n </DropdownMenu.CheckboxItem>\r\n ))}\r\n </DropdownMenu.SubContent>\r\n </DropdownMenu.Portal>\r\n </DropdownMenu.Sub>\r\n );\r\n}\r\n","import { useEffect, useState, useCallback } from 'react';\r\n\r\nexport type DarkModeValue = 'auto' | 'light' | 'dark';\r\n\r\nconst STORAGE_KEY = 'monkeys-dark-mode';\r\n\r\nfunction getStoredMode(): DarkModeValue {\r\n if (typeof window === 'undefined') return 'auto';\r\n const stored = localStorage.getItem(STORAGE_KEY);\r\n if (stored === 'light' || stored === 'dark' || stored === 'auto') return stored;\r\n return 'auto';\r\n}\r\n\r\nfunction getSystemPrefersDark(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n}\r\n\r\nfunction resolve(mode: DarkModeValue): 'light' | 'dark' {\r\n if (mode === 'auto') return getSystemPrefersDark() ? 'dark' : 'light';\r\n return mode;\r\n}\r\n\r\nfunction applyClass(resolved: 'light' | 'dark') {\r\n const el = document.documentElement;\r\n if (resolved === 'dark') {\r\n el.classList.add('dark');\r\n } else {\r\n el.classList.remove('dark');\r\n }\r\n}\r\n\r\nexport interface UseDarkModeReturn {\r\n mode: DarkModeValue;\r\n setMode: (mode: DarkModeValue) => void;\r\n resolvedMode: 'light' | 'dark';\r\n}\r\n\r\n/**\r\n * Reads/writes dark-mode preference to localStorage, listens to\r\n * `prefers-color-scheme` for auto mode, and toggles `.dark` on `<html>`.\r\n */\r\nexport function useDarkMode(): UseDarkModeReturn {\r\n const [mode, setModeState] = useState<DarkModeValue>(getStoredMode);\r\n const [resolvedMode, setResolvedMode] = useState<'light' | 'dark'>(() => resolve(mode));\r\n\r\n const setMode = useCallback((next: DarkModeValue) => {\r\n localStorage.setItem(STORAGE_KEY, next);\r\n setModeState(next);\r\n const r = resolve(next);\r\n setResolvedMode(r);\r\n applyClass(r);\r\n }, []);\r\n\r\n // Apply on mount\r\n useEffect(() => {\r\n applyClass(resolvedMode);\r\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\r\n\r\n // Listen to system preference changes for auto mode\r\n useEffect(() => {\r\n if (mode !== 'auto') return;\r\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\r\n const handler = (e: MediaQueryListEvent) => {\r\n const r = e.matches ? 'dark' : 'light';\r\n setResolvedMode(r);\r\n applyClass(r);\r\n };\r\n mql.addEventListener('change', handler);\r\n return () => mql.removeEventListener('change', handler);\r\n }, [mode]);\r\n\r\n return { mode, setMode, resolvedMode };\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/toolbar/DarkModeSelector.tsx","../../../src/components/toolbar/I18nSelector.tsx","../../../src/components/toolbar/useDarkMode.ts"],"names":["jsxs","jsx","DropdownMenu","Tooltip","cn","DropdownMenu2","Tooltip2","useState","useCallback","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import * as React from 'react';\nimport * as DropdownMenu from '@radix-ui/react-dropdown-menu';\nimport * as Tooltip from '@radix-ui/react-tooltip';\n\nfunction cn(...inputs: (string | undefined | null | false)[]): string {\n return inputs.filter(Boolean).join(' ');\n}\n\n// ---------- Inline SVG Icons ----------\n\nfunction SunIcon({ className }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2v2\" /><path d=\"M12 20v2\" />\n <path d=\"m4.93 4.93 1.41 1.41\" /><path d=\"m17.66 17.66 1.41 1.41\" />\n <path d=\"M2 12h2\" /><path d=\"M20 12h2\" />\n <path d=\"m6.34 17.66-1.41 1.41\" /><path d=\"m19.07 4.93-1.41 1.41\" />\n </svg>\n );\n}\n\nfunction MoonIcon({ className }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\" />\n </svg>\n );\n}\n\nfunction MonitorIcon({ className }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\n </svg>\n );\n}\n\n// ---------- Component ----------\n\nexport type DarkModeValue = 'auto' | 'light' | 'dark';\n\nexport interface DarkModeSelectorProps {\n mode: DarkModeValue;\n onModeChange: (mode: DarkModeValue) => void;\n labels?: { auto?: string; light?: string; dark?: string };\n tooltip?: string;\n className?: string;\n}\n\nconst triggerIconMap: Record<DarkModeValue, React.FC<{ className?: string }>> = {\n light: SunIcon,\n dark: MoonIcon,\n auto: MonitorIcon,\n};\n\nexport function DarkModeSelector({\n mode,\n onModeChange,\n labels = {},\n tooltip,\n className,\n}: DarkModeSelectorProps) {\n const TriggerIcon = triggerIconMap[mode];\n const resolvedLabels = {\n auto: labels.auto ?? 'Auto',\n light: labels.light ?? 'Light',\n dark: labels.dark ?? 'Dark',\n };\n\n const options: { value: DarkModeValue; label: string; Icon: React.FC<{ className?: string }> }[] = [\n { value: 'auto', label: resolvedLabels.auto, Icon: MonitorIcon },\n { value: 'light', label: resolvedLabels.light, Icon: SunIcon },\n { value: 'dark', label: resolvedLabels.dark, Icon: MoonIcon },\n ];\n\n const trigger = (\n <DropdownMenu.Trigger asChild>\n <button\n className={cn(\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] transition-colors focus-visible:outline-none',\n className,\n )}\n >\n <TriggerIcon />\n <span className=\"sr-only\">{tooltip ?? 'Toggle theme'}</span>\n </button>\n </DropdownMenu.Trigger>\n );\n\n return (\n <DropdownMenu.Root>\n {tooltip ? (\n <Tooltip.Provider delayDuration={300}>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>{trigger}</Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content\n className=\"rounded-md bg-[hsl(var(--popover))] px-3 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-md border border-[hsl(var(--border))] animate-in fade-in-0 zoom-in-95\"\n sideOffset={5}\n >\n {tooltip}\n <Tooltip.Arrow className=\"fill-[hsl(var(--popover))]\" />\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </Tooltip.Provider>\n ) : (\n trigger\n )}\n\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\n sideOffset={5}\n align=\"end\"\n >\n {options.map(({ value, label, Icon }) => (\n <DropdownMenu.Item\n key={value}\n className={cn(\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))]',\n mode === value && 'bg-[hsl(var(--accent))]',\n )}\n onSelect={() => onModeChange(value)}\n >\n <Icon className=\"h-4 w-4\" />\n {label}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n );\n}\n\n// ---------- Sub-menu variant (for embedding in user dropdown) ----------\n\nfunction SunMoonIcon({ className }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M12 8a2.83 2.83 0 0 0 4 4 4 4 0 1 1-4-4\" />\n <path d=\"M12 2v2\" /><path d=\"M12 20v2\" />\n <path d=\"m4.9 4.9 1.4 1.4\" /><path d=\"m17.7 17.7 1.4 1.4\" />\n <path d=\"M2 12h2\" /><path d=\"M20 12h2\" />\n <path d=\"m6.3 17.7-1.4 1.4\" /><path d=\"m19.1 4.9-1.4 1.4\" />\n </svg>\n );\n}\n\nexport interface DarkModeSubMenuProps {\n mode: DarkModeValue;\n onModeChange: (mode: DarkModeValue) => void;\n label?: string;\n labels?: { auto?: string; light?: string; dark?: string };\n}\n\n/**\n * A DropdownMenuSub component for embedding dark mode selector\n * inside a Radix DropdownMenu (e.g. user avatar menu).\n * Must be rendered as a child of DropdownMenu.Group / DropdownMenu.Content.\n */\nexport function DarkModeSubMenu({\n mode,\n onModeChange,\n label = '外观',\n labels = {},\n}: DarkModeSubMenuProps) {\n const resolvedLabels = {\n auto: labels.auto ?? '跟随系统',\n light: labels.light ?? '浅色模式',\n dark: labels.dark ?? '深色模式',\n };\n\n const currentLabel = mode === 'auto' ? resolvedLabels.auto : mode === 'dark' ? resolvedLabels.dark : resolvedLabels.light;\n\n const options: { value: DarkModeValue; label: string; Icon: React.FC<{ className?: string }> }[] = [\n { value: 'auto', label: resolvedLabels.auto, Icon: MonitorIcon },\n { value: 'light', label: resolvedLabels.light, Icon: SunIcon },\n { value: 'dark', label: resolvedLabels.dark, Icon: MoonIcon },\n ];\n\n return (\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger className=\"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[state=open]:bg-[hsl(var(--accent))]\">\n <SunMoonIcon className=\"h-4 w-4\" />\n <span>{label}</span>\n <span className=\"ml-auto text-xs text-[hsl(var(--muted-foreground))]\">{currentLabel}</span>\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\n sideOffset={8}\n >\n {options.map(({ value, label: optLabel, Icon }) => (\n <DropdownMenu.CheckboxItem\n key={value}\n checked={mode === value}\n disabled={mode === value}\n className={cn(\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 pl-7 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n )}\n onCheckedChange={() => onModeChange(value)}\n >\n <DropdownMenu.ItemIndicator className=\"absolute left-2 inline-flex items-center justify-center\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>\n </DropdownMenu.ItemIndicator>\n <Icon className=\"h-4 w-4\" />\n {optLabel}\n </DropdownMenu.CheckboxItem>\n ))}\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n );\n}\n","import * as React from 'react';\nimport * as DropdownMenu from '@radix-ui/react-dropdown-menu';\nimport * as Tooltip from '@radix-ui/react-tooltip';\n\nfunction cn(...inputs: (string | undefined | null | false)[]): string {\n return inputs.filter(Boolean).join(' ');\n}\n\n// ---------- Inline SVG Icon ----------\n\nfunction GlobeIcon({ className }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n <path d=\"M2 12h20\" />\n </svg>\n );\n}\n\n// ---------- Component ----------\n\nexport interface I18nLanguage {\n code: string;\n label: string;\n}\n\nexport interface I18nSelectorProps {\n languages: I18nLanguage[];\n currentLanguage: string;\n onLanguageChange: (code: string) => void;\n tooltip?: string;\n className?: string;\n}\n\nexport function I18nSelector({\n languages,\n currentLanguage,\n onLanguageChange,\n tooltip,\n className,\n}: I18nSelectorProps) {\n const trigger = (\n <DropdownMenu.Trigger asChild>\n <button\n className={cn(\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] transition-colors focus-visible:outline-none',\n className,\n )}\n >\n <GlobeIcon />\n <span className=\"sr-only\">{tooltip ?? 'Switch language'}</span>\n </button>\n </DropdownMenu.Trigger>\n );\n\n return (\n <DropdownMenu.Root>\n {tooltip ? (\n <Tooltip.Provider delayDuration={300}>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>{trigger}</Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content\n className=\"rounded-md bg-[hsl(var(--popover))] px-3 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-md border border-[hsl(var(--border))] animate-in fade-in-0 zoom-in-95\"\n sideOffset={5}\n >\n {tooltip}\n <Tooltip.Arrow className=\"fill-[hsl(var(--popover))]\" />\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </Tooltip.Provider>\n ) : (\n trigger\n )}\n\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\n sideOffset={5}\n align=\"end\"\n >\n {languages.map(({ code, label }) => (\n <DropdownMenu.Item\n key={code}\n className={cn(\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))]',\n currentLanguage === code && 'bg-[hsl(var(--accent))]',\n )}\n onSelect={() => onLanguageChange(code)}\n >\n {label}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n );\n}\n\n// ---------- Sub-menu variant (for embedding in user dropdown) ----------\n\nexport interface I18nSubMenuProps {\n languages: I18nLanguage[];\n currentLanguage: string;\n onLanguageChange: (code: string) => void;\n label?: string;\n}\n\n/**\n * A DropdownMenuSub component for embedding language selector\n * inside a Radix DropdownMenu (e.g. user avatar menu).\n * Must be rendered as a child of DropdownMenu.Group / DropdownMenu.Content.\n */\nexport function I18nSubMenu({\n languages,\n currentLanguage,\n onLanguageChange,\n label = '语言',\n}: I18nSubMenuProps) {\n const currentLabel = languages.find((l) => l.code === currentLanguage)?.label ?? currentLanguage;\n\n return (\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger className=\"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[state=open]:bg-[hsl(var(--accent))]\">\n <GlobeIcon className=\"h-4 w-4\" />\n <span>{label}</span>\n <span className=\"ml-auto text-xs text-[hsl(var(--muted-foreground))]\">{currentLabel}</span>\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\n sideOffset={8}\n >\n {languages.map(({ code, label: langLabel }) => (\n <DropdownMenu.CheckboxItem\n key={code}\n checked={currentLanguage === code}\n disabled={currentLanguage === code}\n className={cn(\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 pl-7 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n )}\n onCheckedChange={() => onLanguageChange(code)}\n >\n <DropdownMenu.ItemIndicator className=\"absolute left-2 inline-flex items-center justify-center\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>\n </DropdownMenu.ItemIndicator>\n {langLabel}\n </DropdownMenu.CheckboxItem>\n ))}\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n );\n}\n","import { useEffect, useState, useCallback } from 'react';\n\nexport type DarkModeValue = 'auto' | 'light' | 'dark';\n\nconst STORAGE_KEY = 'monkeys-dark-mode';\n\nfunction getStoredMode(): DarkModeValue {\n if (typeof window === 'undefined') return 'auto';\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored === 'light' || stored === 'dark' || stored === 'auto') return stored;\n return 'auto';\n}\n\nfunction getSystemPrefersDark(): boolean {\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n}\n\nfunction resolve(mode: DarkModeValue): 'light' | 'dark' {\n if (mode === 'auto') return getSystemPrefersDark() ? 'dark' : 'light';\n return mode;\n}\n\nfunction applyClass(resolved: 'light' | 'dark') {\n const el = document.documentElement;\n if (resolved === 'dark') {\n el.classList.add('dark');\n } else {\n el.classList.remove('dark');\n }\n}\n\nexport interface UseDarkModeReturn {\n mode: DarkModeValue;\n setMode: (mode: DarkModeValue) => void;\n resolvedMode: 'light' | 'dark';\n}\n\n/**\n * Reads/writes dark-mode preference to localStorage, listens to\n * `prefers-color-scheme` for auto mode, and toggles `.dark` on `<html>`.\n */\nexport function useDarkMode(): UseDarkModeReturn {\n const [mode, setModeState] = useState<DarkModeValue>(getStoredMode);\n const [resolvedMode, setResolvedMode] = useState<'light' | 'dark'>(() => resolve(mode));\n\n const setMode = useCallback((next: DarkModeValue) => {\n localStorage.setItem(STORAGE_KEY, next);\n setModeState(next);\n const r = resolve(next);\n setResolvedMode(r);\n applyClass(r);\n }, []);\n\n // Apply on mount\n useEffect(() => {\n applyClass(resolvedMode);\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Listen to system preference changes for auto mode\n useEffect(() => {\n if (mode !== 'auto') return;\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => {\n const r = e.matches ? 'dark' : 'light';\n setResolvedMode(r);\n applyClass(r);\n };\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n }, [mode]);\n\n return { mode, setMode, resolvedMode };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/toolbar/DarkModeSelector.tsx","../../../src/components/toolbar/I18nSelector.tsx","../../../src/components/toolbar/useDarkMode.ts"],"names":["cn","jsxs","jsx","DropdownMenu2","Tooltip2"],"mappings":";;;;;;AAIA,SAAS,MAAM,MAAA,EAAuD;AACpE,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AACxC;AAIA,SAAS,OAAA,CAAQ,EAAE,SAAA,EAAU,EAA2B;AACtD,EAAA,uBACE,IAAA,CAAC,SAAI,KAAA,EAAM,4BAAA,EAA6B,OAAM,IAAA,EAAK,MAAA,EAAO,MAAK,OAAA,EAAQ,WAAA,EAAY,MAAK,MAAA,EAAO,MAAA,EAAO,gBAAe,WAAA,EAAY,GAAA,EAAI,eAAc,OAAA,EAAQ,cAAA,EAAe,SAAQ,SAAA,EAChL,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,YAAO,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,GAAE,GAAA,EAAI,CAAA;AAAA,oBAC9B,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,SAAA,EAAU,CAAA;AAAA,oBAAE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,UAAA,EAAW,CAAA;AAAA,oBACvC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,sBAAA,EAAuB,CAAA;AAAA,oBAAE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,wBAAA,EAAyB,CAAA;AAAA,oBAClE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,SAAA,EAAU,CAAA;AAAA,oBAAE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,UAAA,EAAW,CAAA;AAAA,oBACvC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,uBAAA,EAAwB,CAAA;AAAA,oBAAE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,uBAAA,EAAwB;AAAA,GAAA,EACpE,CAAA;AAEJ;AAEA,SAAS,QAAA,CAAS,EAAE,SAAA,EAAU,EAA2B;AACvD,EAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,4BAAA,EAA6B,KAAA,EAAM,MAAK,MAAA,EAAO,IAAA,EAAK,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,MAAA,EAAO,QAAO,cAAA,EAAe,WAAA,EAAY,GAAA,EAAI,aAAA,EAAc,OAAA,EAAQ,cAAA,EAAe,OAAA,EAAQ,SAAA,EAChL,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,oCAAA,EAAqC,CAAA,EAC/C,CAAA;AAEJ;AAEA,SAAS,WAAA,CAAY,EAAE,SAAA,EAAU,EAA2B;AAC1D,EAAA,uBACE,IAAA,CAAC,SAAI,KAAA,EAAM,4BAAA,EAA6B,OAAM,IAAA,EAAK,MAAA,EAAO,MAAK,OAAA,EAAQ,WAAA,EAAY,MAAK,MAAA,EAAO,MAAA,EAAO,gBAAe,WAAA,EAAY,GAAA,EAAI,eAAc,OAAA,EAAQ,cAAA,EAAe,SAAQ,SAAA,EAChL,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,GAAE,GAAA,EAAI,CAAA,EAAE,GAAA,EAAI,EAAA,EAAG,GAAA,EAAI,CAAA;AAAA,oBAChD,GAAA,CAAC,UAAK,EAAA,EAAG,GAAA,EAAI,IAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,CAAA;AAAA,oBACrC,GAAA,CAAC,UAAK,EAAA,EAAG,IAAA,EAAK,IAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK;AAAA,GAAA,EACxC,CAAA;AAEJ;AAcA,IAAM,cAAA,GAA0E;AAAA,EAC9E,KAAA,EAAO,OAAA;AAAA,EACP,IAAA,EAAM,QAAA;AAAA,EACN,IAAA,EAAM;AACR,CAAA;AAEO,SAAS,gBAAA,CAAiB;AAAA,EAC/B,IAAA;AAAA,EACA,YAAA;AAAA,EACA,SAAS,EAAC;AAAA,EACV,OAAA;AAAA,EACA;AACF,CAAA,EAA0B;AACxB,EAAA,MAAM,WAAA,GAAc,eAAe,IAAI,CAAA;AACvC,EAAA,MAAM,cAAA,GAAiB;AAAA,IACrB,IAAA,EAAM,OAAO,IAAA,IAAQ,MAAA;AAAA,IACrB,KAAA,EAAO,OAAO,KAAA,IAAS,OAAA;AAAA,IACvB,IAAA,EAAM,OAAO,IAAA,IAAQ;AAAA,GACvB;AAEA,EAAA,MAAM,OAAA,GAA6F;AAAA,IACjG,EAAE,KAAA,EAAO,MAAA,EAAQ,OAAO,cAAA,CAAe,IAAA,EAAM,MAAM,WAAA,EAAY;AAAA,IAC/D,EAAE,KAAA,EAAO,OAAA,EAAS,OAAO,cAAA,CAAe,KAAA,EAAO,MAAM,OAAA,EAAQ;AAAA,IAC7D,EAAE,KAAA,EAAO,MAAA,EAAQ,OAAO,cAAA,CAAe,IAAA,EAAM,MAAM,QAAA;AAAS,GAC9D;AAEA,EAAA,MAAM,OAAA,mBACJ,GAAA,CAAc,YAAA,CAAA,OAAA,EAAb,EAAqB,SAAO,IAAA,EAC3B,QAAA,kBAAA,IAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,gNAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAA,GAAA,CAAC,WAAA,EAAA,EAAY,CAAA;AAAA,wBACb,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EAAW,qBAAW,cAAA,EAAe;AAAA;AAAA;AAAA,GACvD,EACF,CAAA;AAGF,EAAA,uBACE,IAAA,CAAc,mBAAb,EACE,QAAA,EAAA;AAAA,IAAA,OAAA,uBACU,OAAA,CAAA,QAAA,EAAR,EAAiB,eAAe,GAAA,EAC/B,QAAA,kBAAA,IAAA,CAAS,cAAR,EACC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAS,OAAA,CAAA,OAAA,EAAR,EAAgB,OAAA,EAAO,IAAA,EAAE,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,sBAClC,GAAA,CAAS,gBAAR,EACC,QAAA,kBAAA,IAAA;AAAA,QAAS,OAAA,CAAA,OAAA;AAAA,QAAR;AAAA,UACC,SAAA,EAAU,4KAAA;AAAA,UACV,UAAA,EAAY,CAAA;AAAA,UAEX,QAAA,EAAA;AAAA,YAAA,OAAA;AAAA,4BACD,GAAA,CAAS,OAAA,CAAA,KAAA,EAAR,EAAc,SAAA,EAAU,4BAAA,EAA6B;AAAA;AAAA;AAAA,OACxD,EACF;AAAA,KAAA,EACF,GACF,CAAA,GAEA,OAAA;AAAA,oBAGF,GAAA,CAAc,qBAAb,EACC,QAAA,kBAAA,GAAA;AAAA,MAAc,YAAA,CAAA,OAAA;AAAA,MAAb;AAAA,QACC,SAAA,EAAU,8KAAA;AAAA,QACV,UAAA,EAAY,CAAA;AAAA,QACZ,KAAA,EAAM,KAAA;AAAA,QAEL,kBAAQ,GAAA,CAAI,CAAC,EAAE,KAAA,EAAO,KAAA,EAAO,MAAK,qBACjC,IAAA;AAAA,UAAc,YAAA,CAAA,IAAA;AAAA,UAAb;AAAA,YAEC,SAAA,EAAW,EAAA;AAAA,cACT,oMAAA;AAAA,cACA,SAAS,KAAA,IAAS;AAAA,aACpB;AAAA,YACA,QAAA,EAAU,MAAM,YAAA,CAAa,KAAK,CAAA;AAAA,YAElC,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAC,IAAA,EAAA,EAAK,WAAU,SAAA,EAAU,CAAA;AAAA,cACzB;AAAA;AAAA,WAAA;AAAA,UARI;AAAA,SAUR;AAAA;AAAA,KACH,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;AAIA,SAAS,WAAA,CAAY,EAAE,SAAA,EAAU,EAA2B;AAC1D,EAAA,uBACE,IAAA,CAAC,SAAI,KAAA,EAAM,4BAAA,EAA6B,OAAM,IAAA,EAAK,MAAA,EAAO,MAAK,OAAA,EAAQ,WAAA,EAAY,MAAK,MAAA,EAAO,MAAA,EAAO,gBAAe,WAAA,EAAY,KAAA,EAAM,eAAc,OAAA,EAAQ,cAAA,EAAe,SAAQ,SAAA,EAClL,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,GAAE,yCAAA,EAA0C,CAAA;AAAA,oBAClD,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,SAAA,EAAU,CAAA;AAAA,oBAAE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,UAAA,EAAW,CAAA;AAAA,oBACvC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,kBAAA,EAAmB,CAAA;AAAA,oBAAE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,oBAAA,EAAqB,CAAA;AAAA,oBAC1D,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,SAAA,EAAU,CAAA;AAAA,oBAAE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,UAAA,EAAW,CAAA;AAAA,oBACvC,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,mBAAA,EAAoB,CAAA;AAAA,oBAAE,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,mBAAA,EAAoB;AAAA,GAAA,EAC5D,CAAA;AAEJ;AAcO,SAAS,eAAA,CAAgB;AAAA,EAC9B,IAAA;AAAA,EACA,YAAA;AAAA,EACA,KAAA,GAAQ,cAAA;AAAA,EACR,SAAS;AACX,CAAA,EAAyB;AACvB,EAAA,MAAM,cAAA,GAAiB;AAAA,IACrB,IAAA,EAAM,OAAO,IAAA,IAAQ,0BAAA;AAAA,IACrB,KAAA,EAAO,OAAO,KAAA,IAAS,0BAAA;AAAA,IACvB,IAAA,EAAM,OAAO,IAAA,IAAQ;AAAA,GACvB;AAEA,EAAA,MAAM,YAAA,GAAe,SAAS,MAAA,GAAS,cAAA,CAAe,OAAO,IAAA,KAAS,MAAA,GAAS,cAAA,CAAe,IAAA,GAAO,cAAA,CAAe,KAAA;AAEpH,EAAA,MAAM,OAAA,GAA6F;AAAA,IACjG,EAAE,KAAA,EAAO,MAAA,EAAQ,OAAO,cAAA,CAAe,IAAA,EAAM,MAAM,WAAA,EAAY;AAAA,IAC/D,EAAE,KAAA,EAAO,OAAA,EAAS,OAAO,cAAA,CAAe,KAAA,EAAO,MAAM,OAAA,EAAQ;AAAA,IAC7D,EAAE,KAAA,EAAO,MAAA,EAAQ,OAAO,cAAA,CAAe,IAAA,EAAM,MAAM,QAAA;AAAS,GAC9D;AAEA,EAAA,uBACE,IAAA,CAAc,kBAAb,EACC,QAAA,EAAA;AAAA,oBAAA,IAAA,CAAc,YAAA,CAAA,UAAA,EAAb,EAAwB,SAAA,EAAU,8OAAA,EACjC,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,WAAA,EAAA,EAAY,WAAU,SAAA,EAAU,CAAA;AAAA,sBACjC,GAAA,CAAC,UAAM,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,sBACb,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,qDAAA,EAAuD,QAAA,EAAA,YAAA,EAAa;AAAA,KAAA,EACtF,CAAA;AAAA,oBACA,GAAA,CAAc,qBAAb,EACC,QAAA,kBAAA,GAAA;AAAA,MAAc,YAAA,CAAA,UAAA;AAAA,MAAb;AAAA,QACC,SAAA,EAAU,8KAAA;AAAA,QACV,UAAA,EAAY,CAAA;AAAA,QAEX,QAAA,EAAA,OAAA,CAAQ,IAAI,CAAC,EAAE,OAAO,KAAA,EAAO,QAAA,EAAU,MAAK,qBAC3C,IAAA;AAAA,UAAc,YAAA,CAAA,YAAA;AAAA,UAAb;AAAA,YAEC,SAAS,IAAA,KAAS,KAAA;AAAA,YAClB,UAAU,IAAA,KAAS,KAAA;AAAA,YACnB,SAAA,EAAW,EAAA;AAAA,cACT;AAAA,aACF;AAAA,YACA,eAAA,EAAiB,MAAM,YAAA,CAAa,KAAK,CAAA;AAAA,YAEzC,QAAA,EAAA;AAAA,8BAAA,GAAA,CAAc,YAAA,CAAA,aAAA,EAAb,EAA2B,SAAA,EAAU,yDAAA,EACpC,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,4BAAA,EAA6B,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,IAAA,EAAK,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,cAAA,EAAe,WAAA,EAAY,GAAA,EAAI,aAAA,EAAc,OAAA,EAAQ,cAAA,EAAe,OAAA,EAAQ,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,iBAAA,EAAiB,GAAE,CAAA,EAC/M,CAAA;AAAA,8BACA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EAAU,CAAA;AAAA,cACzB;AAAA;AAAA,WAAA;AAAA,UAZI;AAAA,SAcR;AAAA;AAAA,KACH,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;ACrNA,SAASA,OAAM,MAAA,EAAuD;AACpE,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA,CAAE,KAAK,GAAG,CAAA;AACxC;AAIA,SAAS,SAAA,CAAU,EAAE,SAAA,EAAU,EAA2B;AACxD,EAAA,uBACEC,KAAC,KAAA,EAAA,EAAI,KAAA,EAAM,8BAA6B,KAAA,EAAM,IAAA,EAAK,QAAO,IAAA,EAAK,OAAA,EAAQ,aAAY,IAAA,EAAK,MAAA,EAAO,QAAO,cAAA,EAAe,WAAA,EAAY,KAAI,aAAA,EAAc,OAAA,EAAQ,cAAA,EAAe,OAAA,EAAQ,SAAA,EAChL,QAAA,EAAA;AAAA,oBAAAC,IAAC,QAAA,EAAA,EAAO,EAAA,EAAG,MAAK,EAAA,EAAG,IAAA,EAAK,GAAE,IAAA,EAAK,CAAA;AAAA,oBAC/BA,GAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,iDAAA,EAAkD,CAAA;AAAA,oBAC1DA,GAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,UAAA,EAAW;AAAA,GAAA,EACrB,CAAA;AAEJ;AAiBO,SAAS,YAAA,CAAa;AAAA,EAC3B,SAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,OAAA;AAAA,EACA;AACF,CAAA,EAAsB;AACpB,EAAA,MAAM,0BACJA,GAAAA,CAAcC,sBAAb,EAAqB,OAAA,EAAO,MAC3B,QAAA,kBAAAF,IAAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAWD,GAAAA;AAAA,QACT,gNAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEA,QAAA,EAAA;AAAA,wBAAAE,IAAC,SAAA,EAAA,EAAU,CAAA;AAAA,wBACXA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,SAAA,EAAW,qBAAW,iBAAA,EAAkB;AAAA;AAAA;AAAA,GAC1D,EACF,CAAA;AAGF,EAAA,uBACED,IAAAA,CAAcE,YAAA,CAAA,IAAA,EAAb,EACE,QAAA,EAAA;AAAA,IAAA,OAAA,mBACCD,IAASE,OAAA,CAAA,QAAA,EAAR,EAAiB,eAAe,GAAA,EAC/B,QAAA,kBAAAH,IAAAA,CAASG,OAAA,CAAA,IAAA,EAAR,EACC,QAAA,EAAA;AAAA,sBAAAF,GAAAA,CAASE,OAAA,CAAA,OAAA,EAAR,EAAgB,OAAA,EAAO,MAAE,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,sBAClCF,GAAAA,CAASE,OAAA,CAAA,MAAA,EAAR,EACC,QAAA,kBAAAH,IAAAA;AAAA,QAASG,OAAA,CAAA,OAAA;AAAA,QAAR;AAAA,UACC,SAAA,EAAU,4KAAA;AAAA,UACV,UAAA,EAAY,CAAA;AAAA,UAEX,QAAA,EAAA;AAAA,YAAA,OAAA;AAAA,4BACDF,GAAAA,CAASE,OAAA,CAAA,KAAA,EAAR,EAAc,WAAU,4BAAA,EAA6B;AAAA;AAAA;AAAA,OACxD,EACF;AAAA,KAAA,EACF,GACF,CAAA,GAEA,OAAA;AAAA,oBAGFF,GAAAA,CAAcC,YAAA,CAAA,MAAA,EAAb,EACC,QAAA,kBAAAD,GAAAA;AAAA,MAAcC,YAAA,CAAA,OAAA;AAAA,MAAb;AAAA,QACC,SAAA,EAAU,8KAAA;AAAA,QACV,UAAA,EAAY,CAAA;AAAA,QACZ,KAAA,EAAM,KAAA;AAAA,QAEL,oBAAU,GAAA,CAAI,CAAC,EAAE,IAAA,EAAM,KAAA,uBACtBD,GAAAA;AAAA,UAAcC,YAAA,CAAA,IAAA;AAAA,UAAb;AAAA,YAEC,SAAA,EAAWH,GAAAA;AAAA,cACT,oMAAA;AAAA,cACA,oBAAoB,IAAA,IAAQ;AAAA,aAC9B;AAAA,YACA,QAAA,EAAU,MAAM,gBAAA,CAAiB,IAAI,CAAA;AAAA,YAEpC,QAAA,EAAA;AAAA,WAAA;AAAA,UAPI;AAAA,SASR;AAAA;AAAA,KACH,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;AAgBO,SAAS,WAAA,CAAY;AAAA,EAC1B,SAAA;AAAA,EACA,eAAA;AAAA,EACA,gBAAA;AAAA,EACA,KAAA,GAAQ;AACV,CAAA,EAAqB;AACnB,EAAA,MAAM,YAAA,GAAe,UAAU,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,eAAe,CAAA,EAAG,KAAA,IAAS,eAAA;AAEjF,EAAA,uBACEC,IAAAA,CAAcE,YAAA,CAAA,GAAA,EAAb,EACC,QAAA,EAAA;AAAA,oBAAAF,IAAAA,CAAcE,YAAA,CAAA,UAAA,EAAb,EAAwB,SAAA,EAAU,8OAAA,EACjC,QAAA,EAAA;AAAA,sBAAAD,GAAAA,CAAC,SAAA,EAAA,EAAU,SAAA,EAAU,SAAA,EAAU,CAAA;AAAA,sBAC/BA,GAAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,sBACbA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,uDAAuD,QAAA,EAAA,YAAA,EAAa;AAAA,KAAA,EACtF,CAAA;AAAA,oBACAA,GAAAA,CAAcC,YAAA,CAAA,MAAA,EAAb,EACC,QAAA,kBAAAD,GAAAA;AAAA,MAAcC,YAAA,CAAA,UAAA;AAAA,MAAb;AAAA,QACC,SAAA,EAAU,8KAAA;AAAA,QACV,UAAA,EAAY,CAAA;AAAA,QAEX,QAAA,EAAA,SAAA,CAAU,IAAI,CAAC,EAAE,MAAM,KAAA,EAAO,SAAA,uBAC7BF,IAAAA;AAAA,UAAcE,YAAA,CAAA,YAAA;AAAA,UAAb;AAAA,YAEC,SAAS,eAAA,KAAoB,IAAA;AAAA,YAC7B,UAAU,eAAA,KAAoB,IAAA;AAAA,YAC9B,SAAA,EAAWH,GAAAA;AAAA,cACT;AAAA,aACF;AAAA,YACA,eAAA,EAAiB,MAAM,gBAAA,CAAiB,IAAI,CAAA;AAAA,YAE5C,QAAA,EAAA;AAAA,8BAAAE,GAAAA,CAAcC,YAAA,CAAA,aAAA,EAAb,EAA2B,SAAA,EAAU,2DACpC,QAAA,kBAAAD,GAAAA,CAAC,KAAA,EAAA,EAAI,KAAA,EAAM,4BAAA,EAA6B,KAAA,EAAM,IAAA,EAAK,MAAA,EAAO,MAAK,OAAA,EAAQ,WAAA,EAAY,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,cAAA,EAAe,WAAA,EAAY,GAAA,EAAI,eAAc,OAAA,EAAQ,cAAA,EAAe,OAAA,EAAQ,QAAA,kBAAAA,GAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,iBAAA,EAAiB,GAAE,CAAA,EAC/M,CAAA;AAAA,cACC;AAAA;AAAA,WAAA;AAAA,UAXI;AAAA,SAaR;AAAA;AAAA,KACH,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;ACvJA,IAAM,WAAA,GAAc,mBAAA;AAEpB,SAAS,aAAA,GAA+B;AACtC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,MAAA;AAC1C,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,OAAA,CAAQ,WAAW,CAAA;AAC/C,EAAA,IAAI,WAAW,OAAA,IAAW,MAAA,KAAW,MAAA,IAAU,MAAA,KAAW,QAAQ,OAAO,MAAA;AACzE,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,oBAAA,GAAgC;AACvC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,KAAA;AAC1C,EAAA,OAAO,MAAA,CAAO,UAAA,CAAW,8BAA8B,CAAA,CAAE,OAAA;AAC3D;AAEA,SAAS,QAAQ,IAAA,EAAuC;AACtD,EAAA,IAAI,IAAA,KAAS,MAAA,EAAQ,OAAO,oBAAA,KAAyB,MAAA,GAAS,OAAA;AAC9D,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,WAAW,QAAA,EAA4B;AAC9C,EAAA,MAAM,KAAK,QAAA,CAAS,eAAA;AACpB,EAAA,IAAI,aAAa,MAAA,EAAQ;AACvB,IAAA,EAAA,CAAG,SAAA,CAAU,IAAI,MAAM,CAAA;AAAA,EACzB,CAAA,MAAO;AACL,IAAA,EAAA,CAAG,SAAA,CAAU,OAAO,MAAM,CAAA;AAAA,EAC5B;AACF;AAYO,SAAS,WAAA,GAAiC;AAC/C,EAAA,MAAM,CAAC,IAAA,EAAM,YAAY,CAAA,GAAI,SAAwB,aAAa,CAAA;AAClE,EAAA,MAAM,CAAC,cAAc,eAAe,CAAA,GAAI,SAA2B,MAAM,OAAA,CAAQ,IAAI,CAAC,CAAA;AAEtF,EAAA,MAAM,OAAA,GAAU,WAAA,CAAY,CAAC,IAAA,KAAwB;AACnD,IAAA,YAAA,CAAa,OAAA,CAAQ,aAAa,IAAI,CAAA;AACtC,IAAA,YAAA,CAAa,IAAI,CAAA;AACjB,IAAA,MAAM,CAAA,GAAI,QAAQ,IAAI,CAAA;AACtB,IAAA,eAAA,CAAgB,CAAC,CAAA;AACjB,IAAA,UAAA,CAAW,CAAC,CAAA;AAAA,EACd,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,UAAA,CAAW,YAAY,CAAA;AAAA,EACzB,CAAA,EAAG,EAAE,CAAA;AAGL,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,SAAS,MAAA,EAAQ;AACrB,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,UAAA,CAAW,8BAA8B,CAAA;AAC5D,IAAA,MAAM,OAAA,GAAU,CAAC,CAAA,KAA2B;AAC1C,MAAA,MAAM,CAAA,GAAI,CAAA,CAAE,OAAA,GAAU,MAAA,GAAS,OAAA;AAC/B,MAAA,eAAA,CAAgB,CAAC,CAAA;AACjB,MAAA,UAAA,CAAW,CAAC,CAAA;AAAA,IACd,CAAA;AACA,IAAA,GAAA,CAAI,gBAAA,CAAiB,UAAU,OAAO,CAAA;AACtC,IAAA,OAAO,MAAM,GAAA,CAAI,mBAAA,CAAoB,QAAA,EAAU,OAAO,CAAA;AAAA,EACxD,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AAET,EAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,YAAA,EAAa;AACvC","file":"index.mjs","sourcesContent":["import * as React from 'react';\r\nimport * as DropdownMenu from '@radix-ui/react-dropdown-menu';\r\nimport * as Tooltip from '@radix-ui/react-tooltip';\r\n\r\nfunction cn(...inputs: (string | undefined | null | false)[]): string {\r\n return inputs.filter(Boolean).join(' ');\r\n}\r\n\r\n// ---------- Inline SVG Icons ----------\r\n\r\nfunction SunIcon({ className }: { className?: string }) {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\r\n <path d=\"M12 2v2\" /><path d=\"M12 20v2\" />\r\n <path d=\"m4.93 4.93 1.41 1.41\" /><path d=\"m17.66 17.66 1.41 1.41\" />\r\n <path d=\"M2 12h2\" /><path d=\"M20 12h2\" />\r\n <path d=\"m6.34 17.66-1.41 1.41\" /><path d=\"m19.07 4.93-1.41 1.41\" />\r\n </svg>\r\n );\r\n}\r\n\r\nfunction MoonIcon({ className }: { className?: string }) {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\" />\r\n </svg>\r\n );\r\n}\r\n\r\nfunction MonitorIcon({ className }: { className?: string }) {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\r\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\r\n </svg>\r\n );\r\n}\r\n\r\n// ---------- Component ----------\r\n\r\nexport type DarkModeValue = 'auto' | 'light' | 'dark';\r\n\r\nexport interface DarkModeSelectorProps {\r\n mode: DarkModeValue;\r\n onModeChange: (mode: DarkModeValue) => void;\r\n labels?: { auto?: string; light?: string; dark?: string };\r\n tooltip?: string;\r\n className?: string;\r\n}\r\n\r\nconst triggerIconMap: Record<DarkModeValue, React.FC<{ className?: string }>> = {\r\n light: SunIcon,\r\n dark: MoonIcon,\r\n auto: MonitorIcon,\r\n};\r\n\r\nexport function DarkModeSelector({\r\n mode,\r\n onModeChange,\r\n labels = {},\r\n tooltip,\r\n className,\r\n}: DarkModeSelectorProps) {\r\n const TriggerIcon = triggerIconMap[mode];\r\n const resolvedLabels = {\r\n auto: labels.auto ?? 'Auto',\r\n light: labels.light ?? 'Light',\r\n dark: labels.dark ?? 'Dark',\r\n };\r\n\r\n const options: { value: DarkModeValue; label: string; Icon: React.FC<{ className?: string }> }[] = [\r\n { value: 'auto', label: resolvedLabels.auto, Icon: MonitorIcon },\r\n { value: 'light', label: resolvedLabels.light, Icon: SunIcon },\r\n { value: 'dark', label: resolvedLabels.dark, Icon: MoonIcon },\r\n ];\r\n\r\n const trigger = (\r\n <DropdownMenu.Trigger asChild>\r\n <button\r\n className={cn(\r\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] transition-colors focus-visible:outline-none',\r\n className,\r\n )}\r\n >\r\n <TriggerIcon />\r\n <span className=\"sr-only\">{tooltip ?? 'Toggle theme'}</span>\r\n </button>\r\n </DropdownMenu.Trigger>\r\n );\r\n\r\n return (\r\n <DropdownMenu.Root>\r\n {tooltip ? (\r\n <Tooltip.Provider delayDuration={300}>\r\n <Tooltip.Root>\r\n <Tooltip.Trigger asChild>{trigger}</Tooltip.Trigger>\r\n <Tooltip.Portal>\r\n <Tooltip.Content\r\n className=\"rounded-md bg-[hsl(var(--popover))] px-3 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-md border border-[hsl(var(--border))] animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={5}\r\n >\r\n {tooltip}\r\n <Tooltip.Arrow className=\"fill-[hsl(var(--popover))]\" />\r\n </Tooltip.Content>\r\n </Tooltip.Portal>\r\n </Tooltip.Root>\r\n </Tooltip.Provider>\r\n ) : (\r\n trigger\r\n )}\r\n\r\n <DropdownMenu.Portal>\r\n <DropdownMenu.Content\r\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={5}\r\n align=\"end\"\r\n >\r\n {options.map(({ value, label, Icon }) => (\r\n <DropdownMenu.Item\r\n key={value}\r\n className={cn(\r\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))]',\r\n mode === value && 'bg-[hsl(var(--accent))]',\r\n )}\r\n onSelect={() => onModeChange(value)}\r\n >\r\n <Icon className=\"h-4 w-4\" />\r\n {label}\r\n </DropdownMenu.Item>\r\n ))}\r\n </DropdownMenu.Content>\r\n </DropdownMenu.Portal>\r\n </DropdownMenu.Root>\r\n );\r\n}\r\n\r\n// ---------- Sub-menu variant (for embedding in user dropdown) ----------\r\n\r\nfunction SunMoonIcon({ className }: { className?: string }) {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <path d=\"M12 8a2.83 2.83 0 0 0 4 4 4 4 0 1 1-4-4\" />\r\n <path d=\"M12 2v2\" /><path d=\"M12 20v2\" />\r\n <path d=\"m4.9 4.9 1.4 1.4\" /><path d=\"m17.7 17.7 1.4 1.4\" />\r\n <path d=\"M2 12h2\" /><path d=\"M20 12h2\" />\r\n <path d=\"m6.3 17.7-1.4 1.4\" /><path d=\"m19.1 4.9-1.4 1.4\" />\r\n </svg>\r\n );\r\n}\r\n\r\nexport interface DarkModeSubMenuProps {\r\n mode: DarkModeValue;\r\n onModeChange: (mode: DarkModeValue) => void;\r\n label?: string;\r\n labels?: { auto?: string; light?: string; dark?: string };\r\n}\r\n\r\n/**\r\n * A DropdownMenuSub component for embedding dark mode selector\r\n * inside a Radix DropdownMenu (e.g. user avatar menu).\r\n * Must be rendered as a child of DropdownMenu.Group / DropdownMenu.Content.\r\n */\r\nexport function DarkModeSubMenu({\r\n mode,\r\n onModeChange,\r\n label = '外观',\r\n labels = {},\r\n}: DarkModeSubMenuProps) {\r\n const resolvedLabels = {\r\n auto: labels.auto ?? '跟随系统',\r\n light: labels.light ?? '浅色模式',\r\n dark: labels.dark ?? '深色模式',\r\n };\r\n\r\n const currentLabel = mode === 'auto' ? resolvedLabels.auto : mode === 'dark' ? resolvedLabels.dark : resolvedLabels.light;\r\n\r\n const options: { value: DarkModeValue; label: string; Icon: React.FC<{ className?: string }> }[] = [\r\n { value: 'auto', label: resolvedLabels.auto, Icon: MonitorIcon },\r\n { value: 'light', label: resolvedLabels.light, Icon: SunIcon },\r\n { value: 'dark', label: resolvedLabels.dark, Icon: MoonIcon },\r\n ];\r\n\r\n return (\r\n <DropdownMenu.Sub>\r\n <DropdownMenu.SubTrigger className=\"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[state=open]:bg-[hsl(var(--accent))]\">\r\n <SunMoonIcon className=\"h-4 w-4\" />\r\n <span>{label}</span>\r\n <span className=\"ml-auto text-xs text-[hsl(var(--muted-foreground))]\">{currentLabel}</span>\r\n </DropdownMenu.SubTrigger>\r\n <DropdownMenu.Portal>\r\n <DropdownMenu.SubContent\r\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={8}\r\n >\r\n {options.map(({ value, label: optLabel, Icon }) => (\r\n <DropdownMenu.CheckboxItem\r\n key={value}\r\n checked={mode === value}\r\n disabled={mode === value}\r\n className={cn(\r\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 pl-7 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\r\n )}\r\n onCheckedChange={() => onModeChange(value)}\r\n >\r\n <DropdownMenu.ItemIndicator className=\"absolute left-2 inline-flex items-center justify-center\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>\r\n </DropdownMenu.ItemIndicator>\r\n <Icon className=\"h-4 w-4\" />\r\n {optLabel}\r\n </DropdownMenu.CheckboxItem>\r\n ))}\r\n </DropdownMenu.SubContent>\r\n </DropdownMenu.Portal>\r\n </DropdownMenu.Sub>\r\n );\r\n}\r\n","import * as React from 'react';\r\nimport * as DropdownMenu from '@radix-ui/react-dropdown-menu';\r\nimport * as Tooltip from '@radix-ui/react-tooltip';\r\n\r\nfunction cn(...inputs: (string | undefined | null | false)[]): string {\r\n return inputs.filter(Boolean).join(' ');\r\n}\r\n\r\n// ---------- Inline SVG Icon ----------\r\n\r\nfunction GlobeIcon({ className }: { className?: string }) {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\r\n <path d=\"M2 12h20\" />\r\n </svg>\r\n );\r\n}\r\n\r\n// ---------- Component ----------\r\n\r\nexport interface I18nLanguage {\r\n code: string;\r\n label: string;\r\n}\r\n\r\nexport interface I18nSelectorProps {\r\n languages: I18nLanguage[];\r\n currentLanguage: string;\r\n onLanguageChange: (code: string) => void;\r\n tooltip?: string;\r\n className?: string;\r\n}\r\n\r\nexport function I18nSelector({\r\n languages,\r\n currentLanguage,\r\n onLanguageChange,\r\n tooltip,\r\n className,\r\n}: I18nSelectorProps) {\r\n const trigger = (\r\n <DropdownMenu.Trigger asChild>\r\n <button\r\n className={cn(\r\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] transition-colors focus-visible:outline-none',\r\n className,\r\n )}\r\n >\r\n <GlobeIcon />\r\n <span className=\"sr-only\">{tooltip ?? 'Switch language'}</span>\r\n </button>\r\n </DropdownMenu.Trigger>\r\n );\r\n\r\n return (\r\n <DropdownMenu.Root>\r\n {tooltip ? (\r\n <Tooltip.Provider delayDuration={300}>\r\n <Tooltip.Root>\r\n <Tooltip.Trigger asChild>{trigger}</Tooltip.Trigger>\r\n <Tooltip.Portal>\r\n <Tooltip.Content\r\n className=\"rounded-md bg-[hsl(var(--popover))] px-3 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-md border border-[hsl(var(--border))] animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={5}\r\n >\r\n {tooltip}\r\n <Tooltip.Arrow className=\"fill-[hsl(var(--popover))]\" />\r\n </Tooltip.Content>\r\n </Tooltip.Portal>\r\n </Tooltip.Root>\r\n </Tooltip.Provider>\r\n ) : (\r\n trigger\r\n )}\r\n\r\n <DropdownMenu.Portal>\r\n <DropdownMenu.Content\r\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={5}\r\n align=\"end\"\r\n >\r\n {languages.map(({ code, label }) => (\r\n <DropdownMenu.Item\r\n key={code}\r\n className={cn(\r\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))]',\r\n currentLanguage === code && 'bg-[hsl(var(--accent))]',\r\n )}\r\n onSelect={() => onLanguageChange(code)}\r\n >\r\n {label}\r\n </DropdownMenu.Item>\r\n ))}\r\n </DropdownMenu.Content>\r\n </DropdownMenu.Portal>\r\n </DropdownMenu.Root>\r\n );\r\n}\r\n\r\n// ---------- Sub-menu variant (for embedding in user dropdown) ----------\r\n\r\nexport interface I18nSubMenuProps {\r\n languages: I18nLanguage[];\r\n currentLanguage: string;\r\n onLanguageChange: (code: string) => void;\r\n label?: string;\r\n}\r\n\r\n/**\r\n * A DropdownMenuSub component for embedding language selector\r\n * inside a Radix DropdownMenu (e.g. user avatar menu).\r\n * Must be rendered as a child of DropdownMenu.Group / DropdownMenu.Content.\r\n */\r\nexport function I18nSubMenu({\r\n languages,\r\n currentLanguage,\r\n onLanguageChange,\r\n label = '语言',\r\n}: I18nSubMenuProps) {\r\n const currentLabel = languages.find((l) => l.code === currentLanguage)?.label ?? currentLanguage;\r\n\r\n return (\r\n <DropdownMenu.Sub>\r\n <DropdownMenu.SubTrigger className=\"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[state=open]:bg-[hsl(var(--accent))]\">\r\n <GlobeIcon className=\"h-4 w-4\" />\r\n <span>{label}</span>\r\n <span className=\"ml-auto text-xs text-[hsl(var(--muted-foreground))]\">{currentLabel}</span>\r\n </DropdownMenu.SubTrigger>\r\n <DropdownMenu.Portal>\r\n <DropdownMenu.SubContent\r\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\r\n sideOffset={8}\r\n >\r\n {languages.map(({ code, label: langLabel }) => (\r\n <DropdownMenu.CheckboxItem\r\n key={code}\r\n checked={currentLanguage === code}\r\n disabled={currentLanguage === code}\r\n className={cn(\r\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 pl-7 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\r\n )}\r\n onCheckedChange={() => onLanguageChange(code)}\r\n >\r\n <DropdownMenu.ItemIndicator className=\"absolute left-2 inline-flex items-center justify-center\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>\r\n </DropdownMenu.ItemIndicator>\r\n {langLabel}\r\n </DropdownMenu.CheckboxItem>\r\n ))}\r\n </DropdownMenu.SubContent>\r\n </DropdownMenu.Portal>\r\n </DropdownMenu.Sub>\r\n );\r\n}\r\n","import { useEffect, useState, useCallback } from 'react';\r\n\r\nexport type DarkModeValue = 'auto' | 'light' | 'dark';\r\n\r\nconst STORAGE_KEY = 'monkeys-dark-mode';\r\n\r\nfunction getStoredMode(): DarkModeValue {\r\n if (typeof window === 'undefined') return 'auto';\r\n const stored = localStorage.getItem(STORAGE_KEY);\r\n if (stored === 'light' || stored === 'dark' || stored === 'auto') return stored;\r\n return 'auto';\r\n}\r\n\r\nfunction getSystemPrefersDark(): boolean {\r\n if (typeof window === 'undefined') return false;\r\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\r\n}\r\n\r\nfunction resolve(mode: DarkModeValue): 'light' | 'dark' {\r\n if (mode === 'auto') return getSystemPrefersDark() ? 'dark' : 'light';\r\n return mode;\r\n}\r\n\r\nfunction applyClass(resolved: 'light' | 'dark') {\r\n const el = document.documentElement;\r\n if (resolved === 'dark') {\r\n el.classList.add('dark');\r\n } else {\r\n el.classList.remove('dark');\r\n }\r\n}\r\n\r\nexport interface UseDarkModeReturn {\r\n mode: DarkModeValue;\r\n setMode: (mode: DarkModeValue) => void;\r\n resolvedMode: 'light' | 'dark';\r\n}\r\n\r\n/**\r\n * Reads/writes dark-mode preference to localStorage, listens to\r\n * `prefers-color-scheme` for auto mode, and toggles `.dark` on `<html>`.\r\n */\r\nexport function useDarkMode(): UseDarkModeReturn {\r\n const [mode, setModeState] = useState<DarkModeValue>(getStoredMode);\r\n const [resolvedMode, setResolvedMode] = useState<'light' | 'dark'>(() => resolve(mode));\r\n\r\n const setMode = useCallback((next: DarkModeValue) => {\r\n localStorage.setItem(STORAGE_KEY, next);\r\n setModeState(next);\r\n const r = resolve(next);\r\n setResolvedMode(r);\r\n applyClass(r);\r\n }, []);\r\n\r\n // Apply on mount\r\n useEffect(() => {\r\n applyClass(resolvedMode);\r\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\r\n\r\n // Listen to system preference changes for auto mode\r\n useEffect(() => {\r\n if (mode !== 'auto') return;\r\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\r\n const handler = (e: MediaQueryListEvent) => {\r\n const r = e.matches ? 'dark' : 'light';\r\n setResolvedMode(r);\r\n applyClass(r);\r\n };\r\n mql.addEventListener('change', handler);\r\n return () => mql.removeEventListener('change', handler);\r\n }, [mode]);\r\n\r\n return { mode, setMode, resolvedMode };\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/toolbar/DarkModeSelector.tsx","../../../src/components/toolbar/I18nSelector.tsx","../../../src/components/toolbar/useDarkMode.ts"],"names":["cn","jsxs","jsx","DropdownMenu2","Tooltip2"],"mappings":"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","file":"index.mjs","sourcesContent":["import * as React from 'react';\nimport * as DropdownMenu from '@radix-ui/react-dropdown-menu';\nimport * as Tooltip from '@radix-ui/react-tooltip';\n\nfunction cn(...inputs: (string | undefined | null | false)[]): string {\n return inputs.filter(Boolean).join(' ');\n}\n\n// ---------- Inline SVG Icons ----------\n\nfunction SunIcon({ className }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"12\" cy=\"12\" r=\"4\" />\n <path d=\"M12 2v2\" /><path d=\"M12 20v2\" />\n <path d=\"m4.93 4.93 1.41 1.41\" /><path d=\"m17.66 17.66 1.41 1.41\" />\n <path d=\"M2 12h2\" /><path d=\"M20 12h2\" />\n <path d=\"m6.34 17.66-1.41 1.41\" /><path d=\"m19.07 4.93-1.41 1.41\" />\n </svg>\n );\n}\n\nfunction MoonIcon({ className }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\" />\n </svg>\n );\n}\n\nfunction MonitorIcon({ className }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\n </svg>\n );\n}\n\n// ---------- Component ----------\n\nexport type DarkModeValue = 'auto' | 'light' | 'dark';\n\nexport interface DarkModeSelectorProps {\n mode: DarkModeValue;\n onModeChange: (mode: DarkModeValue) => void;\n labels?: { auto?: string; light?: string; dark?: string };\n tooltip?: string;\n className?: string;\n}\n\nconst triggerIconMap: Record<DarkModeValue, React.FC<{ className?: string }>> = {\n light: SunIcon,\n dark: MoonIcon,\n auto: MonitorIcon,\n};\n\nexport function DarkModeSelector({\n mode,\n onModeChange,\n labels = {},\n tooltip,\n className,\n}: DarkModeSelectorProps) {\n const TriggerIcon = triggerIconMap[mode];\n const resolvedLabels = {\n auto: labels.auto ?? 'Auto',\n light: labels.light ?? 'Light',\n dark: labels.dark ?? 'Dark',\n };\n\n const options: { value: DarkModeValue; label: string; Icon: React.FC<{ className?: string }> }[] = [\n { value: 'auto', label: resolvedLabels.auto, Icon: MonitorIcon },\n { value: 'light', label: resolvedLabels.light, Icon: SunIcon },\n { value: 'dark', label: resolvedLabels.dark, Icon: MoonIcon },\n ];\n\n const trigger = (\n <DropdownMenu.Trigger asChild>\n <button\n className={cn(\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] transition-colors focus-visible:outline-none',\n className,\n )}\n >\n <TriggerIcon />\n <span className=\"sr-only\">{tooltip ?? 'Toggle theme'}</span>\n </button>\n </DropdownMenu.Trigger>\n );\n\n return (\n <DropdownMenu.Root>\n {tooltip ? (\n <Tooltip.Provider delayDuration={300}>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>{trigger}</Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content\n className=\"rounded-md bg-[hsl(var(--popover))] px-3 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-md border border-[hsl(var(--border))] animate-in fade-in-0 zoom-in-95\"\n sideOffset={5}\n >\n {tooltip}\n <Tooltip.Arrow className=\"fill-[hsl(var(--popover))]\" />\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </Tooltip.Provider>\n ) : (\n trigger\n )}\n\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\n sideOffset={5}\n align=\"end\"\n >\n {options.map(({ value, label, Icon }) => (\n <DropdownMenu.Item\n key={value}\n className={cn(\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))]',\n mode === value && 'bg-[hsl(var(--accent))]',\n )}\n onSelect={() => onModeChange(value)}\n >\n <Icon className=\"h-4 w-4\" />\n {label}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n );\n}\n\n// ---------- Sub-menu variant (for embedding in user dropdown) ----------\n\nfunction SunMoonIcon({ className }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <path d=\"M12 8a2.83 2.83 0 0 0 4 4 4 4 0 1 1-4-4\" />\n <path d=\"M12 2v2\" /><path d=\"M12 20v2\" />\n <path d=\"m4.9 4.9 1.4 1.4\" /><path d=\"m17.7 17.7 1.4 1.4\" />\n <path d=\"M2 12h2\" /><path d=\"M20 12h2\" />\n <path d=\"m6.3 17.7-1.4 1.4\" /><path d=\"m19.1 4.9-1.4 1.4\" />\n </svg>\n );\n}\n\nexport interface DarkModeSubMenuProps {\n mode: DarkModeValue;\n onModeChange: (mode: DarkModeValue) => void;\n label?: string;\n labels?: { auto?: string; light?: string; dark?: string };\n}\n\n/**\n * A DropdownMenuSub component for embedding dark mode selector\n * inside a Radix DropdownMenu (e.g. user avatar menu).\n * Must be rendered as a child of DropdownMenu.Group / DropdownMenu.Content.\n */\nexport function DarkModeSubMenu({\n mode,\n onModeChange,\n label = '外观',\n labels = {},\n}: DarkModeSubMenuProps) {\n const resolvedLabels = {\n auto: labels.auto ?? '跟随系统',\n light: labels.light ?? '浅色模式',\n dark: labels.dark ?? '深色模式',\n };\n\n const currentLabel = mode === 'auto' ? resolvedLabels.auto : mode === 'dark' ? resolvedLabels.dark : resolvedLabels.light;\n\n const options: { value: DarkModeValue; label: string; Icon: React.FC<{ className?: string }> }[] = [\n { value: 'auto', label: resolvedLabels.auto, Icon: MonitorIcon },\n { value: 'light', label: resolvedLabels.light, Icon: SunIcon },\n { value: 'dark', label: resolvedLabels.dark, Icon: MoonIcon },\n ];\n\n return (\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger className=\"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[state=open]:bg-[hsl(var(--accent))]\">\n <SunMoonIcon className=\"h-4 w-4\" />\n <span>{label}</span>\n <span className=\"ml-auto text-xs text-[hsl(var(--muted-foreground))]\">{currentLabel}</span>\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\n sideOffset={8}\n >\n {options.map(({ value, label: optLabel, Icon }) => (\n <DropdownMenu.CheckboxItem\n key={value}\n checked={mode === value}\n disabled={mode === value}\n className={cn(\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 pl-7 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n )}\n onCheckedChange={() => onModeChange(value)}\n >\n <DropdownMenu.ItemIndicator className=\"absolute left-2 inline-flex items-center justify-center\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>\n </DropdownMenu.ItemIndicator>\n <Icon className=\"h-4 w-4\" />\n {optLabel}\n </DropdownMenu.CheckboxItem>\n ))}\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n );\n}\n","import * as React from 'react';\nimport * as DropdownMenu from '@radix-ui/react-dropdown-menu';\nimport * as Tooltip from '@radix-ui/react-tooltip';\n\nfunction cn(...inputs: (string | undefined | null | false)[]): string {\n return inputs.filter(Boolean).join(' ');\n}\n\n// ---------- Inline SVG Icon ----------\n\nfunction GlobeIcon({ className }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className={className}>\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n <path d=\"M2 12h20\" />\n </svg>\n );\n}\n\n// ---------- Component ----------\n\nexport interface I18nLanguage {\n code: string;\n label: string;\n}\n\nexport interface I18nSelectorProps {\n languages: I18nLanguage[];\n currentLanguage: string;\n onLanguageChange: (code: string) => void;\n tooltip?: string;\n className?: string;\n}\n\nexport function I18nSelector({\n languages,\n currentLanguage,\n onLanguageChange,\n tooltip,\n className,\n}: I18nSelectorProps) {\n const trigger = (\n <DropdownMenu.Trigger asChild>\n <button\n className={cn(\n 'inline-flex h-8 w-8 items-center justify-center rounded-md text-[hsl(var(--foreground))] hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] transition-colors focus-visible:outline-none',\n className,\n )}\n >\n <GlobeIcon />\n <span className=\"sr-only\">{tooltip ?? 'Switch language'}</span>\n </button>\n </DropdownMenu.Trigger>\n );\n\n return (\n <DropdownMenu.Root>\n {tooltip ? (\n <Tooltip.Provider delayDuration={300}>\n <Tooltip.Root>\n <Tooltip.Trigger asChild>{trigger}</Tooltip.Trigger>\n <Tooltip.Portal>\n <Tooltip.Content\n className=\"rounded-md bg-[hsl(var(--popover))] px-3 py-1.5 text-xs text-[hsl(var(--popover-foreground))] shadow-md border border-[hsl(var(--border))] animate-in fade-in-0 zoom-in-95\"\n sideOffset={5}\n >\n {tooltip}\n <Tooltip.Arrow className=\"fill-[hsl(var(--popover))]\" />\n </Tooltip.Content>\n </Tooltip.Portal>\n </Tooltip.Root>\n </Tooltip.Provider>\n ) : (\n trigger\n )}\n\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\n sideOffset={5}\n align=\"end\"\n >\n {languages.map(({ code, label }) => (\n <DropdownMenu.Item\n key={code}\n className={cn(\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))]',\n currentLanguage === code && 'bg-[hsl(var(--accent))]',\n )}\n onSelect={() => onLanguageChange(code)}\n >\n {label}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n );\n}\n\n// ---------- Sub-menu variant (for embedding in user dropdown) ----------\n\nexport interface I18nSubMenuProps {\n languages: I18nLanguage[];\n currentLanguage: string;\n onLanguageChange: (code: string) => void;\n label?: string;\n}\n\n/**\n * A DropdownMenuSub component for embedding language selector\n * inside a Radix DropdownMenu (e.g. user avatar menu).\n * Must be rendered as a child of DropdownMenu.Group / DropdownMenu.Content.\n */\nexport function I18nSubMenu({\n languages,\n currentLanguage,\n onLanguageChange,\n label = '语言',\n}: I18nSubMenuProps) {\n const currentLabel = languages.find((l) => l.code === currentLanguage)?.label ?? currentLanguage;\n\n return (\n <DropdownMenu.Sub>\n <DropdownMenu.SubTrigger className=\"relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[state=open]:bg-[hsl(var(--accent))]\">\n <GlobeIcon className=\"h-4 w-4\" />\n <span>{label}</span>\n <span className=\"ml-auto text-xs text-[hsl(var(--muted-foreground))]\">{currentLabel}</span>\n </DropdownMenu.SubTrigger>\n <DropdownMenu.Portal>\n <DropdownMenu.SubContent\n className=\"z-50 min-w-[8rem] rounded-md border border-[hsl(var(--border))] bg-[hsl(var(--popover))] p-1 text-[hsl(var(--popover-foreground))] shadow-md animate-in fade-in-0 zoom-in-95\"\n sideOffset={8}\n >\n {languages.map(({ code, label: langLabel }) => (\n <DropdownMenu.CheckboxItem\n key={code}\n checked={currentLanguage === code}\n disabled={currentLanguage === code}\n className={cn(\n 'relative flex cursor-pointer select-none items-center gap-2 rounded-sm px-2 py-1.5 pl-7 text-sm outline-none transition-colors hover:bg-[hsl(var(--accent))] hover:text-[hsl(var(--accent-foreground))] data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n )}\n onCheckedChange={() => onLanguageChange(code)}\n >\n <DropdownMenu.ItemIndicator className=\"absolute left-2 inline-flex items-center justify-center\">\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M20 6 9 17l-5-5\"/></svg>\n </DropdownMenu.ItemIndicator>\n {langLabel}\n </DropdownMenu.CheckboxItem>\n ))}\n </DropdownMenu.SubContent>\n </DropdownMenu.Portal>\n </DropdownMenu.Sub>\n );\n}\n","import { useEffect, useState, useCallback } from 'react';\n\nexport type DarkModeValue = 'auto' | 'light' | 'dark';\n\nconst STORAGE_KEY = 'monkeys-dark-mode';\n\nfunction getStoredMode(): DarkModeValue {\n if (typeof window === 'undefined') return 'auto';\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored === 'light' || stored === 'dark' || stored === 'auto') return stored;\n return 'auto';\n}\n\nfunction getSystemPrefersDark(): boolean {\n if (typeof window === 'undefined') return false;\n return window.matchMedia('(prefers-color-scheme: dark)').matches;\n}\n\nfunction resolve(mode: DarkModeValue): 'light' | 'dark' {\n if (mode === 'auto') return getSystemPrefersDark() ? 'dark' : 'light';\n return mode;\n}\n\nfunction applyClass(resolved: 'light' | 'dark') {\n const el = document.documentElement;\n if (resolved === 'dark') {\n el.classList.add('dark');\n } else {\n el.classList.remove('dark');\n }\n}\n\nexport interface UseDarkModeReturn {\n mode: DarkModeValue;\n setMode: (mode: DarkModeValue) => void;\n resolvedMode: 'light' | 'dark';\n}\n\n/**\n * Reads/writes dark-mode preference to localStorage, listens to\n * `prefers-color-scheme` for auto mode, and toggles `.dark` on `<html>`.\n */\nexport function useDarkMode(): UseDarkModeReturn {\n const [mode, setModeState] = useState<DarkModeValue>(getStoredMode);\n const [resolvedMode, setResolvedMode] = useState<'light' | 'dark'>(() => resolve(mode));\n\n const setMode = useCallback((next: DarkModeValue) => {\n localStorage.setItem(STORAGE_KEY, next);\n setModeState(next);\n const r = resolve(next);\n setResolvedMode(r);\n applyClass(r);\n }, []);\n\n // Apply on mount\n useEffect(() => {\n applyClass(resolvedMode);\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Listen to system preference changes for auto mode\n useEffect(() => {\n if (mode !== 'auto') return;\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => {\n const r = e.matches ? 'dark' : 'light';\n setResolvedMode(r);\n applyClass(r);\n };\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n }, [mode]);\n\n return { mode, setMode, resolvedMode };\n}\n"]}
|