@windrun-huaiin/base-ui 3.2.2 → 3.2.4

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.
@@ -130,6 +130,34 @@ declare function getIconElement(icon: string | undefined): React__default.ReactE
130
130
  declare const DefaultSiteIcon: () => react_jsx_runtime.JSX.Element;
131
131
  declare const NotFoundIcon: () => react_jsx_runtime.JSX.Element;
132
132
 
133
+ type I18nConfig = {
134
+ locales: readonly string[];
135
+ detector: {
136
+ storagePrefix: string;
137
+ storageKey: string;
138
+ autoCloseTimeout: number;
139
+ expirationDays: number;
140
+ };
141
+ };
142
+ interface LanguageDetectorProps {
143
+ i18nConfig: I18nConfig;
144
+ }
145
+ declare function LanguageDetector({ i18nConfig }: LanguageDetectorProps): react_jsx_runtime.JSX.Element | null;
146
+
147
+ /**
148
+ * @license
149
+ * MIT License
150
+ * Copyright (c) 2025 D8ger
151
+ *
152
+ * This source code is licensed under the MIT license found in the
153
+ * LICENSE file in the root directory of this source tree.
154
+ */
155
+ interface LanguageSwitcherProps {
156
+ locales: readonly string[];
157
+ localeLabels: Record<string, string>;
158
+ }
159
+ declare function LanguageSwitcher({ locales, localeLabels }: LanguageSwitcherProps): react_jsx_runtime.JSX.Element;
160
+
133
161
  declare function GoogleAnalyticsScript(): react_jsx_runtime.JSX.Element | null;
