@anker-in/headless-ui 1.1.44 → 1.1.45
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/cjs/biz-components/IPRedirect/RegionBanner.d.ts +39 -0
- package/dist/cjs/biz-components/IPRedirect/RegionBanner.js +68 -0
- package/dist/cjs/biz-components/IPRedirect/RegionBanner.js.map +7 -0
- package/dist/cjs/biz-components/IPRedirect/RegionSelectorModal.d.ts +58 -0
- package/dist/cjs/biz-components/IPRedirect/RegionSelectorModal.js +68 -0
- package/dist/cjs/biz-components/IPRedirect/RegionSelectorModal.js.map +7 -0
- package/dist/cjs/biz-components/IPRedirect/index.d.ts +9 -0
- package/dist/cjs/biz-components/IPRedirect/index.js +2 -0
- package/dist/cjs/biz-components/IPRedirect/index.js.map +7 -0
- package/dist/cjs/biz-components/IPRedirect/type.d.ts +36 -0
- package/dist/cjs/biz-components/IPRedirect/type.js +2 -0
- package/dist/cjs/biz-components/IPRedirect/type.js.map +7 -0
- package/dist/cjs/biz-components/IPRedirect/useAutoRedirect.d.ts +71 -0
- package/dist/cjs/biz-components/IPRedirect/useAutoRedirect.js +2 -0
- package/dist/cjs/biz-components/IPRedirect/useAutoRedirect.js.map +7 -0
- package/dist/cjs/biz-components/IPRedirect/useDetectedRegionRedirect.d.ts +51 -0
- package/dist/cjs/biz-components/IPRedirect/useDetectedRegionRedirect.js +2 -0
- package/dist/cjs/biz-components/IPRedirect/useDetectedRegionRedirect.js.map +7 -0
- package/dist/cjs/biz-components/IPRedirect/useIPRedirect.d.ts +42 -0
- package/dist/cjs/biz-components/IPRedirect/useIPRedirect.js +2 -0
- package/dist/cjs/biz-components/IPRedirect/useIPRedirect.js.map +7 -0
- package/dist/cjs/biz-components/IPRedirect/useRedirectBanner.d.ts +108 -0
- package/dist/cjs/biz-components/IPRedirect/useRedirectBanner.js +2 -0
- package/dist/cjs/biz-components/IPRedirect/useRedirectBanner.js.map +7 -0
- package/dist/cjs/biz-components/IPRedirect/useRegionRedirectManager.d.ts +168 -0
- package/dist/cjs/biz-components/IPRedirect/useRegionRedirectManager.js +2 -0
- package/dist/cjs/biz-components/IPRedirect/useRegionRedirectManager.js.map +7 -0
- package/dist/cjs/biz-components/IPRedirect/useSavedRegionRedirect.d.ts +51 -0
- package/dist/cjs/biz-components/IPRedirect/useSavedRegionRedirect.js +2 -0
- package/dist/cjs/biz-components/IPRedirect/useSavedRegionRedirect.js.map +7 -0
- package/dist/cjs/biz-components/IPRedirect/utils.d.ts +224 -0
- package/dist/cjs/biz-components/IPRedirect/utils.js +2 -0
- package/dist/cjs/biz-components/IPRedirect/utils.js.map +7 -0
- package/dist/cjs/biz-components/index.d.ts +2 -0
- package/dist/cjs/biz-components/index.js +1 -1
- package/dist/cjs/biz-components/index.js.map +3 -3
- package/dist/esm/biz-components/IPRedirect/RegionBanner.d.ts +39 -0
- package/dist/esm/biz-components/IPRedirect/RegionBanner.js +68 -0
- package/dist/esm/biz-components/IPRedirect/RegionBanner.js.map +7 -0
- package/dist/esm/biz-components/IPRedirect/RegionSelectorModal.d.ts +58 -0
- package/dist/esm/biz-components/IPRedirect/RegionSelectorModal.js +68 -0
- package/dist/esm/biz-components/IPRedirect/RegionSelectorModal.js.map +7 -0
- package/dist/esm/biz-components/IPRedirect/index.d.ts +9 -0
- package/dist/esm/biz-components/IPRedirect/index.js +2 -0
- package/dist/esm/biz-components/IPRedirect/index.js.map +7 -0
- package/dist/esm/biz-components/IPRedirect/type.d.ts +36 -0
- package/dist/esm/biz-components/IPRedirect/type.js +1 -0
- package/dist/esm/biz-components/IPRedirect/type.js.map +7 -0
- package/dist/esm/biz-components/IPRedirect/useAutoRedirect.d.ts +71 -0
- package/dist/esm/biz-components/IPRedirect/useAutoRedirect.js +2 -0
- package/dist/esm/biz-components/IPRedirect/useAutoRedirect.js.map +7 -0
- package/dist/esm/biz-components/IPRedirect/useDetectedRegionRedirect.d.ts +51 -0
- package/dist/esm/biz-components/IPRedirect/useDetectedRegionRedirect.js +2 -0
- package/dist/esm/biz-components/IPRedirect/useDetectedRegionRedirect.js.map +7 -0
- package/dist/esm/biz-components/IPRedirect/useIPRedirect.d.ts +42 -0
- package/dist/esm/biz-components/IPRedirect/useIPRedirect.js +2 -0
- package/dist/esm/biz-components/IPRedirect/useIPRedirect.js.map +7 -0
- package/dist/esm/biz-components/IPRedirect/useRedirectBanner.d.ts +108 -0
- package/dist/esm/biz-components/IPRedirect/useRedirectBanner.js +2 -0
- package/dist/esm/biz-components/IPRedirect/useRedirectBanner.js.map +7 -0
- package/dist/esm/biz-components/IPRedirect/useRegionRedirectManager.d.ts +168 -0
- package/dist/esm/biz-components/IPRedirect/useRegionRedirectManager.js +2 -0
- package/dist/esm/biz-components/IPRedirect/useRegionRedirectManager.js.map +7 -0
- package/dist/esm/biz-components/IPRedirect/useSavedRegionRedirect.d.ts +51 -0
- package/dist/esm/biz-components/IPRedirect/useSavedRegionRedirect.js +2 -0
- package/dist/esm/biz-components/IPRedirect/useSavedRegionRedirect.js.map +7 -0
- package/dist/esm/biz-components/IPRedirect/utils.d.ts +224 -0
- package/dist/esm/biz-components/IPRedirect/utils.js +2 -0
- package/dist/esm/biz-components/IPRedirect/utils.js.map +7 -0
- package/dist/esm/biz-components/index.d.ts +2 -0
- package/dist/esm/biz-components/index.js +1 -1
- package/dist/esm/biz-components/index.js.map +3 -3
- package/package.json +4 -1
- package/style.css +1 -1
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { RegionConfig, IPRedirectBannerCopy } from './type.js';
|
|
2
|
+
/** 横幅样式配置 */
|
|
3
|
+
export type RegionBannerStyles = {
|
|
4
|
+
/** 背景色,默认 #fff */
|
|
5
|
+
backgroundColor?: string;
|
|
6
|
+
/** 按钮圆角,默认 9999px */
|
|
7
|
+
buttonBorderRadius?: string;
|
|
8
|
+
/** 文案字号,默认 14px */
|
|
9
|
+
fontSize?: string;
|
|
10
|
+
/** Stay Here 按钮背景色,默认 #000 */
|
|
11
|
+
stayButtonBgColor?: string;
|
|
12
|
+
/** Stay Here 按钮文字颜色,默认 #fff */
|
|
13
|
+
stayButtonTextColor?: string;
|
|
14
|
+
/** Switch Site 按钮边框颜色,默认 #000 */
|
|
15
|
+
switchButtonBorderColor?: string;
|
|
16
|
+
/** Switch Site 按钮文字颜色,默认 #000 */
|
|
17
|
+
switchButtonTextColor?: string;
|
|
18
|
+
/** 大屏幕(≥1920px)最大宽度,默认 1664px */
|
|
19
|
+
maxWidth?: string;
|
|
20
|
+
};
|
|
21
|
+
export type RegionBannerProps = {
|
|
22
|
+
/** 控制横幅显示/隐藏 */
|
|
23
|
+
visible: boolean;
|
|
24
|
+
/** 横幅状态变化回调 */
|
|
25
|
+
onVisibleChange: (visible: boolean) => void;
|
|
26
|
+
/** 文案配置 */
|
|
27
|
+
copy: IPRedirectBannerCopy;
|
|
28
|
+
/** 点击 Stay Here 按钮的回调 */
|
|
29
|
+
onStayHere: () => void;
|
|
30
|
+
/** 点击 Switch Site 按钮的回调 */
|
|
31
|
+
onSwitchSite: () => void;
|
|
32
|
+
/** 样式配置 */
|
|
33
|
+
styles?: RegionBannerStyles;
|
|
34
|
+
/** 当前站点地区配置(用于显示国旗图标) */
|
|
35
|
+
currentRegion?: RegionConfig;
|
|
36
|
+
/** 自定义类名 */
|
|
37
|
+
className?: string;
|
|
38
|
+
};
|
|
39
|
+
export declare function RegionBanner({ visible, onVisibleChange, copy, onStayHere, onSwitchSite, styles: customStyles, currentRegion, className, }: RegionBannerProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";"use client";var l=Object.defineProperty;var x=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var u=(o,t)=>{for(var i in t)l(o,i,{get:t[i],enumerable:!0})},C=(o,t,i,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of h(t))!b.call(o,r)&&r!==i&&l(o,r,{get:()=>t[r],enumerable:!(a=x(t,r))||a.enumerable});return o};var f=o=>C(l({},"__esModule",{value:!0}),o);var y={};u(y,{RegionBanner:()=>m});module.exports=f(y);var e=require("react/jsx-runtime");const w={backgroundColor:"#fff",buttonBorderRadius:"9999px",fontSize:"14px",stayButtonBgColor:"#000",stayButtonTextColor:"#fff",switchButtonBorderColor:"#000",switchButtonTextColor:"#000",maxWidth:"1664px"};function m({visible:o,onVisibleChange:t,copy:i,onStayHere:a,onSwitchSite:r,styles:d,currentRegion:s,className:g}){const n={...w,...d};if(!o)return null;const p=()=>{a(),t(!1)},c=()=>{a(),t(!1)};return(0,e.jsxs)(e.Fragment,{children:[(0,e.jsx)("style",{children:`
|
|
2
|
+
.region-banner-wrapper {
|
|
3
|
+
height: auto;
|
|
4
|
+
min-height: 74px;
|
|
5
|
+
}
|
|
6
|
+
@media (min-width: 1024px) {
|
|
7
|
+
.region-banner-wrapper {
|
|
8
|
+
height: 54px;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
.region-banner-content {
|
|
12
|
+
padding: 0 12px;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
gap: 8px;
|
|
15
|
+
align-items: flex-start;
|
|
16
|
+
}
|
|
17
|
+
.region-banner-title-row {
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
width: 100%;
|
|
21
|
+
gap: 8px;
|
|
22
|
+
height: auto;
|
|
23
|
+
margin-top: 8px;
|
|
24
|
+
}
|
|
25
|
+
.region-banner-content h1 {
|
|
26
|
+
flex: 1;
|
|
27
|
+
min-width: 0;
|
|
28
|
+
}
|
|
29
|
+
.region-banner-close-btn {
|
|
30
|
+
position: static;
|
|
31
|
+
flex-shrink: 0;
|
|
32
|
+
}
|
|
33
|
+
@media (min-width: 1024px) {
|
|
34
|
+
.region-banner-content {
|
|
35
|
+
padding: 0 64px;
|
|
36
|
+
flex-direction: row;
|
|
37
|
+
align-items: center;
|
|
38
|
+
}
|
|
39
|
+
.region-banner-title-row {
|
|
40
|
+
flex: 1;
|
|
41
|
+
height: 20px;
|
|
42
|
+
}
|
|
43
|
+
.region-banner-close-btn {
|
|
44
|
+
position: absolute;
|
|
45
|
+
right: 16px;
|
|
46
|
+
top: 50%;
|
|
47
|
+
transform: translateY(-50%);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
@media (min-width: 1920px) {
|
|
51
|
+
.region-banner-wrapper {
|
|
52
|
+
display: flex;
|
|
53
|
+
justify-content: center;
|
|
54
|
+
}
|
|
55
|
+
.region-banner-content {
|
|
56
|
+
max-width: ${n.maxWidth};
|
|
57
|
+
width: 100%;
|
|
58
|
+
position: relative;
|
|
59
|
+
padding-left: 0px;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
@media (min-width: 1025px) and (max-width: 1440px) {
|
|
63
|
+
.region-banner-title {
|
|
64
|
+
max-width: 623px;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`}),(0,e.jsx)("div",{className:`region-banner-wrapper relative left-0 top-0 w-full ${g||""}`,style:{backgroundColor:n.backgroundColor,boxShadow:"0 2px 8px rgba(0,0,0,0.1)",zIndex:1e3},children:(0,e.jsxs)("div",{className:"region-banner-content flex h-full justify-between text-black",children:[(0,e.jsxs)("div",{className:"region-banner-title-row",children:[(0,e.jsx)("h1",{className:"region-banner-title font-bold",style:{fontSize:n.fontSize,color:"#1F2021"},children:i.message}),(0,e.jsx)("button",{onClick:c,className:"region-banner-close-btn inline-flex size-[28px] items-center justify-center rounded-full hover:bg-[#f5f5f5] focus:outline-none",style:{color:"#767880"},"aria-label":"Close",children:(0,e.jsx)("svg",{width:"20",height:"20",viewBox:"0 0 18 18",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:(0,e.jsx)("path",{d:"M13.5 4.5L4.5 13.5M4.5 4.5L13.5 13.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})]}),(0,e.jsxs)("div",{className:"l-tablet:ml-0 l-tablet:mb-[8px] ml-4 flex gap-3",children:[(0,e.jsxs)("button",{onClick:p,className:"box-border flex h-[38px] items-center gap-1 whitespace-nowrap px-4 py-2 hover:opacity-80",style:{backgroundColor:n.stayButtonBgColor,color:n.stayButtonTextColor,fontWeight:"700",fontSize:n.fontSize,borderRadius:n.buttonBorderRadius,border:"none"},children:[s?.icon&&(0,e.jsx)("img",{src:s.icon,alt:"",style:{width:"16px",height:"16px",borderRadius:"100%"}}),i.stayButtonText]}),(0,e.jsxs)("button",{onClick:r,className:"box-border flex h-[38px] items-center gap-1 whitespace-nowrap px-4 py-2 hover:opacity-80",style:{backgroundColor:"transparent",color:n.switchButtonTextColor,border:`1.6px solid ${n.switchButtonBorderColor}`,fontWeight:"700",fontSize:n.fontSize,borderRadius:n.buttonBorderRadius},children:[(0,e.jsx)("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:(0,e.jsx)("path",{d:"M8.29883 1.2041C12.216 1.20425 15.3923 4.37181 15.3926 8.28027C15.3926 12.189 12.2162 15.3563 8.29883 15.3564C4.38145 15.3563 1.2041 12.189 1.2041 8.28027C1.20439 4.37183 4.38163 1.20428 8.29883 1.2041ZM3.58105 11.4795C4.31053 12.5471 5.39411 13.3542 6.66406 13.7324C6.21155 13.0301 5.86128 12.2699 5.60938 11.4795H3.58105ZM11.0166 11.4795C10.7696 12.2779 10.4256 13.0347 9.98438 13.7178C11.2325 13.3333 12.2971 12.5331 13.0166 11.4795H11.0166ZM7.0791 11.4795C7.3755 12.2654 7.78717 12.9997 8.31445 13.6455C8.83791 13.0305 9.25428 12.2929 9.55273 11.4795H7.0791ZM2.85645 6.56738C2.6854 7.10801 2.59283 7.68338 2.59277 8.28027C2.59277 8.91383 2.69891 9.52251 2.89063 10.0918H5.27148C5.15636 9.42693 5.10277 8.75388 5.11133 8.08789C5.11789 7.57837 5.1619 7.06931 5.23926 6.56738L2.85645 6.56738ZM11.3447 6.56738C11.4483 7.20036 11.4944 7.84036 11.4863 8.47363C11.4793 9.01629 11.4291 9.55828 11.3418 10.0918H13.707C13.8986 9.52259 14.0039 8.91374 14.0039 8.28027C14.0039 7.68337 13.9112 7.10802 13.7402 6.56738H11.3447ZM6.64648 6.56738C6.55761 7.06802 6.50673 7.58339 6.5 8.10547C6.49143 8.7725 6.55341 9.44067 6.68359 10.0918L9.93457 10.0918C10.0348 9.56074 10.0905 9.01207 10.0977 8.45605C10.1058 7.82231 10.0497 7.18763 9.93262 6.56738L6.64648 6.56738ZM6.6123 2.84277C5.32602 3.23909 4.23535 4.07819 3.51563 5.17969L5.5498 5.17969C5.79857 4.34514 6.15294 3.55384 6.6123 2.84277ZM9.93262 2.8291C10.4039 3.56047 10.7656 4.35407 11.0195 5.17969H13.0811C12.3519 4.06343 11.2413 3.21866 9.93262 2.8291ZM8.28223 2.91504C7.73775 3.55467 7.30932 4.32752 7.00879 5.17969L9.55566 5.17969C9.25672 4.35642 8.83179 3.58782 8.28223 2.91504Z",fill:"currentColor"})}),i.switchButtonText]})]})]})})]})}
|
|
68
|
+
//# sourceMappingURL=RegionBanner.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/biz-components/IPRedirect/RegionBanner.tsx"],
|
|
4
|
+
"sourcesContent": ["'use client'\n\nimport type { RegionConfig, IPRedirectBannerCopy } from './type.js'\n\n/** \u6A2A\u5E45\u6837\u5F0F\u914D\u7F6E */\nexport type RegionBannerStyles = {\n /** \u80CC\u666F\u8272\uFF0C\u9ED8\u8BA4 #fff */\n backgroundColor?: string\n /** \u6309\u94AE\u5706\u89D2\uFF0C\u9ED8\u8BA4 9999px */\n buttonBorderRadius?: string\n /** \u6587\u6848\u5B57\u53F7\uFF0C\u9ED8\u8BA4 14px */\n fontSize?: string\n /** Stay Here \u6309\u94AE\u80CC\u666F\u8272\uFF0C\u9ED8\u8BA4 #000 */\n stayButtonBgColor?: string\n /** Stay Here \u6309\u94AE\u6587\u5B57\u989C\u8272\uFF0C\u9ED8\u8BA4 #fff */\n stayButtonTextColor?: string\n /** Switch Site \u6309\u94AE\u8FB9\u6846\u989C\u8272\uFF0C\u9ED8\u8BA4 #000 */\n switchButtonBorderColor?: string\n /** Switch Site \u6309\u94AE\u6587\u5B57\u989C\u8272\uFF0C\u9ED8\u8BA4 #000 */\n switchButtonTextColor?: string\n /** \u5927\u5C4F\u5E55\uFF08\u22651920px\uFF09\u6700\u5927\u5BBD\u5EA6\uFF0C\u9ED8\u8BA4 1664px */\n maxWidth?: string\n}\n\nexport type RegionBannerProps = {\n /** \u63A7\u5236\u6A2A\u5E45\u663E\u793A/\u9690\u85CF */\n visible: boolean\n /** \u6A2A\u5E45\u72B6\u6001\u53D8\u5316\u56DE\u8C03 */\n onVisibleChange: (visible: boolean) => void\n /** \u6587\u6848\u914D\u7F6E */\n copy: IPRedirectBannerCopy\n /** \u70B9\u51FB Stay Here \u6309\u94AE\u7684\u56DE\u8C03 */\n onStayHere: () => void\n /** \u70B9\u51FB Switch Site \u6309\u94AE\u7684\u56DE\u8C03 */\n onSwitchSite: () => void\n /** \u6837\u5F0F\u914D\u7F6E */\n styles?: RegionBannerStyles\n /** \u5F53\u524D\u7AD9\u70B9\u5730\u533A\u914D\u7F6E\uFF08\u7528\u4E8E\u663E\u793A\u56FD\u65D7\u56FE\u6807\uFF09 */\n currentRegion?: RegionConfig\n /** \u81EA\u5B9A\u4E49\u7C7B\u540D */\n className?: string\n}\n\n// \u9ED8\u8BA4\u6837\u5F0F\nconst defaultStyles: Required<RegionBannerStyles> = {\n backgroundColor: '#fff',\n buttonBorderRadius: '9999px',\n fontSize: '14px',\n stayButtonBgColor: '#000',\n stayButtonTextColor: '#fff',\n switchButtonBorderColor: '#000',\n switchButtonTextColor: '#000',\n maxWidth: '1664px',\n}\n\nexport function RegionBanner({\n visible,\n onVisibleChange,\n copy,\n onStayHere,\n onSwitchSite,\n styles: customStyles,\n currentRegion,\n className,\n}: RegionBannerProps) {\n // \u5408\u5E76\u6837\u5F0F\n const styles = { ...defaultStyles, ...customStyles }\n\n if (!visible) return null\n\n const handleStayHere = () => {\n onStayHere()\n onVisibleChange(false)\n }\n\n const handleClose = () => {\n // \u5173\u95ED\u6309\u94AE\u548C Stay Here \u6309\u94AE\u884C\u4E3A\u4E00\u81F4\n onStayHere()\n onVisibleChange(false)\n }\n\n return (\n <>\n <style>{`\n .region-banner-wrapper {\n height: auto;\n min-height: 74px;\n }\n @media (min-width: 1024px) {\n .region-banner-wrapper {\n height: 54px;\n }\n }\n .region-banner-content {\n padding: 0 12px;\n flex-direction: column;\n gap: 8px;\n align-items: flex-start;\n }\n .region-banner-title-row {\n display: flex;\n align-items: center;\n width: 100%;\n gap: 8px;\n height: auto;\n margin-top: 8px;\n }\n .region-banner-content h1 {\n flex: 1;\n min-width: 0;\n }\n .region-banner-close-btn {\n position: static;\n flex-shrink: 0;\n }\n @media (min-width: 1024px) {\n .region-banner-content {\n padding: 0 64px;\n flex-direction: row;\n align-items: center;\n }\n .region-banner-title-row {\n flex: 1;\n height: 20px;\n }\n .region-banner-close-btn {\n position: absolute;\n right: 16px;\n top: 50%;\n transform: translateY(-50%);\n }\n }\n @media (min-width: 1920px) {\n .region-banner-wrapper {\n display: flex;\n justify-content: center;\n }\n .region-banner-content {\n max-width: ${styles.maxWidth};\n width: 100%;\n position: relative;\n padding-left: 0px;\n }\n }\n @media (min-width: 1025px) and (max-width: 1440px) {\n .region-banner-title {\n max-width: 623px;\n }\n }\n `}</style>\n\n <div\n className={`region-banner-wrapper relative left-0 top-0 w-full ${className || ''}`}\n style={{ backgroundColor: styles.backgroundColor, boxShadow: '0 2px 8px rgba(0,0,0,0.1)', zIndex: 1000 }}\n >\n <div className=\"region-banner-content flex h-full justify-between text-black\">\n <div className=\"region-banner-title-row\">\n <h1 className=\"region-banner-title font-bold\" style={{ fontSize: styles.fontSize, color: '#1F2021' }}>\n {copy.message}\n </h1>\n\n {/* \u5173\u95ED\u6309\u94AE */}\n <button\n onClick={handleClose}\n className=\"region-banner-close-btn inline-flex size-[28px] items-center justify-center rounded-full hover:bg-[#f5f5f5] focus:outline-none\"\n style={{ color: '#767880' }}\n aria-label=\"Close\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13.5 4.5L4.5 13.5M4.5 4.5L13.5 13.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n </div>\n\n <div className=\"l-tablet:ml-0 l-tablet:mb-[8px] ml-4 flex gap-3\">\n {/* Stay Here \u6309\u94AE */}\n <button\n onClick={handleStayHere}\n className=\"box-border flex h-[38px] items-center gap-1 whitespace-nowrap px-4 py-2 hover:opacity-80\"\n style={{\n backgroundColor: styles.stayButtonBgColor,\n color: styles.stayButtonTextColor,\n fontWeight: '700',\n fontSize: styles.fontSize,\n borderRadius: styles.buttonBorderRadius,\n border: 'none',\n }}\n >\n {currentRegion?.icon && (\n <img src={currentRegion.icon} alt=\"\" style={{ width: '16px', height: '16px', borderRadius: '100%' }} />\n )}\n {copy.stayButtonText}\n </button>\n\n {/* Switch Site \u6309\u94AE */}\n <button\n onClick={onSwitchSite}\n className=\"box-border flex h-[38px] items-center gap-1 whitespace-nowrap px-4 py-2 hover:opacity-80\"\n style={{\n backgroundColor: 'transparent',\n color: styles.switchButtonTextColor,\n border: `1.6px solid ${styles.switchButtonBorderColor}`,\n fontWeight: '700',\n fontSize: styles.fontSize,\n borderRadius: styles.buttonBorderRadius,\n }}\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.29883 1.2041C12.216 1.20425 15.3923 4.37181 15.3926 8.28027C15.3926 12.189 12.2162 15.3563 8.29883 15.3564C4.38145 15.3563 1.2041 12.189 1.2041 8.28027C1.20439 4.37183 4.38163 1.20428 8.29883 1.2041ZM3.58105 11.4795C4.31053 12.5471 5.39411 13.3542 6.66406 13.7324C6.21155 13.0301 5.86128 12.2699 5.60938 11.4795H3.58105ZM11.0166 11.4795C10.7696 12.2779 10.4256 13.0347 9.98438 13.7178C11.2325 13.3333 12.2971 12.5331 13.0166 11.4795H11.0166ZM7.0791 11.4795C7.3755 12.2654 7.78717 12.9997 8.31445 13.6455C8.83791 13.0305 9.25428 12.2929 9.55273 11.4795H7.0791ZM2.85645 6.56738C2.6854 7.10801 2.59283 7.68338 2.59277 8.28027C2.59277 8.91383 2.69891 9.52251 2.89063 10.0918H5.27148C5.15636 9.42693 5.10277 8.75388 5.11133 8.08789C5.11789 7.57837 5.1619 7.06931 5.23926 6.56738L2.85645 6.56738ZM11.3447 6.56738C11.4483 7.20036 11.4944 7.84036 11.4863 8.47363C11.4793 9.01629 11.4291 9.55828 11.3418 10.0918H13.707C13.8986 9.52259 14.0039 8.91374 14.0039 8.28027C14.0039 7.68337 13.9112 7.10802 13.7402 6.56738H11.3447ZM6.64648 6.56738C6.55761 7.06802 6.50673 7.58339 6.5 8.10547C6.49143 8.7725 6.55341 9.44067 6.68359 10.0918L9.93457 10.0918C10.0348 9.56074 10.0905 9.01207 10.0977 8.45605C10.1058 7.82231 10.0497 7.18763 9.93262 6.56738L6.64648 6.56738ZM6.6123 2.84277C5.32602 3.23909 4.23535 4.07819 3.51563 5.17969L5.5498 5.17969C5.79857 4.34514 6.15294 3.55384 6.6123 2.84277ZM9.93262 2.8291C10.4039 3.56047 10.7656 4.35407 11.0195 5.17969H13.0811C12.3519 4.06343 11.2413 3.21866 9.93262 2.8291ZM8.28223 2.91504C7.73775 3.55467 7.30932 4.32752 7.00879 5.17969L9.55566 5.17969C9.25672 4.35642 8.83179 3.58782 8.28223 2.91504Z\"\n fill=\"currentColor\"\n />\n </svg>\n {copy.switchButtonText}\n </button>\n </div>\n </div>\n </div>\n </>\n )\n}\n"],
|
|
5
|
+
"mappings": "sbAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,kBAAAE,IAAA,eAAAC,EAAAH,GAkFI,IAAAI,EAAA,6BAtCJ,MAAMC,EAA8C,CAClD,gBAAiB,OACjB,mBAAoB,SACpB,SAAU,OACV,kBAAmB,OACnB,oBAAqB,OACrB,wBAAyB,OACzB,sBAAuB,OACvB,SAAU,QACZ,EAEO,SAASH,EAAa,CAC3B,QAAAI,EACA,gBAAAC,EACA,KAAAC,EACA,WAAAC,EACA,aAAAC,EACA,OAAQC,EACR,cAAAC,EACA,UAAAC,CACF,EAAsB,CAEpB,MAAMC,EAAS,CAAE,GAAGT,EAAe,GAAGM,CAAa,EAEnD,GAAI,CAACL,EAAS,OAAO,KAErB,MAAMS,EAAiB,IAAM,CAC3BN,EAAW,EACXF,EAAgB,EAAK,CACvB,EAEMS,EAAc,IAAM,CAExBP,EAAW,EACXF,EAAgB,EAAK,CACvB,EAEA,SACE,oBACE,oBAAC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAuDWO,EAAO,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWhC,KAEF,OAAC,OACC,UAAW,sDAAsDD,GAAa,EAAE,GAChF,MAAO,CAAE,gBAAiBC,EAAO,gBAAiB,UAAW,4BAA6B,OAAQ,GAAK,EAEvG,oBAAC,OAAI,UAAU,+DACb,qBAAC,OAAI,UAAU,0BACb,oBAAC,MAAG,UAAU,gCAAgC,MAAO,CAAE,SAAUA,EAAO,SAAU,MAAO,SAAU,EAChG,SAAAN,EAAK,QACR,KAGA,OAAC,UACC,QAASQ,EACT,UAAU,iIACV,MAAO,CAAE,MAAO,SAAU,EAC1B,aAAW,QAEX,mBAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BAChE,mBAAC,QACC,EAAE,uCACF,OAAO,eACP,YAAY,MACZ,cAAc,QACd,eAAe,QACjB,EACF,EACF,GACF,KAEA,QAAC,OAAI,UAAU,kDAEb,qBAAC,UACC,QAASD,EACT,UAAU,2FACV,MAAO,CACL,gBAAiBD,EAAO,kBACxB,MAAOA,EAAO,oBACd,WAAY,MACZ,SAAUA,EAAO,SACjB,aAAcA,EAAO,mBACrB,OAAQ,MACV,EAEC,UAAAF,GAAe,SACd,OAAC,OAAI,IAAKA,EAAc,KAAM,IAAI,GAAG,MAAO,CAAE,MAAO,OAAQ,OAAQ,OAAQ,aAAc,MAAO,EAAG,EAEtGJ,EAAK,gBACR,KAGA,QAAC,UACC,QAASE,EACT,UAAU,2FACV,MAAO,CACL,gBAAiB,cACjB,MAAOI,EAAO,sBACd,OAAQ,eAAeA,EAAO,uBAAuB,GACrD,WAAY,MACZ,SAAUA,EAAO,SACjB,aAAcA,EAAO,kBACvB,EAEA,oBAAC,OAAI,MAAM,KAAK,OAAO,KAAK,QAAQ,YAAY,KAAK,OAAO,MAAM,6BAChE,mBAAC,QACC,EAAE,8lDACF,KAAK,eACP,EACF,EACCN,EAAK,kBACR,GACF,GACF,EACF,GACF,CAEJ",
|
|
6
|
+
"names": ["RegionBanner_exports", "__export", "RegionBanner", "__toCommonJS", "import_jsx_runtime", "defaultStyles", "visible", "onVisibleChange", "copy", "onStayHere", "onSwitchSite", "customStyles", "currentRegion", "className", "styles", "handleStayHere", "handleClose"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { RegionConfig, IPRedirectModalCopy } from './type.js';
|
|
2
|
+
/** 样式配置 */
|
|
3
|
+
export type RegionSelectorModalStyles = {
|
|
4
|
+
/** 弹窗宽度,默认 80% */
|
|
5
|
+
width?: string;
|
|
6
|
+
/** 弹窗最大宽度,默认 1000px */
|
|
7
|
+
maxWidth?: string;
|
|
8
|
+
/** 弹窗内边距,默认 '30px 32px' */
|
|
9
|
+
padding?: string;
|
|
10
|
+
/** 弹窗圆角,默认 16px */
|
|
11
|
+
borderRadius?: string;
|
|
12
|
+
/** 标题字号,默认 20px */
|
|
13
|
+
titleFontSize?: string;
|
|
14
|
+
/** 分组标题字号,默认 inherit */
|
|
15
|
+
groupTitleFontSize?: string;
|
|
16
|
+
/** 卡片高度,默认 56px */
|
|
17
|
+
itemHeight?: string;
|
|
18
|
+
/** 卡片背景色,默认 #f5f5f5 */
|
|
19
|
+
itemBgColor?: string;
|
|
20
|
+
/** 卡片圆角,默认 8px */
|
|
21
|
+
itemBorderRadius?: string;
|
|
22
|
+
/** 卡片间距,默认 8px */
|
|
23
|
+
itemGap?: string;
|
|
24
|
+
/** 每行卡片数量,默认 3 */
|
|
25
|
+
columns?: number;
|
|
26
|
+
};
|
|
27
|
+
export type RegionSelectorModalProps = {
|
|
28
|
+
/** 控制弹窗显示/隐藏 */
|
|
29
|
+
open: boolean;
|
|
30
|
+
/** 弹窗状态变化回调 */
|
|
31
|
+
onOpenChange: (open: boolean) => void;
|
|
32
|
+
/** 地区配置列表 */
|
|
33
|
+
regions: RegionConfig[];
|
|
34
|
+
/** 文案配置 */
|
|
35
|
+
copy: IPRedirectModalCopy;
|
|
36
|
+
/** 用户选择地区后的回调 */
|
|
37
|
+
onConfirm?: (region: RegionConfig) => void;
|
|
38
|
+
/** 是否自动跳转,默认 false */
|
|
39
|
+
autoRedirect?: boolean;
|
|
40
|
+
/** 是否跳转到首页(仅在 autoRedirect 为 true 时生效),默认 false(保留当前路径) */
|
|
41
|
+
redirectToHomepage?: boolean;
|
|
42
|
+
/** 样式配置 */
|
|
43
|
+
styles?: RegionSelectorModalStyles;
|
|
44
|
+
/** 自定义类名 */
|
|
45
|
+
className?: string;
|
|
46
|
+
/**
|
|
47
|
+
* 当前站点的地区代码(用于构建 ref 参数,表示从哪个站点跳转来的)
|
|
48
|
+
* 如果启用 autoRedirect,强烈建议提供此参数以便正确追踪跳转来源
|
|
49
|
+
*/
|
|
50
|
+
currentRegionCode?: string;
|
|
51
|
+
/**
|
|
52
|
+
* 自定义 ref 参数前缀(用于手动切换站点追踪)
|
|
53
|
+
* @default 'geo_redirect_manual'
|
|
54
|
+
* @example 'user_switch'
|
|
55
|
+
*/
|
|
56
|
+
refPrefixManual?: string;
|
|
57
|
+
};
|
|
58
|
+
export declare function RegionSelectorModal({ open, onOpenChange, regions, copy, onConfirm, autoRedirect, redirectToHomepage, styles: customStyles, className, currentRegionCode, refPrefixManual, }: RegionSelectorModalProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";var T=Object.create;var h=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var B=Object.getPrototypeOf,W=Object.prototype.hasOwnProperty;var H=(o,a)=>{for(var l in a)h(o,l,{get:a[l],enumerable:!0})},f=(o,a,l,c)=>{if(a&&typeof a=="object"||typeof a=="function")for(let s of M(a))!W.call(o,s)&&s!==l&&h(o,s,{get:()=>a[s],enumerable:!(c=$(a,s))||c.enumerable});return o};var D=(o,a,l)=>(l=o!=null?T(B(o)):{},f(a||!o||!o.__esModule?h(l,"default",{value:o,enumerable:!0}):l,o)),P=o=>f(h({},"__esModule",{value:!0}),o);var U={};H(U,{RegionSelectorModal:()=>G});module.exports=P(U);var t=require("react/jsx-runtime"),m=require("../../components/index.js"),p=D(require("@radix-ui/react-dialog")),w=require("react"),r=require("./utils.js");const j={width:"80%",maxWidth:"1000px",padding:"0px",borderRadius:"12px",titleFontSize:"24px",groupTitleFontSize:"18px",itemHeight:"54px",itemBgColor:"#F5F6F7",itemBorderRadius:"0px",itemGap:"8px",columns:3};function G({open:o,onOpenChange:a,regions:l,copy:c,onConfirm:s,autoRedirect:y=!1,redirectToHomepage:R=!1,styles:b,className:v,currentRegionCode:g,refPrefixManual:x="geo_redirect_manual"}){const i={...j,...b},C=n=>{if(s&&s(n),y){const d=window.location.search;if(R){const e=g?(0,r.buildGeoRedirectRefManual)(g,x):(0,r.buildGeoRedirectRefManual)(n.code,x),u=(0,r.appendRefParam)(n.url,e);window.location.href=u}else{const e=window.location.pathname,u=window.location.hash,N=`${n.url.replace(/\/$/,"")}${e}${d}`,k=g?(0,r.buildGeoRedirectRefManual)(g,x):(0,r.buildGeoRedirectRefManual)(n.code,x),F=(0,r.appendRefParam)(N,k)+u;window.location.href=F}}a(!1)},S=`calc((100% - ${i.itemGap} * ${i.columns-1}) / ${i.columns})`,z=(0,w.useMemo)(()=>{const n={};return l.forEach(d=>{const e=d.group||"Other";n[e]||(n[e]=[]),n[e].push(d)}),n},[l]);return(0,t.jsx)(p.Root,{open:o,onOpenChange:a,children:(0,t.jsxs)(p.Portal,{children:[(0,t.jsx)("style",{children:`
|
|
2
|
+
.region-item {
|
|
3
|
+
width: 100%;
|
|
4
|
+
}
|
|
5
|
+
@media (min-width: 1024px) {
|
|
6
|
+
.region-item {
|
|
7
|
+
width: ${S};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
.modal-content {
|
|
11
|
+
padding: 0 16px 32px 16px;
|
|
12
|
+
overflow-y: auto;
|
|
13
|
+
max-height: calc(90vh - 92px);
|
|
14
|
+
max-height: calc(90dvh - 92px);
|
|
15
|
+
-webkit-overflow-scrolling: touch;
|
|
16
|
+
}
|
|
17
|
+
@media (min-width: 1024px) {
|
|
18
|
+
.modal-content {
|
|
19
|
+
padding: 0 32px 32px 32px;
|
|
20
|
+
max-height: none;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
.modal-dialog {
|
|
24
|
+
width: 100% !important;
|
|
25
|
+
max-width: 100% !important;
|
|
26
|
+
top: 100px !important;
|
|
27
|
+
bottom: 0 !important;
|
|
28
|
+
height: calc(100vh - 100px) !important;
|
|
29
|
+
max-height: none !important;
|
|
30
|
+
}
|
|
31
|
+
@media (min-width: 1024px) {
|
|
32
|
+
.modal-dialog {
|
|
33
|
+
width: ${i.width} !important;
|
|
34
|
+
max-width: ${i.maxWidth} !important;
|
|
35
|
+
top: 50% !important;
|
|
36
|
+
bottom: auto !important;
|
|
37
|
+
transform: translate(-50%, -50%) !important;
|
|
38
|
+
height: auto !important;
|
|
39
|
+
max-height: calc(100vh - 32px) !important;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
.modal-title {
|
|
43
|
+
text-align: center;
|
|
44
|
+
}
|
|
45
|
+
@media (max-width: 1024px) {
|
|
46
|
+
.modal-title {
|
|
47
|
+
text-align: left;
|
|
48
|
+
font-size: 20px !important;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
.region-group {
|
|
52
|
+
gap: 12px;
|
|
53
|
+
}
|
|
54
|
+
@media (max-width: 1024px) {
|
|
55
|
+
.region-group {
|
|
56
|
+
gap: 0;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
.group-title {
|
|
60
|
+
margin-bottom: 8px;
|
|
61
|
+
}
|
|
62
|
+
@media (max-width: 1024px) {
|
|
63
|
+
.group-title {
|
|
64
|
+
font-size: 16px !important;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`}),(0,t.jsx)(p.Overlay,{className:"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-[9998] bg-black/50"}),(0,t.jsx)(p.Content,{className:`modal-dialog data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed left-1/2 z-[9999] -translate-x-1/2 overflow-hidden bg-white shadow-lg duration-200 ${v||""}`,style:{padding:i.padding,borderRadius:i.borderRadius},children:(0,t.jsxs)("div",{className:"flex flex-col",children:[(0,t.jsx)("div",{className:"relative flex items-center justify-end p-[16px]",children:(0,t.jsx)(p.Close,{asChild:!0,children:(0,t.jsx)("button",{className:"inline-flex size-[28px] items-center justify-center rounded-full hover:bg-[#f5f5f5] focus:outline-none",style:{color:"#767880"},"aria-label":"Close",children:(0,t.jsx)("svg",{width:"20",height:"20",viewBox:"0 0 18 18",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:(0,t.jsx)("path",{d:"M13.5 4.5L4.5 13.5M4.5 4.5L13.5 13.5",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})})})}),(0,t.jsxs)("div",{className:"modal-content flex flex-col gap-[24px]",children:[(0,t.jsx)(p.Title,{asChild:!0,children:(0,t.jsx)(m.Heading,{as:"h2",className:"modal-title text-[#1F2021]",style:{fontSize:i.titleFontSize,fontWeight:"700"},children:c.title})}),Object.entries(z).map(([n,d])=>(0,t.jsxs)("div",{className:"region-group flex flex-col",children:[(0,t.jsx)(m.Text,{size:3,className:"group-title text-left font-semibold text-[#1F2021]",style:{fontSize:i.groupTitleFontSize,fontWeight:"700"},children:n}),(0,t.jsx)("div",{className:"flex flex-wrap justify-start",style:{gap:i.itemGap},children:d.map(e=>(0,t.jsxs)("button",{onClick:()=>C(e),className:"region-item flex items-center gap-[12px] px-[16px] transition-colors hover:opacity-80",style:{height:i.itemHeight,backgroundColor:i.itemBgColor,borderRadius:i.itemBorderRadius},children:[(0,t.jsx)(m.Text,{size:2,className:"flex-1 text-left font-medium",style:{color:"#000",fontWeight:"700"},children:e.name}),(e.language||e.currency)&&(0,t.jsxs)(m.Text,{size:2,className:"shrink-0 text-[16px]",style:{color:"#767880"},children:[e.language,e.language&&e.currency&&" / ",e.currency]})]},e.code))})]},n))]})]})})]})})}
|
|
68
|
+
//# sourceMappingURL=RegionSelectorModal.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/biz-components/IPRedirect/RegionSelectorModal.tsx"],
|
|
4
|
+
"sourcesContent": ["import { Heading, Text } from '../../components/index.js'\nimport * as Dialog from '@radix-ui/react-dialog'\nimport { useMemo } from 'react'\nimport type { RegionConfig, IPRedirectModalCopy } from './type.js'\nimport { buildGeoRedirectRefManual, appendRefParam } from './utils.js'\n\n/** \u6837\u5F0F\u914D\u7F6E */\nexport type RegionSelectorModalStyles = {\n /** \u5F39\u7A97\u5BBD\u5EA6\uFF0C\u9ED8\u8BA4 80% */\n width?: string\n /** \u5F39\u7A97\u6700\u5927\u5BBD\u5EA6\uFF0C\u9ED8\u8BA4 1000px */\n maxWidth?: string\n /** \u5F39\u7A97\u5185\u8FB9\u8DDD\uFF0C\u9ED8\u8BA4 '30px 32px' */\n padding?: string\n /** \u5F39\u7A97\u5706\u89D2\uFF0C\u9ED8\u8BA4 16px */\n borderRadius?: string\n /** \u6807\u9898\u5B57\u53F7\uFF0C\u9ED8\u8BA4 20px */\n titleFontSize?: string\n /** \u5206\u7EC4\u6807\u9898\u5B57\u53F7\uFF0C\u9ED8\u8BA4 inherit */\n groupTitleFontSize?: string\n /** \u5361\u7247\u9AD8\u5EA6\uFF0C\u9ED8\u8BA4 56px */\n itemHeight?: string\n /** \u5361\u7247\u80CC\u666F\u8272\uFF0C\u9ED8\u8BA4 #f5f5f5 */\n itemBgColor?: string\n /** \u5361\u7247\u5706\u89D2\uFF0C\u9ED8\u8BA4 8px */\n itemBorderRadius?: string\n /** \u5361\u7247\u95F4\u8DDD\uFF0C\u9ED8\u8BA4 8px */\n itemGap?: string\n /** \u6BCF\u884C\u5361\u7247\u6570\u91CF\uFF0C\u9ED8\u8BA4 3 */\n columns?: number\n}\n\nexport type RegionSelectorModalProps = {\n /** \u63A7\u5236\u5F39\u7A97\u663E\u793A/\u9690\u85CF */\n open: boolean\n /** \u5F39\u7A97\u72B6\u6001\u53D8\u5316\u56DE\u8C03 */\n onOpenChange: (open: boolean) => void\n /** \u5730\u533A\u914D\u7F6E\u5217\u8868 */\n regions: RegionConfig[]\n /** \u6587\u6848\u914D\u7F6E */\n copy: IPRedirectModalCopy\n /** \u7528\u6237\u9009\u62E9\u5730\u533A\u540E\u7684\u56DE\u8C03 */\n onConfirm?: (region: RegionConfig) => void\n /** \u662F\u5426\u81EA\u52A8\u8DF3\u8F6C\uFF0C\u9ED8\u8BA4 false */\n autoRedirect?: boolean\n /** \u662F\u5426\u8DF3\u8F6C\u5230\u9996\u9875\uFF08\u4EC5\u5728 autoRedirect \u4E3A true \u65F6\u751F\u6548\uFF09\uFF0C\u9ED8\u8BA4 false\uFF08\u4FDD\u7559\u5F53\u524D\u8DEF\u5F84\uFF09 */\n redirectToHomepage?: boolean\n /** \u6837\u5F0F\u914D\u7F6E */\n styles?: RegionSelectorModalStyles\n /** \u81EA\u5B9A\u4E49\u7C7B\u540D */\n className?: string\n /**\n * \u5F53\u524D\u7AD9\u70B9\u7684\u5730\u533A\u4EE3\u7801\uFF08\u7528\u4E8E\u6784\u5EFA ref \u53C2\u6570\uFF0C\u8868\u793A\u4ECE\u54EA\u4E2A\u7AD9\u70B9\u8DF3\u8F6C\u6765\u7684\uFF09\n * \u5982\u679C\u542F\u7528 autoRedirect\uFF0C\u5F3A\u70C8\u5EFA\u8BAE\u63D0\u4F9B\u6B64\u53C2\u6570\u4EE5\u4FBF\u6B63\u786E\u8FFD\u8E2A\u8DF3\u8F6C\u6765\u6E90\n */\n currentRegionCode?: string\n /**\n * \u81EA\u5B9A\u4E49 ref \u53C2\u6570\u524D\u7F00\uFF08\u7528\u4E8E\u624B\u52A8\u5207\u6362\u7AD9\u70B9\u8FFD\u8E2A\uFF09\n * @default 'geo_redirect_manual'\n * @example 'user_switch'\n */\n refPrefixManual?: string\n}\n\nconst defaultStyles: Required<RegionSelectorModalStyles> = {\n width: '80%',\n maxWidth: '1000px',\n padding: '0px',\n borderRadius: '12px',\n titleFontSize: '24px',\n groupTitleFontSize: '18px',\n itemHeight: '54px',\n itemBgColor: '#F5F6F7',\n itemBorderRadius: '0px',\n itemGap: '8px',\n columns: 3,\n}\n\nexport function RegionSelectorModal({\n open,\n onOpenChange,\n regions,\n copy,\n onConfirm,\n autoRedirect = false,\n redirectToHomepage = false,\n styles: customStyles,\n className,\n currentRegionCode,\n refPrefixManual = 'geo_redirect_manual',\n}: RegionSelectorModalProps) {\n const styles = { ...defaultStyles, ...customStyles }\n\n const handleRegionClick = (region: RegionConfig) => {\n if (onConfirm) {\n onConfirm(region)\n }\n\n if (autoRedirect) {\n const currentSearch = window.location.search\n\n if (redirectToHomepage) {\n // \u4F7F\u7528\u5F53\u524D\u7AD9\u70B9\u4EE3\u7801\u6784\u5EFA ref \u53C2\u6570\uFF08\u8868\u793A\u4ECE\u54EA\u4E2A\u7AD9\u70B9\u8DF3\u8F6C\u6765\u7684\uFF09\n const refValue = currentRegionCode\n ? buildGeoRedirectRefManual(currentRegionCode, refPrefixManual)\n : buildGeoRedirectRefManual(region.code, refPrefixManual) // \u5411\u540E\u517C\u5BB9\uFF1A\u5982\u679C\u6CA1\u6709\u63D0\u4F9B currentRegionCode\uFF0C\u4F7F\u7528\u76EE\u6807\u7AD9\u70B9\u4EE3\u7801\n const targetUrl = appendRefParam(region.url, refValue)\n window.location.href = targetUrl\n } else {\n const currentPath = window.location.pathname\n const currentHash = window.location.hash\n const targetBaseUrl = region.url.replace(/\\/$/, '')\n const baseUrl = `${targetBaseUrl}${currentPath}${currentSearch}`\n // \u4F7F\u7528\u5F53\u524D\u7AD9\u70B9\u4EE3\u7801\u6784\u5EFA ref \u53C2\u6570\uFF08\u8868\u793A\u4ECE\u54EA\u4E2A\u7AD9\u70B9\u8DF3\u8F6C\u6765\u7684\uFF09\n const refValue = currentRegionCode\n ? buildGeoRedirectRefManual(currentRegionCode, refPrefixManual)\n : buildGeoRedirectRefManual(region.code, refPrefixManual) // \u5411\u540E\u517C\u5BB9\uFF1A\u5982\u679C\u6CA1\u6709\u63D0\u4F9B currentRegionCode\uFF0C\u4F7F\u7528\u76EE\u6807\u7AD9\u70B9\u4EE3\u7801\n const fullTargetUrl = appendRefParam(baseUrl, refValue) + currentHash\n window.location.href = fullTargetUrl\n }\n }\n\n onOpenChange(false)\n }\n\n const itemWidth = `calc((100% - ${styles.itemGap} * ${styles.columns - 1}) / ${styles.columns})`\n\n const groupedRegions = useMemo(() => {\n const groups: Record<string, RegionConfig[]> = {}\n regions.forEach(region => {\n const group = region.group || 'Other'\n if (!groups[group]) {\n groups[group] = []\n }\n groups[group].push(region)\n })\n return groups\n }, [regions])\n\n return (\n <Dialog.Root open={open} onOpenChange={onOpenChange}>\n <Dialog.Portal>\n <style>{`\n .region-item {\n width: 100%;\n }\n @media (min-width: 1024px) {\n .region-item {\n width: ${itemWidth};\n }\n }\n .modal-content {\n padding: 0 16px 32px 16px;\n overflow-y: auto;\n max-height: calc(90vh - 92px);\n max-height: calc(90dvh - 92px);\n -webkit-overflow-scrolling: touch;\n }\n @media (min-width: 1024px) {\n .modal-content {\n padding: 0 32px 32px 32px;\n max-height: none;\n }\n }\n .modal-dialog {\n width: 100% !important;\n max-width: 100% !important;\n top: 100px !important;\n bottom: 0 !important;\n height: calc(100vh - 100px) !important;\n max-height: none !important;\n }\n @media (min-width: 1024px) {\n .modal-dialog {\n width: ${styles.width} !important;\n max-width: ${styles.maxWidth} !important;\n top: 50% !important;\n bottom: auto !important;\n transform: translate(-50%, -50%) !important;\n height: auto !important;\n max-height: calc(100vh - 32px) !important;\n }\n }\n .modal-title {\n text-align: center;\n }\n @media (max-width: 1024px) {\n .modal-title {\n text-align: left;\n font-size: 20px !important;\n }\n }\n .region-group {\n gap: 12px;\n }\n @media (max-width: 1024px) {\n .region-group {\n gap: 0;\n }\n }\n .group-title {\n margin-bottom: 8px;\n }\n @media (max-width: 1024px) {\n .group-title {\n font-size: 16px !important;\n }\n }\n `}</style>\n <Dialog.Overlay className=\"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-[9998] bg-black/50\" />\n <Dialog.Content\n className={`modal-dialog data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed left-1/2 z-[9999] -translate-x-1/2 overflow-hidden bg-white shadow-lg duration-200 ${className || ''}`}\n style={{\n padding: styles.padding,\n borderRadius: styles.borderRadius,\n }}\n >\n <div className=\"flex flex-col\">\n <div className=\"relative flex items-center justify-end p-[16px]\">\n <Dialog.Close asChild>\n <button\n className=\"inline-flex size-[28px] items-center justify-center rounded-full hover:bg-[#f5f5f5] focus:outline-none\"\n style={{ color: '#767880' }}\n aria-label=\"Close\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 18 18\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13.5 4.5L4.5 13.5M4.5 4.5L13.5 13.5\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n </button>\n </Dialog.Close>\n </div>\n\n <div className=\"modal-content flex flex-col gap-[24px]\">\n <Dialog.Title asChild>\n <Heading\n as=\"h2\"\n className=\"modal-title text-[#1F2021]\"\n style={{ fontSize: styles.titleFontSize, fontWeight: '700' }}\n >\n {copy.title}\n </Heading>\n </Dialog.Title>\n {Object.entries(groupedRegions).map(([groupName, groupRegions]) => (\n <div key={groupName} className=\"region-group flex flex-col\">\n <Text\n size={3 as any}\n className=\"group-title text-left font-semibold text-[#1F2021]\"\n style={{ fontSize: styles.groupTitleFontSize, fontWeight: '700' }}\n >\n {groupName}\n </Text>\n <div className=\"flex flex-wrap justify-start\" style={{ gap: styles.itemGap }}>\n {groupRegions.map(region => (\n <button\n key={region.code}\n onClick={() => handleRegionClick(region)}\n className=\"region-item flex items-center gap-[12px] px-[16px] transition-colors hover:opacity-80\"\n style={{\n height: styles.itemHeight,\n backgroundColor: styles.itemBgColor,\n borderRadius: styles.itemBorderRadius,\n }}\n >\n <Text\n size={2 as any}\n className=\"flex-1 text-left font-medium\"\n style={{ color: '#000', fontWeight: '700' }}\n >\n {region.name}\n </Text>\n {(region.language || region.currency) && (\n <Text size={2 as any} className=\"shrink-0 text-[16px]\" style={{ color: '#767880' }}>\n {region.language}\n {region.language && region.currency && ' / '}\n {region.currency}\n </Text>\n )}\n </button>\n ))}\n </div>\n </div>\n ))}\n </div>\n </div>\n </Dialog.Content>\n </Dialog.Portal>\n </Dialog.Root>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["RegionSelectorModal_exports", "__export", "RegionSelectorModal", "__toCommonJS", "import_jsx_runtime", "import_components", "Dialog", "import_react", "import_utils", "defaultStyles", "open", "onOpenChange", "regions", "copy", "onConfirm", "autoRedirect", "redirectToHomepage", "customStyles", "className", "currentRegionCode", "refPrefixManual", "styles", "handleRegionClick", "region", "currentSearch", "refValue", "targetUrl", "currentPath", "currentHash", "baseUrl", "fullTargetUrl", "itemWidth", "groupedRegions", "groups", "group", "groupName", "groupRegions"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { RegionSelectorModal } from './RegionSelectorModal.js';
|
|
2
|
+
export { RegionBanner } from './RegionBanner.js';
|
|
3
|
+
export { RegionSelectorModal as default } from './RegionSelectorModal.js';
|
|
4
|
+
export { useRegionRedirectManager } from './useRegionRedirectManager.js';
|
|
5
|
+
export { generateRegionToPathMap, isPathInWhitelist, validateRegionConfig, localeToRegionCode, buildGeoRedirectRef, buildGeoRedirectRefManual, } from './utils.js';
|
|
6
|
+
export type { RegionSelectorModalProps, RegionSelectorModalStyles } from './RegionSelectorModal.js';
|
|
7
|
+
export type { RegionBannerProps, RegionBannerStyles } from './RegionBanner.js';
|
|
8
|
+
export type { UseRegionRedirectManagerOptions, UseRegionRedirectManagerReturn } from './useRegionRedirectManager.js';
|
|
9
|
+
export type { RegionConfig, IPRedirectModalCopy, IPRedirectBannerCopy, RegionToPathMap, CountryToRegionMap, } from './type.js';
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var i=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var c=Object.prototype.hasOwnProperty;var f=(r,o)=>{for(var t in o)i(r,t,{get:o[t],enumerable:!0})},M=(r,o,t,a)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of s(o))!c.call(r,n)&&n!==t&&i(r,n,{get:()=>o[n],enumerable:!(a=d(o,n))||a.enumerable});return r};var y=r=>M(i({},"__esModule",{value:!0}),r);var m={};f(m,{RegionBanner:()=>g.RegionBanner,RegionSelectorModal:()=>R.RegionSelectorModal,buildGeoRedirectRef:()=>e.buildGeoRedirectRef,buildGeoRedirectRefManual:()=>e.buildGeoRedirectRefManual,default:()=>p.RegionSelectorModal,generateRegionToPathMap:()=>e.generateRegionToPathMap,isPathInWhitelist:()=>e.isPathInWhitelist,localeToRegionCode:()=>e.localeToRegionCode,useRegionRedirectManager:()=>l.useRegionRedirectManager,validateRegionConfig:()=>e.validateRegionConfig});module.exports=y(m);var R=require("./RegionSelectorModal.js"),g=require("./RegionBanner.js"),p=require("./RegionSelectorModal.js"),l=require("./useRegionRedirectManager.js"),e=require("./utils.js");
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/biz-components/IPRedirect/index.ts"],
|
|
4
|
+
"sourcesContent": ["// ============================================\n// \u516C\u5171 API - UI \u7EC4\u4EF6\n// ============================================\nexport { RegionSelectorModal } from './RegionSelectorModal.js'\nexport { RegionBanner } from './RegionBanner.js'\nexport { RegionSelectorModal as default } from './RegionSelectorModal.js'\n\n// ============================================\n// \u516C\u5171 API - \u7EDF\u4E00 Hook\uFF08\u63A8\u8350\u4F7F\u7528\uFF09\n// ============================================\nexport { useRegionRedirectManager } from './useRegionRedirectManager.js'\n\n// ============================================\n// \u516C\u5171 API - \u5DE5\u5177\u51FD\u6570\n// ============================================\nexport {\n generateRegionToPathMap,\n isPathInWhitelist,\n validateRegionConfig,\n localeToRegionCode,\n buildGeoRedirectRef,\n buildGeoRedirectRefManual,\n} from './utils.js'\n\n// ============================================\n// \u516C\u5171 API - \u7C7B\u578B\u5B9A\u4E49\n// ============================================\nexport type { RegionSelectorModalProps, RegionSelectorModalStyles } from './RegionSelectorModal.js'\nexport type { RegionBannerProps, RegionBannerStyles } from './RegionBanner.js'\nexport type { UseRegionRedirectManagerOptions, UseRegionRedirectManagerReturn } from './useRegionRedirectManager.js'\nexport type {\n RegionConfig,\n IPRedirectModalCopy,\n IPRedirectBannerCopy,\n RegionToPathMap,\n CountryToRegionMap,\n} from './type.js'\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,8dAAAE,EAAAF,GAGA,IAAAG,EAAoC,oCACpCC,EAA6B,6BAC7BD,EAA+C,oCAK/CE,EAAyC,yCAKzCC,EAOO",
|
|
6
|
+
"names": ["IPRedirect_exports", "__export", "__toCommonJS", "import_RegionSelectorModal", "import_RegionBanner", "import_useRegionRedirectManager", "import_utils"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type RegionConfig = {
|
|
2
|
+
code: string;
|
|
3
|
+
name: string;
|
|
4
|
+
url: string;
|
|
5
|
+
group?: string;
|
|
6
|
+
language?: string;
|
|
7
|
+
languageCode?: string;
|
|
8
|
+
currency?: string;
|
|
9
|
+
icon?: string;
|
|
10
|
+
};
|
|
11
|
+
export type IPRedirectModalCopy = {
|
|
12
|
+
title: string;
|
|
13
|
+
};
|
|
14
|
+
export type IPRedirectBannerCopy = {
|
|
15
|
+
message: string;
|
|
16
|
+
stayButtonText: string;
|
|
17
|
+
switchButtonText: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* 地区代码到路径前缀的映射
|
|
21
|
+
* @example { US: '', CA: 'ca', DE: 'eu-de', UK: 'uk' }
|
|
22
|
+
*/
|
|
23
|
+
export type RegionToPathMap = Record<string, string>;
|
|
24
|
+
/**
|
|
25
|
+
* 国家代码到地区代码的映射
|
|
26
|
+
* @example { US: 'US', GB: 'UK', HK: 'DE' }
|
|
27
|
+
*/
|
|
28
|
+
export type CountryToRegionMap = Record<string, string>;
|
|
29
|
+
/**
|
|
30
|
+
* 配置验证结果
|
|
31
|
+
*/
|
|
32
|
+
export type ValidationResult = {
|
|
33
|
+
valid: boolean;
|
|
34
|
+
error?: string;
|
|
35
|
+
mappedRegion?: string;
|
|
36
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var i=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var s=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var a=(e,t,g,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of s(t))!p.call(e,r)&&r!==g&&i(e,r,{get:()=>t[r],enumerable:!(n=o(t,r))||n.enumerable});return e};var y=e=>a(i({},"__esModule",{value:!0}),e);var d={};module.exports=y(d);
|
|
2
|
+
//# sourceMappingURL=type.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/biz-components/IPRedirect/type.ts"],
|
|
4
|
+
"sourcesContent": ["export type RegionConfig = {\n code: string // \u56FD\u5BB6/\u5730\u533A\u4EE3\u7801\uFF0C\u5982 'US', 'CN', 'DE'\n name: string // \u663E\u793A\u540D\u79F0\uFF0C\u5982 'United States', '\u4E2D\u56FD'\n url: string // \u8DF3\u8F6C\u76EE\u6807 URL\n group?: string // \u5206\u7EC4\u540D\u79F0\uFF0C\u5982 'North America', 'Europe', 'Asia-Pacific'\n language?: string // \u663E\u793A\u7684\u8BED\u8A00\u540D\u79F0\uFF0C\u5982 'English', 'Deutsch'\n languageCode?: string // \u8BED\u8A00\u4EE3\u7801\uFF0C\u5982 'EN', 'DE', 'FR'\uFF08\u7528\u4E8E\u4FDD\u5B58\u5230 cookie\uFF09\n currency?: string // \u8D27\u5E01\u7B26\u53F7\uFF0C\u5982 '$', '\u20AC', '\u00A5'\n icon?: string // \u56FD\u5BB6/\u5730\u533A\u56FE\u6807 URL\uFF0C\u5982 '/icons/us.png'\n}\n\nexport type IPRedirectModalCopy = {\n title: string // \u5F39\u7A97\u6807\u9898\n}\n\nexport type IPRedirectBannerCopy = {\n message: string // \u6A2A\u5E45\u63D0\u793A\u6587\u6848\n stayButtonText: string // \"Stay Here\" \u6309\u94AE\u6587\u6848\n switchButtonText: string // \"Switch Site\" \u6309\u94AE\u6587\u6848\n}\n\n/**\n * \u5730\u533A\u4EE3\u7801\u5230\u8DEF\u5F84\u524D\u7F00\u7684\u6620\u5C04\n * @example { US: '', CA: 'ca', DE: 'eu-de', UK: 'uk' }\n */\nexport type RegionToPathMap = Record<string, string>\n\n/**\n * \u56FD\u5BB6\u4EE3\u7801\u5230\u5730\u533A\u4EE3\u7801\u7684\u6620\u5C04\n * @example { US: 'US', GB: 'UK', HK: 'DE' }\n */\nexport type CountryToRegionMap = Record<string, string>\n\n/**\n * \u914D\u7F6E\u9A8C\u8BC1\u7ED3\u679C\n */\nexport type ValidationResult = {\n valid: boolean // \u662F\u5426\u901A\u8FC7\u9A8C\u8BC1\n error?: string // \u9519\u8BEF\u4FE1\u606F\uFF08\u9A8C\u8BC1\u5931\u8D25\u65F6\uFF09\n mappedRegion?: string // \u6620\u5C04\u7684\u5730\u533A\u4EE3\u7801\uFF08\u9A8C\u8BC1\u6210\u529F\u65F6\uFF09\n}\n"],
|
|
5
|
+
"mappings": "+WAAA,IAAAA,EAAA,kBAAAC,EAAAD",
|
|
6
|
+
"names": ["type_exports", "__toCommonJS"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { RegionConfig } from './type.js';
|
|
2
|
+
export interface UseAutoRedirectOptions {
|
|
3
|
+
/**
|
|
4
|
+
* 地区代码到路径前缀的映射
|
|
5
|
+
* @example { US: '', CA: 'ca', DE: 'eu-de' }
|
|
6
|
+
*/
|
|
7
|
+
regionToPathMap: Record<string, string>;
|
|
8
|
+
/**
|
|
9
|
+
* 地理位置信息(包含国家代码)
|
|
10
|
+
*/
|
|
11
|
+
geo?: {
|
|
12
|
+
country?: {
|
|
13
|
+
code?: string;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* 当前站点的地区代码(用于构建 ref 参数,表示从哪个站点跳转来的)
|
|
18
|
+
*/
|
|
19
|
+
currentRegionCode: string;
|
|
20
|
+
/**
|
|
21
|
+
* 当前站点的 locale
|
|
22
|
+
*/
|
|
23
|
+
locale?: string;
|
|
24
|
+
/**
|
|
25
|
+
* 是否检查目标站点页面存在(需要实现 /api/check-page-exists 接口)
|
|
26
|
+
* @default true
|
|
27
|
+
*/
|
|
28
|
+
checkPageExists?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* 页面存在检查的 API 端点
|
|
31
|
+
* @default '/api/check-page-exists'
|
|
32
|
+
*/
|
|
33
|
+
checkPageApiEndpoint?: string;
|
|
34
|
+
/**
|
|
35
|
+
* 自定义 ref 参数前缀(用于自动跳转追踪)
|
|
36
|
+
* @default 'geo_redirect_auto'
|
|
37
|
+
* @example 'custom_tracking'
|
|
38
|
+
*/
|
|
39
|
+
refPrefix?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface UseAutoRedirectReturn {
|
|
42
|
+
/**
|
|
43
|
+
* 自动跳转到指定地区的函数
|
|
44
|
+
* @param region - 目标地区配置
|
|
45
|
+
* @param isCookieRedirect - 是否是通过 cookie 记忆触发的跳转
|
|
46
|
+
*/
|
|
47
|
+
handleAutoRedirect: (region: RegionConfig, isCookieRedirect?: boolean) => Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 自动跳转 Hook
|
|
51
|
+
* 处理地区跳转的核心逻辑,包括:
|
|
52
|
+
* - 路径保留和转换
|
|
53
|
+
* - 页面存在检查(可选)
|
|
54
|
+
* - UTM 参数处理
|
|
55
|
+
* - sessionStorage 标记
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```tsx
|
|
59
|
+
* const { handleAutoRedirect } = useAutoRedirect({
|
|
60
|
+
* regionToPathMap,
|
|
61
|
+
* geo,
|
|
62
|
+
* locale,
|
|
63
|
+
* checkPageExists: true,
|
|
64
|
+
* })
|
|
65
|
+
*
|
|
66
|
+
* // 当检测到地区不匹配时
|
|
67
|
+
* const targetRegion = regions.find(r => r.code === 'DE')
|
|
68
|
+
* await handleAutoRedirect(targetRegion)
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare function useAutoRedirect(options: UseAutoRedirectOptions): UseAutoRedirectReturn;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var p=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var U=Object.prototype.hasOwnProperty;var k=(n,o)=>{for(var e in o)p(n,e,{get:o[e],enumerable:!0})},b=(n,o,e,d)=>{if(o&&typeof o=="object"||typeof o=="function")for(let c of C(o))!U.call(n,c)&&c!==e&&p(n,c,{get:()=>o[c],enumerable:!(d=P(o,c))||d.enumerable});return n};var y=n=>b(p({},"__esModule",{value:!0}),n);var L={};k(L,{useAutoRedirect:()=>E});module.exports=y(L);var $=require("react"),t=require("./utils.js");function E(n){const{regionToPathMap:o,currentRegionCode:e,locale:d,checkPageExists:c=!0,checkPageApiEndpoint:h="/api/check-page-exists",refPrefix:u="geo_redirect_auto"}=n;return{handleAutoRedirect:(0,$.useCallback)(async(i,w=!1)=>{if(typeof window>"u")return;w?sessionStorage.setItem("cookie_redirected","true"):(sessionStorage.setItem("auto_redirected","true"),sessionStorage.setItem("auto_redirect_from",d||"US"));const m=(0,t.generateAllLocales)(o),f=(0,t.removeLocalePrefix)(window.location.pathname,m);let r;if(c)try{const s=o[i.code]||i.code.toLowerCase(),a=await fetch(`${h}?locale=${encodeURIComponent(s)}&path=${encodeURIComponent(f)}`),{exists:g}=await a.json();if(g){const l=window.location.search,R=window.location.hash;if(e){const x=(0,t.buildGeoRedirectRef)(e,u),A=`${i.url}${f}${l}`;r=`${(0,t.appendRefParam)(A,x)}${R}`}else r=`${i.url}${f}${l}${R}`}else if(r=i.url,e){const l=(0,t.buildGeoRedirectRef)(e,u);r=(0,t.appendRefParam)(r,l)}}catch(s){if(console.error("Error checking page during redirect:",s),r=i.url,e){const a=(0,t.buildGeoRedirectRef)(e,u);r=(0,t.appendRefParam)(r,a)}}else{const s=window.location.search,a=window.location.hash;if(e){const g=(0,t.buildGeoRedirectRef)(e,u),l=`${i.url}${f}${s}`;r=`${(0,t.appendRefParam)(l,g)}${a}`}else r=`${i.url}${f}${s}${a}`}window.location.href=r},[d,o,e,c,h,u])}}
|
|
2
|
+
//# sourceMappingURL=useAutoRedirect.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/biz-components/IPRedirect/useAutoRedirect.tsx"],
|
|
4
|
+
"sourcesContent": ["import { useCallback } from 'react'\nimport { generateAllLocales, removeLocalePrefix, buildGeoRedirectRef, appendRefParam } from './utils.js'\nimport type { RegionConfig } from './type.js'\n\nexport interface UseAutoRedirectOptions {\n /**\n * \u5730\u533A\u4EE3\u7801\u5230\u8DEF\u5F84\u524D\u7F00\u7684\u6620\u5C04\n * @example { US: '', CA: 'ca', DE: 'eu-de' }\n */\n regionToPathMap: Record<string, string>\n\n /**\n * \u5730\u7406\u4F4D\u7F6E\u4FE1\u606F\uFF08\u5305\u542B\u56FD\u5BB6\u4EE3\u7801\uFF09\n */\n geo?: {\n country?: {\n code?: string\n }\n }\n\n /**\n * \u5F53\u524D\u7AD9\u70B9\u7684\u5730\u533A\u4EE3\u7801\uFF08\u7528\u4E8E\u6784\u5EFA ref \u53C2\u6570\uFF0C\u8868\u793A\u4ECE\u54EA\u4E2A\u7AD9\u70B9\u8DF3\u8F6C\u6765\u7684\uFF09\n */\n currentRegionCode: string\n\n /**\n * \u5F53\u524D\u7AD9\u70B9\u7684 locale\n */\n locale?: string\n\n /**\n * \u662F\u5426\u68C0\u67E5\u76EE\u6807\u7AD9\u70B9\u9875\u9762\u5B58\u5728\uFF08\u9700\u8981\u5B9E\u73B0 /api/check-page-exists \u63A5\u53E3\uFF09\n * @default true\n */\n checkPageExists?: boolean\n\n /**\n * \u9875\u9762\u5B58\u5728\u68C0\u67E5\u7684 API \u7AEF\u70B9\n * @default '/api/check-page-exists'\n */\n checkPageApiEndpoint?: string\n\n /**\n * \u81EA\u5B9A\u4E49 ref \u53C2\u6570\u524D\u7F00\uFF08\u7528\u4E8E\u81EA\u52A8\u8DF3\u8F6C\u8FFD\u8E2A\uFF09\n * @default 'geo_redirect_auto'\n * @example 'custom_tracking'\n */\n refPrefix?: string\n}\n\nexport interface UseAutoRedirectReturn {\n /**\n * \u81EA\u52A8\u8DF3\u8F6C\u5230\u6307\u5B9A\u5730\u533A\u7684\u51FD\u6570\n * @param region - \u76EE\u6807\u5730\u533A\u914D\u7F6E\n * @param isCookieRedirect - \u662F\u5426\u662F\u901A\u8FC7 cookie \u8BB0\u5FC6\u89E6\u53D1\u7684\u8DF3\u8F6C\n */\n handleAutoRedirect: (region: RegionConfig, isCookieRedirect?: boolean) => Promise<void>\n}\n\n/**\n * \u81EA\u52A8\u8DF3\u8F6C Hook\n * \u5904\u7406\u5730\u533A\u8DF3\u8F6C\u7684\u6838\u5FC3\u903B\u8F91\uFF0C\u5305\u62EC\uFF1A\n * - \u8DEF\u5F84\u4FDD\u7559\u548C\u8F6C\u6362\n * - \u9875\u9762\u5B58\u5728\u68C0\u67E5\uFF08\u53EF\u9009\uFF09\n * - UTM \u53C2\u6570\u5904\u7406\n * - sessionStorage \u6807\u8BB0\n *\n * @example\n * ```tsx\n * const { handleAutoRedirect } = useAutoRedirect({\n * regionToPathMap,\n * geo,\n * locale,\n * checkPageExists: true,\n * })\n *\n * // \u5F53\u68C0\u6D4B\u5230\u5730\u533A\u4E0D\u5339\u914D\u65F6\n * const targetRegion = regions.find(r => r.code === 'DE')\n * await handleAutoRedirect(targetRegion)\n * ```\n */\nexport function useAutoRedirect(options: UseAutoRedirectOptions): UseAutoRedirectReturn {\n const {\n regionToPathMap,\n currentRegionCode,\n locale,\n checkPageExists = true,\n checkPageApiEndpoint = '/api/check-page-exists',\n refPrefix = 'geo_redirect_auto',\n } = options\n\n const handleAutoRedirect = useCallback(\n async (region: RegionConfig, isCookieRedirect = false) => {\n if (typeof window === 'undefined') return\n\n if (isCookieRedirect) {\n sessionStorage.setItem('cookie_redirected', 'true')\n } else {\n sessionStorage.setItem('auto_redirected', 'true')\n sessionStorage.setItem('auto_redirect_from', locale || 'US')\n }\n\n const allLocales = generateAllLocales(regionToPathMap)\n const pathWithoutLocale = removeLocalePrefix(window.location.pathname, allLocales)\n\n let targetUrl: string\n\n if (checkPageExists) {\n try {\n const targetLocale = regionToPathMap[region.code] || region.code.toLowerCase()\n\n const response = await fetch(\n `${checkPageApiEndpoint}?locale=${encodeURIComponent(\n targetLocale\n )}&path=${encodeURIComponent(pathWithoutLocale)}`\n )\n const { exists: pageExists } = await response.json()\n\n if (pageExists) {\n const currentSearch = window.location.search\n const currentHash = window.location.hash\n\n if (currentRegionCode) {\n const refValue = buildGeoRedirectRef(currentRegionCode, refPrefix)\n const baseUrl = `${region.url}${pathWithoutLocale}${currentSearch}`\n targetUrl = `${appendRefParam(baseUrl, refValue)}${currentHash}`\n } else {\n targetUrl = `${region.url}${pathWithoutLocale}${currentSearch}${currentHash}`\n }\n } else {\n targetUrl = region.url\n\n if (currentRegionCode) {\n const refValue = buildGeoRedirectRef(currentRegionCode, refPrefix)\n targetUrl = appendRefParam(targetUrl, refValue)\n }\n }\n } catch (error) {\n console.error('Error checking page during redirect:', error)\n targetUrl = region.url\n\n if (currentRegionCode) {\n const refValue = buildGeoRedirectRef(currentRegionCode, refPrefix)\n targetUrl = appendRefParam(targetUrl, refValue)\n }\n }\n } else {\n const currentSearch = window.location.search\n const currentHash = window.location.hash\n\n if (currentRegionCode) {\n const refValue = buildGeoRedirectRef(currentRegionCode, refPrefix)\n const baseUrl = `${region.url}${pathWithoutLocale}${currentSearch}`\n targetUrl = `${appendRefParam(baseUrl, refValue)}${currentHash}`\n } else {\n targetUrl = `${region.url}${pathWithoutLocale}${currentSearch}${currentHash}`\n }\n }\n\n window.location.href = targetUrl\n },\n [locale, regionToPathMap, currentRegionCode, checkPageExists, checkPageApiEndpoint, refPrefix]\n )\n\n return { handleAutoRedirect }\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,qBAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAA4B,iBAC5BC,EAA4F,sBAgFrF,SAASH,EAAgBI,EAAwD,CACtF,KAAM,CACJ,gBAAAC,EACA,kBAAAC,EACA,OAAAC,EACA,gBAAAC,EAAkB,GAClB,qBAAAC,EAAuB,yBACvB,UAAAC,EAAY,mBACd,EAAIN,EA2EJ,MAAO,CAAE,sBAzEkB,eACzB,MAAOO,EAAsBC,EAAmB,KAAU,CACxD,GAAI,OAAO,OAAW,IAAa,OAE/BA,EACF,eAAe,QAAQ,oBAAqB,MAAM,GAElD,eAAe,QAAQ,kBAAmB,MAAM,EAChD,eAAe,QAAQ,qBAAsBL,GAAU,IAAI,GAG7D,MAAMM,KAAa,sBAAmBR,CAAe,EAC/CS,KAAoB,sBAAmB,OAAO,SAAS,SAAUD,CAAU,EAEjF,IAAIE,EAEJ,GAAIP,EACF,GAAI,CACF,MAAMQ,EAAeX,EAAgBM,EAAO,IAAI,GAAKA,EAAO,KAAK,YAAY,EAEvEM,EAAW,MAAM,MACrB,GAAGR,CAAoB,WAAW,mBAChCO,CACF,CAAC,SAAS,mBAAmBF,CAAiB,CAAC,EACjD,EACM,CAAE,OAAQI,CAAW,EAAI,MAAMD,EAAS,KAAK,EAEnD,GAAIC,EAAY,CACd,MAAMC,EAAgB,OAAO,SAAS,OAChCC,EAAc,OAAO,SAAS,KAEpC,GAAId,EAAmB,CACrB,MAAMe,KAAW,uBAAoBf,EAAmBI,CAAS,EAC3DY,EAAU,GAAGX,EAAO,GAAG,GAAGG,CAAiB,GAAGK,CAAa,GACjEJ,EAAY,MAAG,kBAAeO,EAASD,CAAQ,CAAC,GAAGD,CAAW,EAChE,MACEL,EAAY,GAAGJ,EAAO,GAAG,GAAGG,CAAiB,GAAGK,CAAa,GAAGC,CAAW,EAE/E,SACEL,EAAYJ,EAAO,IAEfL,EAAmB,CACrB,MAAMe,KAAW,uBAAoBf,EAAmBI,CAAS,EACjEK,KAAY,kBAAeA,EAAWM,CAAQ,CAChD,CAEJ,OAASE,EAAO,CAId,GAHA,QAAQ,MAAM,uCAAwCA,CAAK,EAC3DR,EAAYJ,EAAO,IAEfL,EAAmB,CACrB,MAAMe,KAAW,uBAAoBf,EAAmBI,CAAS,EACjEK,KAAY,kBAAeA,EAAWM,CAAQ,CAChD,CACF,KACK,CACL,MAAMF,EAAgB,OAAO,SAAS,OAChCC,EAAc,OAAO,SAAS,KAEpC,GAAId,EAAmB,CACrB,MAAMe,KAAW,uBAAoBf,EAAmBI,CAAS,EAC3DY,EAAU,GAAGX,EAAO,GAAG,GAAGG,CAAiB,GAAGK,CAAa,GACjEJ,EAAY,MAAG,kBAAeO,EAASD,CAAQ,CAAC,GAAGD,CAAW,EAChE,MACEL,EAAY,GAAGJ,EAAO,GAAG,GAAGG,CAAiB,GAAGK,CAAa,GAAGC,CAAW,EAE/E,CAEA,OAAO,SAAS,KAAOL,CACzB,EACA,CAACR,EAAQF,EAAiBC,EAAmBE,EAAiBC,EAAsBC,CAAS,CAC/F,CAE4B,CAC9B",
|
|
6
|
+
"names": ["useAutoRedirect_exports", "__export", "useAutoRedirect", "__toCommonJS", "import_react", "import_utils", "options", "regionToPathMap", "currentRegionCode", "locale", "checkPageExists", "checkPageApiEndpoint", "refPrefix", "region", "isCookieRedirect", "allLocales", "pathWithoutLocale", "targetUrl", "targetLocale", "response", "pageExists", "currentSearch", "currentHash", "refValue", "baseUrl", "error"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { RegionConfig } from './type.js';
|
|
2
|
+
export interface UseDetectedRegionRedirectOptions {
|
|
3
|
+
/**
|
|
4
|
+
* 检测到的地区代码(从 useIPRedirect 的 onDetectRegion 返回)
|
|
5
|
+
*/
|
|
6
|
+
detectedRegion: string | null;
|
|
7
|
+
/**
|
|
8
|
+
* 当前站点的地区代码
|
|
9
|
+
*/
|
|
10
|
+
currentRegionCode: string;
|
|
11
|
+
/**
|
|
12
|
+
* 地区配置列表
|
|
13
|
+
*/
|
|
14
|
+
regions: RegionConfig[];
|
|
15
|
+
/**
|
|
16
|
+
* 白名单路径(在白名单中不执行跳转)
|
|
17
|
+
*/
|
|
18
|
+
excludePaths?: string[];
|
|
19
|
+
/**
|
|
20
|
+
* 当前路径
|
|
21
|
+
*/
|
|
22
|
+
pathname?: string;
|
|
23
|
+
/**
|
|
24
|
+
* 用户是否手动关闭了横幅(关闭横幅后不再自动跳转)
|
|
25
|
+
*/
|
|
26
|
+
userDismissedBanner?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* 自动跳转处理函数
|
|
29
|
+
*/
|
|
30
|
+
onRedirect: (region: RegionConfig, isCookieRedirect?: boolean) => void | Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* IP 检测地区跳转监听 Hook
|
|
34
|
+
*
|
|
35
|
+
* 监听 IP 检测到的推荐地区(来自 useIPRedirect 的 detectedRegion),
|
|
36
|
+
* 如果检测到的地区与当前地区不匹配,自动跳转到推荐地区
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```tsx
|
|
40
|
+
* useDetectedRegionRedirect({
|
|
41
|
+
* detectedRegion, // 从 useIPRedirect 获取
|
|
42
|
+
* currentRegionCode,
|
|
43
|
+
* regions,
|
|
44
|
+
* excludePaths,
|
|
45
|
+
* pathname,
|
|
46
|
+
* userDismissedBanner,
|
|
47
|
+
* onRedirect: handleAutoRedirect, // 从 useAutoRedirect 获取
|
|
48
|
+
* })
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function useDetectedRegionRedirect(options: UseDetectedRegionRedirectOptions): void;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var r=Object.defineProperty;var u=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var l=(i,e)=>{for(var n in e)r(i,n,{get:e[n],enumerable:!0})},h=(i,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of m(e))!p.call(i,t)&&t!==n&&r(i,t,{get:()=>e[t],enumerable:!(o=u(e,t))||o.enumerable});return i};var C=i=>h(r({},"__esModule",{value:!0}),i);var x={};l(x,{useDetectedRegionRedirect:()=>D});module.exports=C(x);var R=require("react"),f=require("./utils.js");function D(i){const{detectedRegion:e,currentRegionCode:n,regions:o,excludePaths:t=[],pathname:s="",userDismissedBanner:d=!1,onRedirect:c}=i;(0,R.useEffect)(()=>{if((0,f.isPathInWhitelist)(s,t)||d||!e||e===n)return;const g=o.find(a=>a.code===e);g&&c(g)},[e,n,o,d,c,s,t])}
|
|
2
|
+
//# sourceMappingURL=useDetectedRegionRedirect.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/biz-components/IPRedirect/useDetectedRegionRedirect.tsx"],
|
|
4
|
+
"sourcesContent": ["import { useEffect } from 'react'\nimport { isPathInWhitelist } from './utils.js'\nimport type { RegionConfig } from './type.js'\n\nexport interface UseDetectedRegionRedirectOptions {\n /**\n * \u68C0\u6D4B\u5230\u7684\u5730\u533A\u4EE3\u7801\uFF08\u4ECE useIPRedirect \u7684 onDetectRegion \u8FD4\u56DE\uFF09\n */\n detectedRegion: string | null\n\n /**\n * \u5F53\u524D\u7AD9\u70B9\u7684\u5730\u533A\u4EE3\u7801\n */\n currentRegionCode: string\n\n /**\n * \u5730\u533A\u914D\u7F6E\u5217\u8868\n */\n regions: RegionConfig[]\n\n /**\n * \u767D\u540D\u5355\u8DEF\u5F84\uFF08\u5728\u767D\u540D\u5355\u4E2D\u4E0D\u6267\u884C\u8DF3\u8F6C\uFF09\n */\n excludePaths?: string[]\n\n /**\n * \u5F53\u524D\u8DEF\u5F84\n */\n pathname?: string\n\n /**\n * \u7528\u6237\u662F\u5426\u624B\u52A8\u5173\u95ED\u4E86\u6A2A\u5E45\uFF08\u5173\u95ED\u6A2A\u5E45\u540E\u4E0D\u518D\u81EA\u52A8\u8DF3\u8F6C\uFF09\n */\n userDismissedBanner?: boolean\n\n /**\n * \u81EA\u52A8\u8DF3\u8F6C\u5904\u7406\u51FD\u6570\n */\n onRedirect: (region: RegionConfig, isCookieRedirect?: boolean) => void | Promise<void>\n}\n\n/**\n * IP \u68C0\u6D4B\u5730\u533A\u8DF3\u8F6C\u76D1\u542C Hook\n *\n * \u76D1\u542C IP \u68C0\u6D4B\u5230\u7684\u63A8\u8350\u5730\u533A\uFF08\u6765\u81EA useIPRedirect \u7684 detectedRegion\uFF09\uFF0C\n * \u5982\u679C\u68C0\u6D4B\u5230\u7684\u5730\u533A\u4E0E\u5F53\u524D\u5730\u533A\u4E0D\u5339\u914D\uFF0C\u81EA\u52A8\u8DF3\u8F6C\u5230\u63A8\u8350\u5730\u533A\n *\n * @example\n * ```tsx\n * useDetectedRegionRedirect({\n * detectedRegion, // \u4ECE useIPRedirect \u83B7\u53D6\n * currentRegionCode,\n * regions,\n * excludePaths,\n * pathname,\n * userDismissedBanner,\n * onRedirect: handleAutoRedirect, // \u4ECE useAutoRedirect \u83B7\u53D6\n * })\n * ```\n */\nexport function useDetectedRegionRedirect(options: UseDetectedRegionRedirectOptions): void {\n const {\n detectedRegion,\n currentRegionCode,\n regions,\n excludePaths = [],\n pathname = '',\n userDismissedBanner = false,\n onRedirect,\n } = options\n\n useEffect(() => {\n // \u767D\u540D\u5355\u68C0\u67E5\uFF1A\u5982\u679C\u5F53\u524D URL/\u8DEF\u5F84\u5728\u767D\u540D\u5355\u4E2D\uFF0C\u4E0D\u6267\u884C\u81EA\u52A8\u8DF3\u8F6C\n const inWhitelist = isPathInWhitelist(pathname, excludePaths)\n\n if (inWhitelist) {\n return\n }\n\n // \u5982\u679C\u7528\u6237\u5DF2\u624B\u52A8\u5173\u95ED\u6A2A\u5E45\uFF0C\u4E0D\u518D\u81EA\u52A8\u8DF3\u8F6C\n if (userDismissedBanner) {\n return\n }\n\n // \u5982\u679C\u6CA1\u6709\u68C0\u6D4B\u5230\u5730\u533A\uFF0C\u6216\u5730\u533A\u5339\u914D\uFF0C\u4E0D\u5904\u7406\n if (!detectedRegion || detectedRegion === currentRegionCode) {\n return\n }\n\n // \u83B7\u53D6\u76EE\u6807\u5730\u533A\u4FE1\u606F\u5E76\u81EA\u52A8\u8DF3\u8F6C\n const targetRegion = regions.find(r => r.code === detectedRegion)\n\n if (targetRegion) {\n // \u8C03\u7528\u81EA\u52A8\u8DF3\u8F6C\u903B\u8F91\uFF08\u4FDD\u7559\u5F53\u524D\u8DEF\u5F84\uFF09\n onRedirect(targetRegion)\n }\n }, [detectedRegion, currentRegionCode, regions, userDismissedBanner, onRedirect, pathname, excludePaths])\n}\n"],
|
|
5
|
+
"mappings": "yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,+BAAAE,IAAA,eAAAC,EAAAH,GAAA,IAAAI,EAA0B,iBAC1BC,EAAkC,sBA2D3B,SAASH,EAA0BI,EAAiD,CACzF,KAAM,CACJ,eAAAC,EACA,kBAAAC,EACA,QAAAC,EACA,aAAAC,EAAe,CAAC,EAChB,SAAAC,EAAW,GACX,oBAAAC,EAAsB,GACtB,WAAAC,CACF,EAAIP,KAEJ,aAAU,IAAM,CAcd,MAZoB,qBAAkBK,EAAUD,CAAY,GAOxDE,GAKA,CAACL,GAAkBA,IAAmBC,EACxC,OAIF,MAAMM,EAAeL,EAAQ,KAAKM,GAAKA,EAAE,OAASR,CAAc,EAE5DO,GAEFD,EAAWC,CAAY,CAE3B,EAAG,CAACP,EAAgBC,EAAmBC,EAASG,EAAqBC,EAAYF,EAAUD,CAAY,CAAC,CAC1G",
|
|
6
|
+
"names": ["useDetectedRegionRedirect_exports", "__export", "useDetectedRegionRedirect", "__toCommonJS", "import_react", "import_utils", "options", "detectedRegion", "currentRegionCode", "regions", "excludePaths", "pathname", "userDismissedBanner", "onRedirect", "targetRegion", "r"]
|
|
7
|
+
}
|