@windrun-huaiin/base-ui 3.2.2 → 3.2.3
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/dist/components/index.d.mts +29 -1
- package/dist/components/index.d.ts +29 -1
- package/dist/components/index.js +149 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +147 -0
- package/dist/components/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +147 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +145 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/language-detector.tsx +1 -1
- package/src/components/language-switcher.tsx +1 -1
@@ -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 };
|
package/dist/components/index.js
CHANGED
@@ -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,
|