134
162
  declare function useGoogleAnalytics(): {
135
163
  trackEvent: (event: string, data?: Record<string, unknown>) => void;
@@ -143,4 +171,4 @@ declare global {
143
171
 
144
172
  declare function MicrosoftClarityScript(): react_jsx_runtime.JSX.Element | null;
145
173
 
146
- export { DefaultSiteIcon, GoogleAnalyticsScript, MicrosoftClarityScript, NotFoundIcon, NotFoundPage, getGlobalIcon, getIconElement, globalLucideIcons, useGoogleAnalytics };
174
+ export { DefaultSiteIcon, GoogleAnalyticsScript, LanguageDetector, LanguageSwitcher, MicrosoftClarityScript, NotFoundIcon, NotFoundPage, getGlobalIcon, getIconElement, globalLucideIcons, useGoogleAnalytics };
@@ -130,6 +130,34 @@ declare function getIconElement(icon: string | undefined): React__default.ReactE
130
130
  declare const DefaultSiteIcon: () => react_jsx_runtime.JSX.Element;
131
131
  declare const NotFoundIcon: () => react_jsx_runtime.JSX.Element;
132
132
 
133
+ type I18nConfig = {
134
+ locales: readonly string[];
135
+ detector: {
136
+ storagePrefix: string;
137
+ storageKey: string;
138
+ autoCloseTimeout: number;
139
+ expirationDays: number;
140
+ };
141
+ };
142
+ interface LanguageDetectorProps {
143
+ i18nConfig: I18nConfig;
144
+ }
145
+ declare function LanguageDetector({ i18nConfig }: LanguageDetectorProps): react_jsx_runtime.JSX.Element | null;
146
+
147
+ /**
148
+ * @license
149
+ * MIT License
150
+ * Copyright (c) 2025 D8ger
151
+ *
152
+ * This source code is licensed under the MIT license found in the
153
+ * LICENSE file in the root directory of this source tree.
154
+ */
155
+ interface LanguageSwitcherProps {
156
+ locales: readonly string[];
157
+ localeLabels: Record<string, string>;
158
+ }
159
+ declare function LanguageSwitcher({ locales, localeLabels }: LanguageSwitcherProps): react_jsx_runtime.JSX.Element;
160
+
133
161
  declare function GoogleAnalyticsScript(): react_jsx_runtime.JSX.Element | null;
134
162
  declare function useGoogleAnalytics(): {
135
163
  trackEvent: (event: string, data?: Record<string, unknown>) => void;
@@ -143,4 +171,4 @@ declare global {
143
171
 
144
172
  declare function MicrosoftClarityScript(): react_jsx_runtime.JSX.Element | null;
145
173
 
146
- export { DefaultSiteIcon, GoogleAnalyticsScript, MicrosoftClarityScript, NotFoundIcon, NotFoundPage, getGlobalIcon, getIconElement, globalLucideIcons, useGoogleAnalytics };
174
+ export { DefaultSiteIcon, GoogleAnalyticsScript, LanguageDetector, LanguageSwitcher, MicrosoftClarityScript, NotFoundIcon, NotFoundPage, getGlobalIcon, getIconElement, globalLucideIcons, useGoogleAnalytics };
@@ -62,6 +62,8 @@ var components_exports = {};
62
62
  __export(components_exports, {
63
63
  DefaultSiteIcon: () => DefaultSiteIcon,
64
64
  GoogleAnalyticsScript: () => GoogleAnalyticsScript,
65
+ LanguageDetector: () => LanguageDetector,
66
+ LanguageSwitcher: () => LanguageSwitcher,
65
67
  MicrosoftClarityScript: () => MicrosoftClarityScript,
66
68
  NotFoundIcon: () => NotFoundIcon,
67
69
  NotFoundPage: () => NotFoundPage,
@@ -1445,6 +1447,106 @@ var import_next_intl = require("next-intl");
1445
1447
  var import_navigation = require("next/navigation");
1446
1448
  var import_react33 = require("react");
1447
1449
  var import_jsx_runtime34 = require("react/jsx-runtime");
1450
+ function LanguageDetector({ i18nConfig }) {
1451
+ const [show, setShow] = (0, import_react33.useState)(false);
1452
+ const [detectedLocale, setDetectedLocale] = (0, import_react33.useState)(null);
1453
+ const currentLocale = (0, import_next_intl.useLocale)();
1454
+ const router = (0, import_navigation.useRouter)();
1455
+ const t = (0, import_next_intl.useTranslations)("languageDetection");
1456
+ const LANGUAGE_PREFERENCE_KEY = `${i18nConfig.detector.storagePrefix}-${i18nConfig.detector.storageKey}`;
1457
+ (0, import_react33.useEffect)(() => {
1458
+ const browserLang = navigator.language.split("-")[0];
1459
+ const savedPreference = localStorage.getItem(LANGUAGE_PREFERENCE_KEY);
1460
+ const preference = savedPreference ? JSON.parse(savedPreference) : null;
1461
+ const shouldShowDetector = () => {
1462
+ if (!preference) return true;
1463
+ if (preference.locale === currentLocale) return false;
1464
+ if (preference.status === "rejected" && preference.locale === browserLang) return false;
1465
+ if (preference.status === "accepted" && preference.locale === currentLocale) return false;
1466
+ const expirationMs = i18nConfig.detector.expirationDays * 24 * 60 * 60 * 1e3;
1467
+ if (Date.now() - preference.timestamp < expirationMs) return false;
1468
+ return true;
1469
+ };
1470
+ if (i18nConfig.locales.includes(browserLang) && browserLang !== currentLocale && shouldShowDetector()) {
1471
+ setDetectedLocale(browserLang);
1472
+ setShow(true);
1473
+ const timer = setTimeout(() => {
1474
+ console.log("[LanguageDetector] Auto closing after timeout");
1475
+ setShow(false);
1476
+ savePreference(browserLang, "rejected");
1477
+ }, i18nConfig.detector.autoCloseTimeout);
1478
+ return () => clearTimeout(timer);
1479
+ }
1480
+ }, [currentLocale]);
1481
+ const savePreference = (locale, status) => {
1482
+ const preference = {
1483
+ locale,
1484
+ status,
1485
+ timestamp: Date.now()
1486
+ };
1487
+ localStorage.setItem(LANGUAGE_PREFERENCE_KEY, JSON.stringify(preference));
1488
+ };
1489
+ const handleLanguageChange = () => {
1490
+ if (detectedLocale) {
1491
+ savePreference(detectedLocale, "accepted");
1492
+ const pathname = window.location.pathname;
1493
+ const newPathname = pathname.replace(`/${currentLocale}`, `/${detectedLocale}`);
1494
+ router.push(newPathname);
1495
+ setShow(false);
1496
+ }
1497
+ };
1498
+ const handleClose = () => {
1499
+ if (detectedLocale) {
1500
+ savePreference(detectedLocale, "rejected");
1501
+ }
1502
+ setShow(false);
1503
+ };
1504
+ if (!detectedLocale || !show) return null;
1505
+ return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "fixed top-16 right-4 z-40 w-[420px]", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: `shadow-lg rounded-lg transition-all duration-300 ${show ? "translate-x-0 opacity-100" : "translate-x-full opacity-0"}
1506
+ bg-linear-to-r from-purple-100/95 via-white/95 to-purple-100/95 backdrop-blur-xs
1507
+ animate-gradient-x`, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "relative px-6 py-4 overflow-hidden", children: [
1508
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "relative z-10 flex flex-col gap-3", children: [
1509
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-start justify-between gap-4", children: [
1510
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
1511
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("h3", { className: "text-lg font-semibold text-gray-900", children: t("title") }),
1512
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { className: "text-base text-gray-600", children: [
1513
+ t("description"),
1514
+ " ",
1515
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: "text-purple-500 font-semibold", children: detectedLocale === "zh" ? "\u4E2D\u6587" : "English" }),
1516
+ "?"
1517
+ ] })
1518
+ ] }),
1519
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1520
+ "button",
1521
+ {
1522
+ onClick: handleClose,
1523
+ className: "text-gray-500 hover:text-gray-700",
1524
+ children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(globalLucideIcons.X, { className: "h-5 w-5" })
1525
+ }
1526
+ )
1527
+ ] }),
1528
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex items-center gap-3", children: [
1529
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1530
+ "button",
1531
+ {
1532
+ onClick: handleClose,
1533
+ className: "flex-1 px-4 py-2 text-base bg-gray-100 text-gray-600 rounded-md hover:bg-gray-200",
1534
+ children: t("close")
1535
+ }
1536
+ ),
1537
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
1538
+ "button",
1539
+ {
1540
+ onClick: handleLanguageChange,
1541
+ className: "flex-1 px-4 py-2 text-base bg-purple-500 text-white rounded-md hover:bg-purple-600",
1542
+ children: t("changeAction")
1543
+ }
1544
+ )
1545
+ ] })
1546
+ ] }),
1547
+ /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { className: "absolute inset-0 bg-linear-to-r from-transparent via-purple-200/30 to-transparent animate-shimmer" })
1548
+ ] }) }) });
1549
+ }
1448
1550
 
1449
1551
  // src/components/language-switcher.tsx
1450
1552
  var import_navigation2 = require("next/navigation");
@@ -1454,6 +1556,8 @@ var import_next_intl2 = require("next-intl");
1454
1556
  var React30 = __toESM(require("react"));
1455
1557
  var DropdownMenuPrimitive = __toESM(require("@radix-ui/react-dropdown-menu"));
1456
1558
  var import_jsx_runtime35 = require("react/jsx-runtime");
1559
+ var DropdownMenu = DropdownMenuPrimitive.Root;
1560
+ var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
1457
1561
  var DropdownMenuSubTrigger = React30.forwardRef((_a, ref) => {
1458
1562
  var _b = _a, { className, inset, children } = _b, props = __objRest(_b, ["className", "inset", "children"]);
1459
1563
  return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
@@ -1628,6 +1732,49 @@ LanguageButton.displayName = "Button";
1628
1732
 
1629
1733
  // src/components/language-switcher.tsx
1630
1734
  var import_jsx_runtime37 = require("react/jsx-runtime");
1735
+ function LanguageSwitcher({ locales, localeLabels }) {
1736
+ const locale = (0, import_next_intl2.useLocale)();
1737
+ const router = (0, import_navigation2.useRouter)();
1738
+ const pathname = (0, import_navigation2.usePathname)();
1739
+ const handleLocaleChange = (newLocale) => {
1740
+ const newPathname = pathname.replace(`/${locale}`, `/${newLocale}`);
1741
+ router.push(newPathname);
1742
+ };
1743
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(DropdownMenu, { children: [
1744
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1745
+ LanguageButton,
1746
+ {
1747
+ variant: "ghost",
1748
+ size: "icon",
1749
+ className: "bg-linear-to-r from-purple-400 to-pink-600 hover:from-purple-500 hover:to-pink-700 text-white transform hover:scale-110 transition-all duration-300",
1750
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(globalLucideIcons.Globe, { className: "h-5 w-5" })
1751
+ }
1752
+ ) }),
1753
+ /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1754
+ DropdownMenuContent,
1755
+ {
1756
+ align: "end",
1757
+ sideOffset: 5,
1758
+ className: "bg-white/90 dark:bg-gray-800/90 border-purple-100 dark:border-purple-800 w-[200px] p-2 backdrop-blur-xs translate-x-[50px]",
1759
+ children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "grid grid-cols-2 gap-1", children: locales.map((loc) => /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
1760
+ DropdownMenuItem,
1761
+ {
1762
+ className: `
1763
+ px-2 py-2 text-sm cursor-pointer text-center justify-center
1764
+ transition-all duration-300 ease-in-out
1765
+ hover:scale-105 hover:shadow-md
1766
+ rounded-md whitespace-nowrap
1767
+ ${locale === loc ? "bg-linear-to-r from-purple-400 to-pink-600 text-white font-medium shadow-lg scale-105" : "hover:bg-linear-to-r hover:from-purple-400/10 hover:to-pink-600/10 hover:text-transparent hover:bg-clip-text"}
1768
+ `,
1769
+ onClick: () => handleLocaleChange(loc),
1770
+ children: localeLabels[loc]
1771
+ },
1772
+ loc
1773
+ )) })
1774
+ }
1775
+ )
1776
+ ] });
1777
+ }
1631
1778
 
1632
1779
  // src/components/script/google-analytics-script.tsx
1633
1780
  var import_script = __toESM(require("next/script"));
@@ -1694,6 +1841,8 @@ function MicrosoftClarityScript() {
1694
1841
  0 && (module.exports = {
1695
1842
  DefaultSiteIcon,
1696
1843
  GoogleAnalyticsScript,
1844
+ LanguageDetector,
1845
+ LanguageSwitcher,
1697
1846
  MicrosoftClarityScript,
1698
1847
  NotFoundIcon,
1699
1848
  NotFoundPage,