pb-sxp-ui 1.20.14 → 1.20.15

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.
Files changed (46) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +111 -111
  3. package/dist/index.cjs +940 -212
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.css +73 -72
  6. package/dist/index.js +940 -213
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.min.cjs +7 -7
  9. package/dist/index.min.cjs.map +1 -1
  10. package/dist/index.min.js +7 -7
  11. package/dist/index.min.js.map +1 -1
  12. package/dist/pb-ui.js +940 -212
  13. package/dist/pb-ui.js.map +1 -1
  14. package/dist/pb-ui.min.js +7 -7
  15. package/dist/pb-ui.min.js.map +1 -1
  16. package/es/core/components/DiyStoryPreview/index.js +10 -4
  17. package/es/core/components/StructurePage/index.d.ts +89 -0
  18. package/es/core/components/StructurePage/index.js +700 -0
  19. package/es/core/components/SxpPageRender/fakeData.js +1 -1
  20. package/es/core/components/SxpPageRender/index.js +10 -4
  21. package/es/core/context/SxpDataSourceProvider.js +4 -1
  22. package/es/core/hooks/useVisibleHeight.js +7 -7
  23. package/es/core/index.d.ts +2 -0
  24. package/es/core/index.js +1 -0
  25. package/es/core/utils/materials.d.ts +1 -1
  26. package/es/index.d.ts +1 -0
  27. package/es/index.js +1 -0
  28. package/es/materials/sxp/MultiPosts/index.js +4 -4
  29. package/es/materials/sxp/popup/CommodityDetail/index.js +4 -4
  30. package/es/materials/sxp/popup/CommodityDetailDiroNew/index.js +1 -1
  31. package/lib/core/components/DiyStoryPreview/index.js +10 -4
  32. package/lib/core/components/StructurePage/index.d.ts +89 -0
  33. package/lib/core/components/StructurePage/index.js +702 -0
  34. package/lib/core/components/SxpPageRender/fakeData.js +1 -1
  35. package/lib/core/components/SxpPageRender/index.js +10 -4
  36. package/lib/core/context/SxpDataSourceProvider.js +4 -1
  37. package/lib/core/hooks/useVisibleHeight.js +7 -7
  38. package/lib/core/index.d.ts +2 -0
  39. package/lib/core/index.js +6 -1
  40. package/lib/core/utils/materials.d.ts +1 -1
  41. package/lib/index.d.ts +1 -0
  42. package/lib/index.js +3 -1
  43. package/lib/materials/sxp/MultiPosts/index.js +4 -4
  44. package/lib/materials/sxp/popup/CommodityDetail/index.js +4 -4
  45. package/lib/materials/sxp/popup/CommodityDetailDiroNew/index.js +1 -1
  46. package/package.json +111 -111
package/dist/index.cjs CHANGED
@@ -678,6 +678,10 @@ const SxpDataSourceProvider = ({ render, dataSources, utmVal, enableReportEvent
678
678
  const [popupDetailData, setPopupDetailData] = React.useState();
679
679
  const [waterFallData, setWaterFallData] = React.useState();
680
680
  const [openHashtag, setOpenHashtag] = React.useState(isOpenHashTag);
681
+ // 将 setPopupDetailData 挂载到 window 对象,供 StructurePage 使用
682
+ if (typeof window !== 'undefined') {
683
+ window.setPopupDetailData = setPopupDetailData;
684
+ }
681
685
  const [cacheRtcList, setCacheRtcList] = React.useState([]);
682
686
  const [cacheActiveIndex, setCacheActiveIndex] = React.useState(0);
683
687
  const [isFromHashtag, setIsFromHashtag] = React.useState(false);
@@ -1137,7 +1141,7 @@ const SxpDataSourceProvider = ({ render, dataSources, utmVal, enableReportEvent
1137
1141
  query.pageNum = pageNum;
1138
1142
  result = isDiyH5
1139
1143
  ? yield (bffFetch === null || bffFetch === void 0 ? void 0 : bffFetch('v3/recommend/direct/page/view', { method: 'POST', body: query }))
1140
- : yield (bffFetch === null || bffFetch === void 0 ? void 0 : bffFetch('recommend/direct_page', { method: 'POST', body: query }));
1144
+ : yield (bffFetch === null || bffFetch === void 0 ? void 0 : bffFetch('v1/recommend/direct_page', { method: 'POST', body: query }));
1141
1145
  if (!(result === null || result === void 0 ? void 0 : result.success)) {
1142
1146
  return undefined;
1143
1147
  }
@@ -1365,6 +1369,7 @@ const SxpDataSourceProvider = ({ render, dataSources, utmVal, enableReportEvent
1365
1369
  var _a;
1366
1370
  const prop = match.substring(2, match.length - 2);
1367
1371
  try {
1372
+ // eslint-disable-next-line no-new-func
1368
1373
  let replaceValue = new Function('fix_par', 'product', `return ${prop}`)(fix_par, product === null || product === void 0 ? void 0 : product[0]);
1369
1374
  if (replaceValue) {
1370
1375
  if ((prop === null || prop === void 0 ? void 0 : prop.indexOf('currency')) !== -1 &&
@@ -1948,9 +1953,820 @@ const EditorCore = React.forwardRef(({ children, resolver, isSsr, schema, enable
1948
1953
  React.createElement(DataSourceProvider$1, { isSsr: isSsr, enable: enableDataSource }, children)));
1949
1954
  });
1950
1955
 
1956
+ const FormatImage = React.forwardRef((props, ref) => {
1957
+ const { src, onLoad, style, className, loading, alt = 'image' } = props;
1958
+ const [imgSrc, setImgSrc] = React.useState(src);
1959
+ const imgRef = React.useRef(null);
1960
+ const [visible, setVisible] = React.useState(false);
1961
+ React.useImperativeHandle(ref, () => ({
1962
+ setSrc: (v) => {
1963
+ if (v)
1964
+ setImgSrc(v);
1965
+ }
1966
+ }));
1967
+ React.useEffect(() => {
1968
+ if (src)
1969
+ setImgSrc(src);
1970
+ }, [src]);
1971
+ React.useEffect(() => {
1972
+ const onShow = () => {
1973
+ if (src && !visible && imgRef.current) {
1974
+ imgRef.current.src = '';
1975
+ imgRef.current.src = src;
1976
+ }
1977
+ };
1978
+ SXP_EVENT_BUS.on(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
1979
+ return () => {
1980
+ SXP_EVENT_BUS.off(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
1981
+ };
1982
+ }, [src, visible]);
1983
+ return (React.createElement(React.Fragment, null,
1984
+ !visible && !imgSrc && React.createElement("div", { style: { width: '100%', height: '100%', zIndex: 1, backgroundColor: '#fff' } }),
1985
+ (imgSrc === null || imgSrc === void 0 ? void 0 : imgSrc.includes('.avif')) ? (React.createElement("picture", null,
1986
+ React.createElement("source", { type: 'image/avif', srcSet: imgSrc }),
1987
+ React.createElement("source", { type: 'image/webp', srcSet: `${imgSrc}?imageMogr2/format/webp` }),
1988
+ React.createElement("source", { type: 'image/jpeg', srcSet: `${imgSrc}?imageMogr2/format/jpg` }),
1989
+ React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
1990
+ setVisible(true);
1991
+ onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
1992
+ }, alt: alt }))) : (React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
1993
+ setVisible(true);
1994
+ onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
1995
+ }, alt: alt }))));
1996
+ });
1997
+ var FormatImage$1 = React.memo(FormatImage);
1998
+
1999
+ // 动态导入材料库(避免循环依赖)
2000
+ const RESOLVER$3 = {};
2001
+ try {
2002
+ // 尝试动态导入材料库
2003
+ const materialsModule = require('../../materials/sxp');
2004
+ Object.values(materialsModule).forEach((v) => {
2005
+ var _a;
2006
+ if ((_a = v === null || v === void 0 ? void 0 : v.extend) === null || _a === void 0 ? void 0 : _a.type) {
2007
+ RESOLVER$3[v.extend.type] = v;
2008
+ }
2009
+ });
2010
+ }
2011
+ catch (error) {
2012
+ console.warn('Failed to load materials for StructurePage:', error);
2013
+ }
2014
+ // 基础样式定义
2015
+ const baseStyles = {
2016
+ container: {
2017
+ backgroundColor: '#000',
2018
+ overflowY: 'auto',
2019
+ overflowX: 'hidden',
2020
+ padding: 0,
2021
+ boxSizing: 'border-box'
2022
+ },
2023
+ section: {
2024
+ width: '100%',
2025
+ position: 'relative',
2026
+ boxSizing: 'border-box'
2027
+ },
2028
+ // Hero Section
2029
+ heroSection: {
2030
+ width: '100%',
2031
+ height: 'auto',
2032
+ position: 'relative',
2033
+ overflow: 'hidden',
2034
+ backgroundColor: '#000'
2035
+ },
2036
+ heroTopText: {
2037
+ width: '100%',
2038
+ padding: '20px',
2039
+ backgroundColor: '#fff',
2040
+ color: '#000',
2041
+ fontSize: '16px',
2042
+ fontWeight: 'bold',
2043
+ textAlign: 'center',
2044
+ boxSizing: 'border-box'
2045
+ },
2046
+ heroImageContainer: {
2047
+ width: '100%',
2048
+ position: 'relative',
2049
+ overflow: 'hidden'
2050
+ },
2051
+ heroImage: {
2052
+ width: '100%',
2053
+ height: 'auto',
2054
+ display: 'block',
2055
+ objectFit: 'cover'
2056
+ },
2057
+ heroVideo: {
2058
+ width: '100%',
2059
+ height: 'auto',
2060
+ display: 'block',
2061
+ objectFit: 'cover'
2062
+ },
2063
+ heroOverlay: {
2064
+ position: 'absolute',
2065
+ bottom: 0,
2066
+ left: 0,
2067
+ right: 0,
2068
+ padding: '40px 20px',
2069
+ background: 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 100%)',
2070
+ color: '#fff',
2071
+ display: 'flex',
2072
+ justifyContent: 'center',
2073
+ alignItems: 'center'
2074
+ },
2075
+ heroButton: {
2076
+ padding: '12px 30px',
2077
+ backgroundColor: '#fff',
2078
+ color: '#000',
2079
+ border: 'none',
2080
+ fontSize: '14px',
2081
+ fontWeight: 500,
2082
+ cursor: 'pointer',
2083
+ textTransform: 'uppercase'
2084
+ },
2085
+ // Carousel Section
2086
+ carouselSection: {
2087
+ width: '100%',
2088
+ position: 'relative'
2089
+ },
2090
+ carouselImageContainer: {
2091
+ width: '100%',
2092
+ height: 'auto',
2093
+ position: 'relative',
2094
+ overflow: 'hidden'
2095
+ },
2096
+ carouselContainer: {
2097
+ display: 'flex',
2098
+ transition: 'transform 0.5s ease-in-out',
2099
+ width: '100%'
2100
+ },
2101
+ carouselSlide: {
2102
+ minWidth: '100%',
2103
+ position: 'relative'
2104
+ },
2105
+ carouselImage: {
2106
+ width: '100%',
2107
+ height: 'auto',
2108
+ display: 'block',
2109
+ objectFit: 'cover'
2110
+ },
2111
+ carouselVideo: {
2112
+ width: '100%',
2113
+ height: 'auto',
2114
+ display: 'block',
2115
+ objectFit: 'cover'
2116
+ },
2117
+ carouselInfoSection: {
2118
+ width: '100%',
2119
+ padding: '20px',
2120
+ backgroundColor: '#000',
2121
+ color: '#fff',
2122
+ textAlign: 'center'
2123
+ },
2124
+ carouselText: {
2125
+ fontSize: '16px',
2126
+ fontWeight: 'normal',
2127
+ marginBottom: '15px',
2128
+ color: '#fff'
2129
+ },
2130
+ carouselButton: {
2131
+ padding: '10px 25px',
2132
+ backgroundColor: '#fff',
2133
+ color: '#000',
2134
+ border: '1px solid #fff',
2135
+ fontSize: '13px',
2136
+ fontWeight: 500,
2137
+ cursor: 'pointer',
2138
+ textTransform: 'uppercase'
2139
+ },
2140
+ arrowButton: {
2141
+ position: 'absolute',
2142
+ top: '50%',
2143
+ transform: 'translateY(-50%)',
2144
+ width: '40px',
2145
+ height: '40px',
2146
+ backgroundColor: 'rgba(255,255,255,0.8)',
2147
+ border: 'none',
2148
+ borderRadius: '50%',
2149
+ fontSize: '18px',
2150
+ cursor: 'pointer',
2151
+ zIndex: 10,
2152
+ display: 'flex',
2153
+ alignItems: 'center',
2154
+ justifyContent: 'center'
2155
+ },
2156
+ // Highlight Reveal Section
2157
+ highlightSection: {
2158
+ width: '100%',
2159
+ position: 'relative',
2160
+ backgroundColor: '#000'
2161
+ },
2162
+ highlightImageContainer: {
2163
+ width: '100%',
2164
+ aspectRatio: '1/1',
2165
+ position: 'relative',
2166
+ overflow: 'hidden'
2167
+ },
2168
+ highlightImage: {
2169
+ width: '100%',
2170
+ height: '100%',
2171
+ objectFit: 'cover',
2172
+ display: 'block'
2173
+ },
2174
+ highlightInfoSection: {
2175
+ width: '100%',
2176
+ padding: '20px',
2177
+ backgroundColor: '#000',
2178
+ color: '#fff',
2179
+ textAlign: 'center'
2180
+ },
2181
+ highlightTitle: {
2182
+ fontSize: '18px',
2183
+ fontWeight: 'bold',
2184
+ marginBottom: '10px',
2185
+ textAlign: 'center',
2186
+ color: '#fff'
2187
+ },
2188
+ highlightDesc: {
2189
+ fontSize: '14px',
2190
+ marginBottom: '15px',
2191
+ textAlign: 'center',
2192
+ lineHeight: '1.5',
2193
+ color: '#ccc'
2194
+ },
2195
+ highlightButton: {
2196
+ padding: '10px 25px',
2197
+ backgroundColor: 'transparent',
2198
+ color: '#fff',
2199
+ border: '1px solid #fff',
2200
+ fontSize: '13px',
2201
+ fontWeight: 500,
2202
+ cursor: 'pointer',
2203
+ textTransform: 'uppercase'
2204
+ },
2205
+ // Product Grid Section
2206
+ productGrid: {
2207
+ display: 'grid',
2208
+ gridTemplateColumns: '50% 50%',
2209
+ gridAutoRows: 'auto',
2210
+ gap: '0',
2211
+ width: '100%',
2212
+ backgroundColor: '#000',
2213
+ boxSizing: 'border-box',
2214
+ margin: 0,
2215
+ padding: 0,
2216
+ overflow: 'hidden'
2217
+ },
2218
+ productItem: {
2219
+ position: 'relative',
2220
+ backgroundColor: '#000',
2221
+ display: 'block',
2222
+ boxSizing: 'border-box',
2223
+ width: '100%',
2224
+ minWidth: 0,
2225
+ overflow: 'hidden'
2226
+ },
2227
+ productImageContainer: {
2228
+ width: '100%',
2229
+ paddingBottom: '100%',
2230
+ position: 'relative',
2231
+ overflow: 'hidden'
2232
+ },
2233
+ productImage: {
2234
+ position: 'absolute',
2235
+ top: 0,
2236
+ left: 0,
2237
+ width: '100%',
2238
+ height: '100%',
2239
+ objectFit: 'cover',
2240
+ display: 'block'
2241
+ },
2242
+ productCtaContainer: {
2243
+ width: '100%',
2244
+ padding: '15px',
2245
+ backgroundColor: '#000',
2246
+ textAlign: 'center',
2247
+ boxSizing: 'border-box'
2248
+ },
2249
+ productText: {
2250
+ width: '100%',
2251
+ padding: '15px',
2252
+ backgroundColor: '#000',
2253
+ color: '#fff',
2254
+ textAlign: 'center',
2255
+ fontSize: '14px',
2256
+ fontWeight: 'normal',
2257
+ boxSizing: 'border-box'
2258
+ },
2259
+ productButton: {
2260
+ padding: '8px 20px',
2261
+ backgroundColor: 'transparent',
2262
+ color: '#fff',
2263
+ border: '1px solid #fff',
2264
+ fontSize: '12px',
2265
+ fontWeight: 500,
2266
+ cursor: 'pointer',
2267
+ textTransform: 'uppercase',
2268
+ whiteSpace: 'nowrap'
2269
+ },
2270
+ // Footer Section
2271
+ footerSection: {
2272
+ width: '100%',
2273
+ position: 'relative',
2274
+ backgroundColor: '#000'
2275
+ },
2276
+ footerInfoSection: {
2277
+ width: '100%',
2278
+ padding: '20px',
2279
+ backgroundColor: '#000',
2280
+ color: '#fff',
2281
+ textAlign: 'center'
2282
+ },
2283
+ footerText: {
2284
+ fontSize: '18px',
2285
+ fontWeight: 'normal',
2286
+ marginBottom: '15px',
2287
+ lineHeight: '1.4',
2288
+ color: '#fff'
2289
+ },
2290
+ footerButton: {
2291
+ padding: '10px 25px',
2292
+ backgroundColor: 'transparent',
2293
+ color: '#fff',
2294
+ border: '1px solid #fff',
2295
+ fontSize: '13px',
2296
+ fontWeight: 500,
2297
+ cursor: 'pointer',
2298
+ textTransform: 'uppercase',
2299
+ marginBottom: '20px',
2300
+ display: 'inline-block'
2301
+ },
2302
+ footerImageContainer: {
2303
+ width: '100%',
2304
+ aspectRatio: '1/1',
2305
+ overflow: 'hidden'
2306
+ },
2307
+ footerImage: {
2308
+ width: '100%',
2309
+ height: '100%',
2310
+ objectFit: 'cover',
2311
+ display: 'block'
2312
+ }
2313
+ };
2314
+ const StructurePage = (_a) => {
2315
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
2316
+ var { containerStyle, containerHeight = 664, containerWidth = 375, className = '', apiUrl = 'https://bff-be-dev.chatlabs.net/api/v1/recommend/list', requestBody, editorMode = false, multiCTAConfig: propMultiCTAConfig, videoPlayIcon: propVideoPlayIcon, isCmsMode = false, storyId, customHeaders } = _a, rest = __rest(_a, ["containerStyle", "containerHeight", "containerWidth", "className", "apiUrl", "requestBody", "editorMode", "multiCTAConfig", "videoPlayIcon", "isCmsMode", "storyId", "customHeaders"]);
2317
+ const [data, setData] = React.useState(null);
2318
+ const [loading, setLoading] = React.useState(true);
2319
+ const [error, setError] = React.useState(null);
2320
+ const [carouselIndex, setCarouselIndex] = React.useState(0);
2321
+ const heroVideoRef = React.useRef(null);
2322
+ const carouselVideoRefs = React.useRef([]);
2323
+ // 视频暂停状态管理
2324
+ const [isHeroVideoPaused, setIsHeroVideoPaused] = React.useState(false);
2325
+ const [carouselVideoPausedStates, setCarouselVideoPausedStates] = React.useState([]);
2326
+ // 从 schema 中获取 multiCTAConfig(优先使用 props 传入的)
2327
+ const { schema } = useEditor();
2328
+ const multiCTAConfig = React.useMemo(() => {
2329
+ var _a;
2330
+ return propMultiCTAConfig || ((_a = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _a === void 0 ? void 0 : _a.multiCTAConfig) || {};
2331
+ }, [propMultiCTAConfig, (_b = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _b === void 0 ? void 0 : _b.multiCTAConfig]);
2332
+ // 默认播放图标 URL(直接使用 CDN 地址作为后备)
2333
+ const DEFAULT_PAUSE_ICON = 'https://sxph5-uat.chatlabs.net/pb_static/06f28a2025c74c1cb49be6767316d827.png';
2334
+ // 获取视频播放图标
2335
+ const videoPlayIcon = React.useMemo(() => {
2336
+ var _a, _b;
2337
+ // 优先使用 props 传入的
2338
+ if (propVideoPlayIcon)
2339
+ return propVideoPlayIcon;
2340
+ // 然后使用 schema 配置的
2341
+ const configIcon = (_b = (_a = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _a === void 0 ? void 0 : _a.globalConfig) === null || _b === void 0 ? void 0 : _b.videoPlayIcon;
2342
+ if (configIcon) {
2343
+ // 如果是完整 URL,直接使用
2344
+ if (configIcon.startsWith('http://') || configIcon.startsWith('https://')) {
2345
+ return configIcon;
2346
+ }
2347
+ // 如果是相对路径,拼接当前域名
2348
+ if (configIcon.startsWith('/')) {
2349
+ return `${window.location.origin}${configIcon}`;
2350
+ }
2351
+ return configIcon;
2352
+ }
2353
+ // 最后使用默认图标
2354
+ return DEFAULT_PAUSE_ICON;
2355
+ }, [propVideoPlayIcon, (_d = (_c = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _c === void 0 ? void 0 : _c.globalConfig) === null || _d === void 0 ? void 0 : _d.videoPlayIcon]);
2356
+ // 处理 CTA 点击
2357
+ const handleCtaClick = React.useCallback((link, interaction, productData, ctaData) => {
2358
+ // 如果配置了交互设置,优先使用交互设置
2359
+ if (interaction) {
2360
+ const { linkType, popupType, popupAni } = interaction;
2361
+ if (linkType === 'popup' && popupType) {
2362
+ // 设置弹窗要显示的产品数据
2363
+ if (productData && typeof window !== 'undefined' && window.setPopupDetailData) {
2364
+ // 构造与原有系统一致的数据结构
2365
+ const popupData = {
2366
+ video: {
2367
+ bindProduct: productData,
2368
+ bindProducts: [productData],
2369
+ bindCta: ctaData
2370
+ }
2371
+ };
2372
+ window.setPopupDetailData(popupData);
2373
+ }
2374
+ // 打开弹窗 - 使用与现有系统一致的方式
2375
+ if (typeof window !== 'undefined' && window.sxpPopup) {
2376
+ // 如果有动画配置,传递动画参数;否则只传弹窗 ID
2377
+ if (popupAni && popupAni.name) {
2378
+ window.sxpPopup(popupType, popupAni);
2379
+ }
2380
+ else {
2381
+ window.sxpPopup(popupType);
2382
+ }
2383
+ }
2384
+ return;
2385
+ }
2386
+ }
2387
+ // 默认行为:打开外部链接
2388
+ if (link) {
2389
+ window.open(link, '_blank');
2390
+ }
2391
+ }, []);
2392
+ // 合并基础样式和编辑器配置的样式
2393
+ const mergeStyles = React.useCallback((baseStyle, configKey) => {
2394
+ if (!editorMode || !multiCTAConfig[configKey]) {
2395
+ return baseStyle;
2396
+ }
2397
+ const config = multiCTAConfig[configKey];
2398
+ // 定义允许的样式属性列表
2399
+ const styleKeys = [
2400
+ 'fontSize', 'color', 'textAlign', 'fontWeight',
2401
+ 'backgroundColor', 'padding', 'margin', 'borderRadius',
2402
+ 'showBorder', 'borderWidth', 'borderColor',
2403
+ 'buttonBackgroundColor', 'buttonTextColor', 'buttonWidth', 'buttonHeight'
2404
+ ];
2405
+ // 只处理样式相关的属性,忽略 interaction 等非样式属性
2406
+ const styleConfig = Object.keys(config)
2407
+ .filter(key => styleKeys.includes(key))
2408
+ .reduce((obj, key) => {
2409
+ obj[key] = config[key];
2410
+ return obj;
2411
+ }, {});
2412
+ // 如果配置中没有任何样式字段(只有 interaction),直接返回基础样式
2413
+ if (Object.keys(styleConfig).length === 0) {
2414
+ return baseStyle;
2415
+ }
2416
+ const customStyle = {};
2417
+ // 应用配置中的样式
2418
+ if (styleConfig.fontSize && typeof styleConfig.fontSize === 'number') {
2419
+ customStyle.fontSize = `${styleConfig.fontSize}px`;
2420
+ }
2421
+ if (styleConfig.color && typeof styleConfig.color === 'string') {
2422
+ customStyle.color = styleConfig.color;
2423
+ }
2424
+ if (styleConfig.textAlign && typeof styleConfig.textAlign === 'string') {
2425
+ customStyle.textAlign = styleConfig.textAlign;
2426
+ }
2427
+ if (styleConfig.fontWeight && typeof styleConfig.fontWeight === 'number') {
2428
+ customStyle.fontWeight = styleConfig.fontWeight;
2429
+ }
2430
+ if (styleConfig.backgroundColor && typeof styleConfig.backgroundColor === 'string') {
2431
+ customStyle.backgroundColor = styleConfig.backgroundColor;
2432
+ }
2433
+ if (styleConfig.padding && typeof styleConfig.padding === 'string') {
2434
+ customStyle.padding = styleConfig.padding;
2435
+ }
2436
+ if (styleConfig.margin && typeof styleConfig.margin === 'string') {
2437
+ customStyle.margin = styleConfig.margin;
2438
+ }
2439
+ if (styleConfig.borderRadius && typeof styleConfig.borderRadius === 'number') {
2440
+ customStyle.borderRadius = `${styleConfig.borderRadius}px`;
2441
+ }
2442
+ if (styleConfig.showBorder && styleConfig.borderWidth && typeof styleConfig.borderWidth === 'number') {
2443
+ customStyle.border = `${styleConfig.borderWidth}px solid ${styleConfig.borderColor || '#d9d9d9'}`;
2444
+ }
2445
+ // 按钮特殊样式
2446
+ if (styleConfig.buttonBackgroundColor && typeof styleConfig.buttonBackgroundColor === 'string') {
2447
+ customStyle.backgroundColor = styleConfig.buttonBackgroundColor;
2448
+ }
2449
+ if (styleConfig.buttonTextColor && typeof styleConfig.buttonTextColor === 'string') {
2450
+ customStyle.color = styleConfig.buttonTextColor;
2451
+ }
2452
+ if (styleConfig.buttonWidth && typeof styleConfig.buttonWidth === 'number') {
2453
+ customStyle.width = `${styleConfig.buttonWidth}px`;
2454
+ }
2455
+ if (styleConfig.buttonHeight && typeof styleConfig.buttonHeight === 'number') {
2456
+ customStyle.height = `${styleConfig.buttonHeight}px`;
2457
+ }
2458
+ return Object.assign(Object.assign({}, baseStyle), customStyle);
2459
+ }, [editorMode, multiCTAConfig]);
2460
+ // 渲染 CTA 按钮或模版组件
2461
+ const renderCTA = React.useCallback((buttonKey, ctaData, productData, fallbackStyle) => {
2462
+ var _a, _b, _c;
2463
+ if (!ctaData) {
2464
+ return null;
2465
+ }
2466
+ const config = multiCTAConfig[buttonKey];
2467
+ const templateType = config === null || config === void 0 ? void 0 : config.templateType;
2468
+ const interaction = config === null || config === void 0 ? void 0 : config.interaction;
2469
+ // 如果配置了模版类型,渲染对应的模版组件
2470
+ if (editorMode && templateType && RESOLVER$3[templateType]) {
2471
+ const TemplateComponent = RESOLVER$3[templateType];
2472
+ const templateExtend = TemplateComponent === null || TemplateComponent === void 0 ? void 0 : TemplateComponent.extend;
2473
+ if (templateExtend) {
2474
+ // 准备模版组件的 props
2475
+ const templateProps = Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (_a = templateExtend.defaulSetting) === null || _a === void 0 ? void 0 : _a.props), { style: Object.assign(Object.assign(Object.assign({}, (_b = templateExtend.defaulSetting) === null || _b === void 0 ? void 0 : _b.style), mergeStyles(fallbackStyle || {}, buttonKey)), { marginBottom: 0, width: '100%' }), textStyle: (_c = templateExtend.defaulSetting) === null || _c === void 0 ? void 0 : _c.textStyle }), (productData && { bindProduct: productData })), { isTel: true }), rest);
2476
+ // 渲染模版组件
2477
+ return React.createElement(TemplateComponent, templateProps);
2478
+ }
2479
+ }
2480
+ // 默认渲染按钮
2481
+ return (React.createElement("button", { style: mergeStyles(fallbackStyle || baseStyles.heroButton, buttonKey), onClick: () => handleCtaClick(ctaData === null || ctaData === void 0 ? void 0 : ctaData.link, interaction, productData, ctaData) }, ctaData.title));
2482
+ }, [multiCTAConfig, editorMode, handleCtaClick, mergeStyles, rest]);
2483
+ // 获取数据 - 只在组件挂载时执行一次
2484
+ React.useEffect(() => {
2485
+ // 重要:在 PB 编辑器模式下,propMultiCTAConfig 只是样式配置,不是数据源
2486
+ // 只有在 CMS 模式 (isCmsMode=false) 且 propMultiCTAConfig 包含实际数据时才跳过 API 调用
2487
+ // 判断是否包含实际数据:检查是否有 heroSection, carouselSection 等数据字段
2488
+ const hasActualData = propMultiCTAConfig && (propMultiCTAConfig.heroSection ||
2489
+ propMultiCTAConfig.carouselSection ||
2490
+ propMultiCTAConfig.highlightRevealSection ||
2491
+ propMultiCTAConfig.productGridSection ||
2492
+ propMultiCTAConfig.footerSection);
2493
+ if (editorMode && hasActualData && !isCmsMode) {
2494
+ setLoading(false);
2495
+ setError(null);
2496
+ // 使用传入的 multiCTAConfig 作为数据源
2497
+ setData(propMultiCTAConfig);
2498
+ return;
2499
+ }
2500
+ // 如果已经有数据了,且在编辑器模式下,不要重新请求
2501
+ if (editorMode && data && !isCmsMode) {
2502
+ return;
2503
+ }
2504
+ setLoading(true);
2505
+ setError(null);
2506
+ // 根据模式决定使用哪个接口
2507
+ let finalApiUrl = apiUrl;
2508
+ let bodyToSend = {};
2509
+ if (isCmsMode) {
2510
+ // CMS 模式:使用 /api/console/ad/multiCta/rec/detail 接口
2511
+ if (!storyId) {
2512
+ console.error('[StructurePage CMS Mode] storyId is required but not provided');
2513
+ setError('storyId is required in CMS mode');
2514
+ setLoading(false);
2515
+ return;
2516
+ }
2517
+ // 构建 CMS 接口的 URL 和请求体
2518
+ // apiUrl 应该是域名(如 http://localhost:8001),然后拼接 /api/console/ad/multiCta/rec/detail
2519
+ finalApiUrl = `${apiUrl}/api/console/ad/multiCta/rec/detail`;
2520
+ bodyToSend = { storyId };
2521
+ }
2522
+ else {
2523
+ // 普通模式:使用原有的 /api/v1/recommend/list 接口
2524
+ const defaultBody = {
2525
+ maxSize: 20,
2526
+ defaultSize: 10,
2527
+ type: 'story'
2528
+ };
2529
+ bodyToSend = requestBody ? Object.assign(Object.assign({}, defaultBody), requestBody) : defaultBody;
2530
+ }
2531
+ // 构建请求头
2532
+ const headers = {
2533
+ 'Content-Type': 'application/json'
2534
+ };
2535
+ if (isCmsMode) {
2536
+ // CMS 模式:使用自定义 headers(如果有传入)
2537
+ if (customHeaders) {
2538
+ Object.assign(headers, customHeaders);
2539
+ }
2540
+ }
2541
+ else {
2542
+ // 普通模式:从 requestBody 或 bodyToSend 中提取 BFF headers
2543
+ if (bodyToSend['x-app-id']) {
2544
+ headers['x-app-id'] = bodyToSend['x-app-id'];
2545
+ delete bodyToSend['x-app-id'];
2546
+ }
2547
+ if (bodyToSend['x-user-id']) {
2548
+ headers['x-user-id'] = bodyToSend['x-user-id'];
2549
+ delete bodyToSend['x-user-id'];
2550
+ }
2551
+ if (bodyToSend['tenant-id']) {
2552
+ headers['tenant-id'] = bodyToSend['tenant-id'];
2553
+ delete bodyToSend['tenant-id'];
2554
+ }
2555
+ }
2556
+ fetch(finalApiUrl, {
2557
+ method: 'POST',
2558
+ headers,
2559
+ body: JSON.stringify(bodyToSend),
2560
+ credentials: 'include'
2561
+ })
2562
+ .then((res) => {
2563
+ if (!res.ok) {
2564
+ throw new Error(`HTTP error! status: ${res.status}`);
2565
+ }
2566
+ return res.json();
2567
+ })
2568
+ .then((result) => {
2569
+ var _a, _b, _c, _d;
2570
+ if (result.code === '0' || result.code === '00000') {
2571
+ // 判断数据结构:CMS 模式和普通模式可能不同
2572
+ let multiCtaData = null;
2573
+ if (isCmsMode) {
2574
+ // CMS 模式:data.multiCta
2575
+ multiCtaData = (_a = result.data) === null || _a === void 0 ? void 0 : _a.multiCta;
2576
+ }
2577
+ else {
2578
+ // 普通模式:data.recList[0].multiCta
2579
+ multiCtaData = (_d = (_c = (_b = result.data) === null || _b === void 0 ? void 0 : _b.recList) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.multiCta;
2580
+ }
2581
+ if (multiCtaData) {
2582
+ setData(multiCtaData);
2583
+ }
2584
+ else {
2585
+ console.error('[StructurePage] No multiCta data found in response:', result);
2586
+ setError(result.message || 'No multiCta data found');
2587
+ }
2588
+ }
2589
+ else {
2590
+ setError(result.message || 'Failed to load data');
2591
+ }
2592
+ setLoading(false);
2593
+ })
2594
+ .catch((err) => {
2595
+ console.error('[StructurePage] Failed to fetch data:', {
2596
+ error: err,
2597
+ message: err.message,
2598
+ url: finalApiUrl,
2599
+ body: bodyToSend,
2600
+ isCmsMode,
2601
+ storyId
2602
+ });
2603
+ setError(err.message || 'Network error');
2604
+ setLoading(false);
2605
+ });
2606
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2607
+ }, [apiUrl, isCmsMode, storyId, customHeaders]);
2608
+ // 注意:移除了 editorMode 和 propMultiCTAConfig 依赖,因为:
2609
+ // 1. editorMode 和 propMultiCTAConfig 在编辑器中频繁变化
2610
+ // 2. propMultiCTAConfig 只是样式配置,不是数据源
2611
+ // 3. 数据获取只应该在组件挂载时执行一次(除非 apiUrl/storyId 等关键参数变化)
2612
+ // Hero Section 视频自动播放
2613
+ React.useEffect(() => {
2614
+ var _a;
2615
+ if (heroVideoRef.current && ((_a = data === null || data === void 0 ? void 0 : data.heroSection) === null || _a === void 0 ? void 0 : _a.url)) {
2616
+ heroVideoRef.current.play().catch((err) => console.log('Video autoplay failed:', err));
2617
+ setIsHeroVideoPaused(false);
2618
+ }
2619
+ }, [data === null || data === void 0 ? void 0 : data.heroSection]);
2620
+ // 初始化 carousel 视频暂停状态
2621
+ React.useEffect(() => {
2622
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2623
+ // carousel 视频默认不自动播放,所以初始状态应该是暂停(true)
2624
+ setCarouselVideoPausedStates(new Array(data.carouselSection.length).fill(true));
2625
+ }
2626
+ }, [data === null || data === void 0 ? void 0 : data.carouselSection]);
2627
+ // Hero 视频点击处理
2628
+ const handleHeroVideoClick = React.useCallback(() => {
2629
+ if (heroVideoRef.current) {
2630
+ if (heroVideoRef.current.paused) {
2631
+ heroVideoRef.current.play();
2632
+ setIsHeroVideoPaused(false);
2633
+ }
2634
+ else {
2635
+ heroVideoRef.current.pause();
2636
+ setIsHeroVideoPaused(true);
2637
+ }
2638
+ }
2639
+ }, []);
2640
+ // Carousel 视频点击处理
2641
+ const handleCarouselVideoClick = React.useCallback((index) => {
2642
+ const videoRef = carouselVideoRefs.current[index];
2643
+ if (videoRef) {
2644
+ if (videoRef.paused) {
2645
+ videoRef.play();
2646
+ setCarouselVideoPausedStates(prev => {
2647
+ const newStates = [...prev];
2648
+ newStates[index] = false;
2649
+ return newStates;
2650
+ });
2651
+ }
2652
+ else {
2653
+ videoRef.pause();
2654
+ setCarouselVideoPausedStates(prev => {
2655
+ const newStates = [...prev];
2656
+ newStates[index] = true;
2657
+ return newStates;
2658
+ });
2659
+ }
2660
+ }
2661
+ }, []);
2662
+ // Carousel 导航
2663
+ const handleCarouselPrev = () => {
2664
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2665
+ setCarouselIndex((prev) => (prev === 0 ? data.carouselSection.length - 1 : prev - 1));
2666
+ }
2667
+ };
2668
+ const handleCarouselNext = () => {
2669
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2670
+ setCarouselIndex((prev) => (prev === data.carouselSection.length - 1 ? 0 : prev + 1));
2671
+ }
2672
+ };
2673
+ if (loading) {
2674
+ return (React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: '16px' }) }, "Loading..."));
2675
+ }
2676
+ if (error) {
2677
+ return (React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', color: '#fff', padding: '20px', textAlign: 'center' }) },
2678
+ React.createElement("div", { style: { fontSize: '18px', marginBottom: '10px' } }, "\u26A0\uFE0F Error"),
2679
+ React.createElement("div", { style: { fontSize: '14px', opacity: 0.8 } }, error)));
2680
+ }
2681
+ if (!data) {
2682
+ return (React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#fff', fontSize: '16px' }) }, "No data available"));
2683
+ }
2684
+ return (React.createElement("div", { className: className, style: Object.assign(Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth }), containerStyle) },
2685
+ data.heroSection && (React.createElement("div", { style: baseStyles.heroSection },
2686
+ data.heroSection.text && (React.createElement("div", { style: mergeStyles(baseStyles.heroTopText, 'heroTopText') }, data.heroSection.text)),
2687
+ React.createElement("div", { style: baseStyles.heroImageContainer },
2688
+ data.heroSection.url ? (React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: handleHeroVideoClick },
2689
+ React.createElement("video", { ref: heroVideoRef, src: data.heroSection.url, style: baseStyles.heroVideo, autoPlay: true, muted: true, loop: true, playsInline: true, controls: false }),
2690
+ isHeroVideoPaused && (React.createElement(FormatImage$1, { className: 'clc-pb-video-pause', src: videoPlayIcon, alt: 'play' })))) : ((_e = data.heroSection.imgUrls) === null || _e === void 0 ? void 0 : _e[0]) ? (React.createElement("img", { src: data.heroSection.imgUrls[0], alt: 'Hero', style: baseStyles.heroImage })) : null,
2691
+ React.createElement("div", { style: baseStyles.heroOverlay }, renderCTA('heroButton', (_g = (_f = data.heroSection.bindProducts) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g.bindCta, (_h = data.heroSection.bindProducts) === null || _h === void 0 ? void 0 : _h[0], baseStyles.heroButton))))),
2692
+ data.carouselSection && data.carouselSection.length > 0 && (React.createElement("div", { style: mergeStyles(baseStyles.carouselSection, 'carouselSection') },
2693
+ React.createElement("div", { style: baseStyles.carouselImageContainer },
2694
+ React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.carouselContainer), { transform: `translateX(-${carouselIndex * 100}%)` }) }, data.carouselSection.map((item, index) => {
2695
+ var _a;
2696
+ return (React.createElement("div", { key: item.itemId, style: baseStyles.carouselSlide }, item.url ? (React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: () => handleCarouselVideoClick(index) },
2697
+ React.createElement("video", { ref: (el) => {
2698
+ carouselVideoRefs.current[index] = el;
2699
+ }, src: item.url, style: baseStyles.carouselVideo, muted: true, loop: true, playsInline: true, controls: false }),
2700
+ carouselVideoPausedStates[index] && (React.createElement(FormatImage$1, { className: 'clc-pb-video-pause', src: videoPlayIcon, alt: 'play' })))) : ((_a = item.imgUrls) === null || _a === void 0 ? void 0 : _a[0]) ? (React.createElement("img", { src: item.imgUrls[0], alt: item.text || 'Carousel', style: baseStyles.carouselImage })) : null));
2701
+ })),
2702
+ React.createElement("button", { style: Object.assign(Object.assign({}, baseStyles.arrowButton), { left: '10px' }), onClick: handleCarouselPrev }, "\u2039"),
2703
+ React.createElement("button", { style: Object.assign(Object.assign({}, baseStyles.arrowButton), { right: '10px' }), onClick: handleCarouselNext }, "\u203A")),
2704
+ React.createElement("div", { style: mergeStyles(baseStyles.carouselInfoSection, 'carouselSection') },
2705
+ ((_j = data.carouselSection[carouselIndex]) === null || _j === void 0 ? void 0 : _j.text) && (React.createElement("div", { style: mergeStyles(baseStyles.carouselText, 'carouselSection') }, (_k = data.carouselSection[carouselIndex]) === null || _k === void 0 ? void 0 : _k.text)),
2706
+ renderCTA('carouselButton', (_o = (_m = (_l = data.carouselSection[carouselIndex]) === null || _l === void 0 ? void 0 : _l.bindProducts) === null || _m === void 0 ? void 0 : _m[0]) === null || _o === void 0 ? void 0 : _o.bindCta, (_q = (_p = data.carouselSection[carouselIndex]) === null || _p === void 0 ? void 0 : _p.bindProducts) === null || _q === void 0 ? void 0 : _q[0], baseStyles.carouselButton)))),
2707
+ data.highlightRevealSection && (React.createElement("div", { style: mergeStyles(baseStyles.highlightSection, 'highlightSection') },
2708
+ React.createElement("div", { style: baseStyles.highlightImageContainer },
2709
+ React.createElement("img", { src: data.highlightRevealSection.landingImageUrl || data.highlightRevealSection.cover, alt: data.highlightRevealSection.title, style: baseStyles.highlightImage })),
2710
+ React.createElement("div", { style: mergeStyles(baseStyles.highlightInfoSection, 'highlightSection') },
2711
+ React.createElement("div", { style: mergeStyles(baseStyles.highlightTitle, 'highlightSection') }, data.highlightRevealSection.title),
2712
+ renderCTA('highlightButton', data.highlightRevealSection.bindCta, data.highlightRevealSection, baseStyles.highlightButton)))),
2713
+ data.productGridSection && data.productGridSection.length > 0 && (React.createElement("div", { style: mergeStyles(baseStyles.productGrid, 'productGrid') }, (() => {
2714
+ // 创建一个6格的网格 (3行 x 2列),根据position放置产品
2715
+ const gridItems = [null, null, null, null, null, null];
2716
+ // 创建产品索引映射表:gridIndex -> 产品在数据数组中的索引(从1开始)
2717
+ const productIndexMap = {};
2718
+ data.productGridSection.forEach((product, idx) => {
2719
+ var _a;
2720
+ const pos = (_a = product.position) === null || _a === void 0 ? void 0 : _a.toLowerCase();
2721
+ let gridIndex = -1;
2722
+ if (pos === 'top_right') {
2723
+ gridIndex = 1; // 第一行右侧
2724
+ }
2725
+ else if (pos === 'top_left') {
2726
+ gridIndex = 0; // 第一行左侧
2727
+ }
2728
+ else if (pos === 'center_left') {
2729
+ gridIndex = 2; // 第二行左侧
2730
+ }
2731
+ else if (pos === 'center_right') {
2732
+ gridIndex = 3; // 第二行右侧
2733
+ }
2734
+ else if (pos === 'bottom_left') {
2735
+ gridIndex = 4; // 第三行左侧
2736
+ }
2737
+ else if (pos === 'bottom_right') {
2738
+ gridIndex = 5; // 第三行右侧
2739
+ }
2740
+ if (gridIndex >= 0) {
2741
+ gridItems[gridIndex] = product;
2742
+ // 映射:网格位置 -> 产品序号(基于数据数组的顺序,从1开始)
2743
+ productIndexMap[gridIndex] = idx + 1;
2744
+ }
2745
+ });
2746
+ return gridItems.map((product, gridIndex) => {
2747
+ // 使用产品在数据数组中的实际索引来确定 buttonKey
2748
+ const productDataIndex = productIndexMap[gridIndex];
2749
+ const buttonKey = `productButton${productDataIndex || gridIndex + 1}`;
2750
+ return (React.createElement("div", { key: (product === null || product === void 0 ? void 0 : product.itemId) || `empty-${gridIndex}`, style: baseStyles.productItem }, product ? (React.createElement(React.Fragment, null,
2751
+ React.createElement("div", { style: baseStyles.productImageContainer },
2752
+ React.createElement("img", { src: product.landingImageUrl || product.cover,
2753
+ // alt={product.title}
2754
+ style: baseStyles.productImage })),
2755
+ product.bindCta && (React.createElement("div", { style: baseStyles.productCtaContainer }, renderCTA(buttonKey, product.bindCta, product, baseStyles.productButton))))) : (
2756
+ // 空格子
2757
+ React.createElement("div", { style: { width: '100%', paddingBottom: '100%' } }))));
2758
+ });
2759
+ })())),
2760
+ data.footerSection && (React.createElement("div", { style: mergeStyles(baseStyles.footerSection, 'footerSection') },
2761
+ React.createElement("div", { style: mergeStyles(baseStyles.footerInfoSection, 'footerSection') }, renderCTA('footerButton', data.footerSection.bindCta, data.footerSection, baseStyles.footerButton)),
2762
+ React.createElement("div", { style: baseStyles.footerImageContainer },
2763
+ React.createElement("img", { src: data.footerSection.landingImageUrl || data.footerSection.cover, alt: data.footerSection.title, style: baseStyles.footerImage }))))));
2764
+ };
2765
+
1951
2766
  var index$3 = /*#__PURE__*/Object.freeze({
1952
2767
  __proto__: null,
1953
- EditorCore: EditorCore
2768
+ EditorCore: EditorCore,
2769
+ StructurePage: StructurePage
1954
2770
  });
1955
2771
 
1956
2772
  var interactionRender$h = [
@@ -3899,9 +4715,8 @@ function updateSlides() {
3899
4715
  allSlidesSize += slideSizeValue + (spaceBetween || 0);
3900
4716
  });
3901
4717
  allSlidesSize -= spaceBetween;
3902
- const offsetSize = (params.slidesOffsetBefore || 0) + (params.slidesOffsetAfter || 0);
3903
- if (allSlidesSize + offsetSize < swiperSize) {
3904
- const allSlidesOffset = (swiperSize - allSlidesSize - offsetSize) / 2;
4718
+ if (allSlidesSize < swiperSize) {
4719
+ const allSlidesOffset = (swiperSize - allSlidesSize) / 2;
3905
4720
  snapGrid.forEach((snap, snapIndex) => {
3906
4721
  snapGrid[snapIndex] = snap - allSlidesOffset;
3907
4722
  });
@@ -4005,13 +4820,6 @@ function updateSlidesOffset() {
4005
4820
  }
4006
4821
  }
4007
4822
 
4008
- const toggleSlideClasses$1 = (slideEl, condition, className) => {
4009
- if (condition && !slideEl.classList.contains(className)) {
4010
- slideEl.classList.add(className);
4011
- } else if (!condition && slideEl.classList.contains(className)) {
4012
- slideEl.classList.remove(className);
4013
- }
4014
- };
4015
4823
  function updateSlidesProgress(translate) {
4016
4824
  if (translate === void 0) {
4017
4825
  translate = this && this.translate || 0;
@@ -4027,6 +4835,11 @@ function updateSlidesProgress(translate) {
4027
4835
  if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset();
4028
4836
  let offsetCenter = -translate;
4029
4837
  if (rtl) offsetCenter = translate;
4838
+
4839
+ // Visible Slides
4840
+ slides.forEach(slideEl => {
4841
+ slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass);
4842
+ });
4030
4843
  swiper.visibleSlidesIndexes = [];
4031
4844
  swiper.visibleSlides = [];
4032
4845
  let spaceBetween = params.spaceBetween;
@@ -4050,9 +4863,11 @@ function updateSlidesProgress(translate) {
4050
4863
  if (isVisible) {
4051
4864
  swiper.visibleSlides.push(slide);
4052
4865
  swiper.visibleSlidesIndexes.push(i);
4866
+ slides[i].classList.add(params.slideVisibleClass);
4867
+ }
4868
+ if (isFullyVisible) {
4869
+ slides[i].classList.add(params.slideFullyVisibleClass);
4053
4870
  }
4054
- toggleSlideClasses$1(slide, isVisible, params.slideVisibleClass);
4055
- toggleSlideClasses$1(slide, isFullyVisible, params.slideFullyVisibleClass);
4056
4871
  slide.progress = rtl ? -slideProgress : slideProgress;
4057
4872
  slide.originalProgress = rtl ? -originalSlideProgress : originalSlideProgress;
4058
4873
  }
@@ -4121,13 +4936,6 @@ function updateProgress(translate) {
4121
4936
  swiper.emit('progress', progress);
4122
4937
  }
4123
4938
 
4124
- const toggleSlideClasses = (slideEl, condition, className) => {
4125
- if (condition && !slideEl.classList.contains(className)) {
4126
- slideEl.classList.add(className);
4127
- } else if (!condition && slideEl.classList.contains(className)) {
4128
- slideEl.classList.remove(className);
4129
- }
4130
- };
4131
4939
  function updateSlidesClasses() {
4132
4940
  const swiper = this;
4133
4941
  const {
@@ -4141,6 +4949,9 @@ function updateSlidesClasses() {
4141
4949
  const getFilteredSlide = selector => {
4142
4950
  return elementChildren(slidesEl, `.${params.slideClass}${selector}, swiper-slide${selector}`)[0];
4143
4951
  };
4952
+ slides.forEach(slideEl => {
4953
+ slideEl.classList.remove(params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
4954
+ });
4144
4955
  let activeSlide;
4145
4956
  let prevSlide;
4146
4957
  let nextSlide;
@@ -4163,25 +4974,35 @@ function updateSlidesClasses() {
4163
4974
  }
4164
4975
  }
4165
4976
  if (activeSlide) {
4166
- if (!gridEnabled) {
4977
+ // Active classes
4978
+ activeSlide.classList.add(params.slideActiveClass);
4979
+ if (gridEnabled) {
4980
+ if (nextSlide) {
4981
+ nextSlide.classList.add(params.slideNextClass);
4982
+ }
4983
+ if (prevSlide) {
4984
+ prevSlide.classList.add(params.slidePrevClass);
4985
+ }
4986
+ } else {
4167
4987
  // Next Slide
4168
4988
  nextSlide = elementNextAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
4169
4989
  if (params.loop && !nextSlide) {
4170
4990
  nextSlide = slides[0];
4171
4991
  }
4992
+ if (nextSlide) {
4993
+ nextSlide.classList.add(params.slideNextClass);
4994
+ }
4172
4995
 
4173
4996
  // Prev Slide
4174
4997
  prevSlide = elementPrevAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
4175
4998
  if (params.loop && !prevSlide === 0) {
4176
4999
  prevSlide = slides[slides.length - 1];
4177
5000
  }
5001
+ if (prevSlide) {
5002
+ prevSlide.classList.add(params.slidePrevClass);
5003
+ }
4178
5004
  }
4179
5005
  }
4180
- slides.forEach(slideEl => {
4181
- toggleSlideClasses(slideEl, slideEl === activeSlide, params.slideActiveClass);
4182
- toggleSlideClasses(slideEl, slideEl === nextSlide, params.slideNextClass);
4183
- toggleSlideClasses(slideEl, slideEl === prevSlide, params.slidePrevClass);
4184
- });
4185
5006
  swiper.emitSlidesClasses();
4186
5007
  }
4187
5008
 
@@ -4559,7 +5380,6 @@ function translateTo(translate, speed, runCallbacks, translateBounds, internal)
4559
5380
  swiper.wrapperEl.removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);
4560
5381
  swiper.onTranslateToWrapperTransitionEnd = null;
4561
5382
  delete swiper.onTranslateToWrapperTransitionEnd;
4562
- swiper.animating = false;
4563
5383
  if (runCallbacks) {
4564
5384
  swiper.emit('transitionEnd');
4565
5385
  }
@@ -4667,6 +5487,9 @@ function slideTo(index, speed, runCallbacks, internal, initial) {
4667
5487
  if (index === void 0) {
4668
5488
  index = 0;
4669
5489
  }
5490
+ if (speed === void 0) {
5491
+ speed = this.params.speed;
5492
+ }
4670
5493
  if (runCallbacks === void 0) {
4671
5494
  runCallbacks = true;
4672
5495
  }
@@ -4686,12 +5509,9 @@ function slideTo(index, speed, runCallbacks, internal, initial) {
4686
5509
  wrapperEl,
4687
5510
  enabled
4688
5511
  } = swiper;
4689
- if (!enabled && !internal && !initial || swiper.destroyed || swiper.animating && params.preventInteractionOnTransition) {
5512
+ if (swiper.animating && params.preventInteractionOnTransition || !enabled && !internal && !initial || swiper.destroyed) {
4690
5513
  return false;
4691
5514
  }
4692
- if (typeof speed === 'undefined') {
4693
- speed = swiper.params.speed;
4694
- }
4695
5515
  const skip = Math.min(swiper.params.slidesPerGroupSkip, slideIndex);
4696
5516
  let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup);
4697
5517
  if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
@@ -4818,6 +5638,9 @@ function slideToLoop(index, speed, runCallbacks, internal) {
4818
5638
  if (index === void 0) {
4819
5639
  index = 0;
4820
5640
  }
5641
+ if (speed === void 0) {
5642
+ speed = this.params.speed;
5643
+ }
4821
5644
  if (runCallbacks === void 0) {
4822
5645
  runCallbacks = true;
4823
5646
  }
@@ -4827,9 +5650,6 @@ function slideToLoop(index, speed, runCallbacks, internal) {
4827
5650
  }
4828
5651
  const swiper = this;
4829
5652
  if (swiper.destroyed) return;
4830
- if (typeof speed === 'undefined') {
4831
- speed = swiper.params.speed;
4832
- }
4833
5653
  const gridEnabled = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1;
4834
5654
  let newIndex = index;
4835
5655
  if (swiper.params.loop) {
@@ -4861,9 +5681,6 @@ function slideToLoop(index, speed, runCallbacks, internal) {
4861
5681
  if (centeredSlides) {
4862
5682
  needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2);
4863
5683
  }
4864
- if (internal && centeredSlides && swiper.params.slidesPerView !== 'auto' && !gridEnabled) {
4865
- needLoopFix = false;
4866
- }
4867
5684
  if (needLoopFix) {
4868
5685
  const direction = centeredSlides ? targetSlideIndex < swiper.activeIndex ? 'prev' : 'next' : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView ? 'next' : 'prev';
4869
5686
  swiper.loopFix({
@@ -4889,6 +5706,9 @@ function slideToLoop(index, speed, runCallbacks, internal) {
4889
5706
 
4890
5707
  /* eslint no-unused-vars: "off" */
4891
5708
  function slideNext(speed, runCallbacks, internal) {
5709
+ if (speed === void 0) {
5710
+ speed = this.params.speed;
5711
+ }
4892
5712
  if (runCallbacks === void 0) {
4893
5713
  runCallbacks = true;
4894
5714
  }
@@ -4899,9 +5719,6 @@ function slideNext(speed, runCallbacks, internal) {
4899
5719
  animating
4900
5720
  } = swiper;
4901
5721
  if (!enabled || swiper.destroyed) return swiper;
4902
- if (typeof speed === 'undefined') {
4903
- speed = swiper.params.speed;
4904
- }
4905
5722
  let perGroup = params.slidesPerGroup;
4906
5723
  if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {
4907
5724
  perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1);
@@ -4930,6 +5747,9 @@ function slideNext(speed, runCallbacks, internal) {
4930
5747
 
4931
5748
  /* eslint no-unused-vars: "off" */
4932
5749
  function slidePrev(speed, runCallbacks, internal) {
5750
+ if (speed === void 0) {
5751
+ speed = this.params.speed;
5752
+ }
4933
5753
  if (runCallbacks === void 0) {
4934
5754
  runCallbacks = true;
4935
5755
  }
@@ -4943,9 +5763,6 @@ function slidePrev(speed, runCallbacks, internal) {
4943
5763
  animating
4944
5764
  } = swiper;
4945
5765
  if (!enabled || swiper.destroyed) return swiper;
4946
- if (typeof speed === 'undefined') {
4947
- speed = swiper.params.speed;
4948
- }
4949
5766
  const isVirtual = swiper.virtual && params.virtual.enabled;
4950
5767
  if (params.loop) {
4951
5768
  if (animating && !isVirtual && params.loopPreventsSliding) return false;
@@ -4998,19 +5815,22 @@ function slidePrev(speed, runCallbacks, internal) {
4998
5815
 
4999
5816
  /* eslint no-unused-vars: "off" */
5000
5817
  function slideReset(speed, runCallbacks, internal) {
5818
+ if (speed === void 0) {
5819
+ speed = this.params.speed;
5820
+ }
5001
5821
  if (runCallbacks === void 0) {
5002
5822
  runCallbacks = true;
5003
5823
  }
5004
5824
  const swiper = this;
5005
5825
  if (swiper.destroyed) return;
5006
- if (typeof speed === 'undefined') {
5007
- speed = swiper.params.speed;
5008
- }
5009
5826
  return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);
5010
5827
  }
5011
5828
 
5012
5829
  /* eslint no-unused-vars: "off" */
5013
5830
  function slideToClosest(speed, runCallbacks, internal, threshold) {
5831
+ if (speed === void 0) {
5832
+ speed = this.params.speed;
5833
+ }
5014
5834
  if (runCallbacks === void 0) {
5015
5835
  runCallbacks = true;
5016
5836
  }
@@ -5019,9 +5839,6 @@ function slideToClosest(speed, runCallbacks, internal, threshold) {
5019
5839
  }
5020
5840
  const swiper = this;
5021
5841
  if (swiper.destroyed) return;
5022
- if (typeof speed === 'undefined') {
5023
- speed = swiper.params.speed;
5024
- }
5025
5842
  let index = swiper.activeIndex;
5026
5843
  const skip = Math.min(swiper.params.slidesPerGroupSkip, index);
5027
5844
  const snapIndex = skip + Math.floor((index - skip) / swiper.params.slidesPerGroup);
@@ -5656,7 +6473,7 @@ function onTouchMove(event) {
5656
6473
  data.startMoving = true;
5657
6474
  }
5658
6475
  }
5659
- if (data.isScrolling || e.type === 'touchmove' && data.preventTouchMoveFromPointerMove) {
6476
+ if (data.isScrolling) {
5660
6477
  data.isTouched = false;
5661
6478
  return;
5662
6479
  }
@@ -5698,10 +6515,7 @@ function onTouchMove(event) {
5698
6515
  if (swiper.animating) {
5699
6516
  const evt = new window.CustomEvent('transitionend', {
5700
6517
  bubbles: true,
5701
- cancelable: true,
5702
- detail: {
5703
- bySwiperTouchMove: true
5704
- }
6518
+ cancelable: true
5705
6519
  });
5706
6520
  swiper.wrapperEl.dispatchEvent(evt);
5707
6521
  }
@@ -6095,7 +6909,6 @@ const events = (swiper, method) => {
6095
6909
  const capture = !!params.nested;
6096
6910
  const domMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';
6097
6911
  const swiperMethod = method;
6098
- if (!el || typeof el === 'string') return;
6099
6912
 
6100
6913
  // Touch Events
6101
6914
  document[domMethod]('touchstart', swiper.onDocumentTouchStart, {
@@ -6204,8 +7017,6 @@ function setBreakpoint() {
6204
7017
  const breakpointParams = breakpointOnlyParams || swiper.originalParams;
6205
7018
  const wasMultiRow = isGridEnabled(swiper, params);
6206
7019
  const isMultiRow = isGridEnabled(swiper, breakpointParams);
6207
- const wasGrabCursor = swiper.params.grabCursor;
6208
- const isGrabCursor = breakpointParams.grabCursor;
6209
7020
  const wasEnabled = params.enabled;
6210
7021
  if (wasMultiRow && !isMultiRow) {
6211
7022
  el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`);
@@ -6217,11 +7028,6 @@ function setBreakpoint() {
6217
7028
  }
6218
7029
  swiper.emitContainerClasses();
6219
7030
  }
6220
- if (wasGrabCursor && !isGrabCursor) {
6221
- swiper.unsetGrabCursor();
6222
- } else if (!wasGrabCursor && isGrabCursor) {
6223
- swiper.setGrabCursor();
6224
- }
6225
7031
 
6226
7032
  // Toggle navigation, pagination, scrollbar
6227
7033
  ['navigation', 'pagination', 'scrollbar'].forEach(prop => {
@@ -6372,7 +7178,6 @@ function removeClasses() {
6372
7178
  el,
6373
7179
  classNames
6374
7180
  } = swiper;
6375
- if (!el || typeof el === 'string') return;
6376
7181
  el.classList.remove(...classNames);
6377
7182
  swiper.emitContainerClasses();
6378
7183
  }
@@ -7137,12 +7942,8 @@ let Swiper$1 = class Swiper {
7137
7942
  // Cleanup styles
7138
7943
  if (cleanStyles) {
7139
7944
  swiper.removeClasses();
7140
- if (el && typeof el !== 'string') {
7141
- el.removeAttribute('style');
7142
- }
7143
- if (wrapperEl) {
7144
- wrapperEl.removeAttribute('style');
7145
- }
7945
+ el.removeAttribute('style');
7946
+ wrapperEl.removeAttribute('style');
7146
7947
  if (slides && slides.length) {
7147
7948
  slides.forEach(slideEl => {
7148
7949
  slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
@@ -7158,9 +7959,7 @@ let Swiper$1 = class Swiper {
7158
7959
  swiper.off(eventName);
7159
7960
  });
7160
7961
  if (deleteInstance !== false) {
7161
- if (swiper.el && typeof swiper.el !== 'string') {
7162
- swiper.el.swiper = null;
7163
- }
7962
+ swiper.el.swiper = null;
7164
7963
  deleteProps(swiper);
7165
7964
  }
7166
7965
  swiper.destroyed = true;
@@ -7554,7 +8353,7 @@ const updateOnVirtualData = swiper => {
7554
8353
  };
7555
8354
 
7556
8355
  /**
7557
- * Swiper React 11.1.4
8356
+ * Swiper React 11.0.7
7558
8357
  * Most modern mobile touch slider and framework with hardware accelerated transitions
7559
8358
  * https://swiperjs.com
7560
8359
  *
@@ -7562,7 +8361,7 @@ const updateOnVirtualData = swiper => {
7562
8361
  *
7563
8362
  * Released under the MIT License
7564
8363
  *
7565
- * Released on: May 30, 2024
8364
+ * Released on: February 27, 2024
7566
8365
  */
7567
8366
 
7568
8367
 
@@ -8489,10 +9288,8 @@ function Navigation(_ref) {
8489
9288
  }
8490
9289
  if (el) {
8491
9290
  if (typeof el === 'string') res = [...document.querySelectorAll(el)];
8492
- if (swiper.params.uniqueNavElements && typeof el === 'string' && res && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {
9291
+ if (swiper.params.uniqueNavElements && typeof el === 'string' && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {
8493
9292
  res = swiper.el.querySelector(el);
8494
- } else if (res && res.length === 1) {
8495
- res = res[0];
8496
9293
  }
8497
9294
  }
8498
9295
  if (el && !res) return el;
@@ -8614,14 +9411,7 @@ function Navigation(_ref) {
8614
9411
  nextEl = makeElementsArray(nextEl);
8615
9412
  prevEl = makeElementsArray(prevEl);
8616
9413
  const targetEl = e.target;
8617
- let targetIsButton = prevEl.includes(targetEl) || nextEl.includes(targetEl);
8618
- if (swiper.isElement && !targetIsButton) {
8619
- const path = e.path || e.composedPath && e.composedPath();
8620
- if (path) {
8621
- targetIsButton = path.find(pathEl => nextEl.includes(pathEl) || prevEl.includes(pathEl));
8622
- }
8623
- }
8624
- if (swiper.params.navigation.hideOnClick && !targetIsButton) {
9414
+ if (swiper.params.navigation.hideOnClick && !prevEl.includes(targetEl) && !nextEl.includes(targetEl)) {
8625
9415
  if (swiper.pagination && swiper.params.pagination && swiper.params.pagination.clickable && (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) return;
8626
9416
  let isHidden;
8627
9417
  if (nextEl.length) {
@@ -9277,7 +10067,7 @@ function Scrollbar(_ref) {
9277
10067
  dragEl
9278
10068
  } = scrollbar;
9279
10069
  if (!isTouched) return;
9280
- if (e.preventDefault && e.cancelable) e.preventDefault();else e.returnValue = false;
10070
+ if (e.preventDefault) e.preventDefault();else e.returnValue = false;
9281
10071
  setDragPosition(e);
9282
10072
  wrapperEl.style.transitionDuration = '0ms';
9283
10073
  el.style.transitionDuration = '0ms';
@@ -9488,9 +10278,6 @@ function A11y(_ref) {
9488
10278
  clicked: false
9489
10279
  };
9490
10280
  let liveRegion = null;
9491
- let preventFocusHandler;
9492
- let focusTargetSlideEl;
9493
- let visibilityChangedTimestamp = new Date().getTime();
9494
10281
  function notify(message) {
9495
10282
  const notification = liveRegion;
9496
10283
  if (notification.length === 0) return;
@@ -9571,28 +10358,24 @@ function A11y(_ref) {
9571
10358
  if (swiper.pagination && swiper.pagination.el && (targetEl === swiper.pagination.el || swiper.pagination.el.contains(e.target))) {
9572
10359
  if (!e.target.matches(classesToSelector(swiper.params.pagination.bulletClass))) return;
9573
10360
  }
9574
- if (swiper.navigation && swiper.navigation.prevEl && swiper.navigation.nextEl) {
9575
- const prevEls = makeElementsArray(swiper.navigation.prevEl);
9576
- const nextEls = makeElementsArray(swiper.navigation.nextEl);
9577
- if (nextEls.includes(targetEl)) {
9578
- if (!(swiper.isEnd && !swiper.params.loop)) {
9579
- swiper.slideNext();
9580
- }
9581
- if (swiper.isEnd) {
9582
- notify(params.lastSlideMessage);
9583
- } else {
9584
- notify(params.nextSlideMessage);
9585
- }
10361
+ if (swiper.navigation && swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl) {
10362
+ if (!(swiper.isEnd && !swiper.params.loop)) {
10363
+ swiper.slideNext();
9586
10364
  }
9587
- if (prevEls.includes(targetEl)) {
9588
- if (!(swiper.isBeginning && !swiper.params.loop)) {
9589
- swiper.slidePrev();
9590
- }
9591
- if (swiper.isBeginning) {
9592
- notify(params.firstSlideMessage);
9593
- } else {
9594
- notify(params.prevSlideMessage);
9595
- }
10365
+ if (swiper.isEnd) {
10366
+ notify(params.lastSlideMessage);
10367
+ } else {
10368
+ notify(params.nextSlideMessage);
10369
+ }
10370
+ }
10371
+ if (swiper.navigation && swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl) {
10372
+ if (!(swiper.isBeginning && !swiper.params.loop)) {
10373
+ swiper.slidePrev();
10374
+ }
10375
+ if (swiper.isBeginning) {
10376
+ notify(params.firstSlideMessage);
10377
+ } else {
10378
+ notify(params.prevSlideMessage);
9596
10379
  }
9597
10380
  }
9598
10381
  if (swiper.pagination && targetEl.matches(classesToSelector(swiper.params.pagination.bulletClass))) {
@@ -9657,14 +10440,10 @@ function A11y(_ref) {
9657
10440
  addElLabel(el, message);
9658
10441
  addElControls(el, wrapperId);
9659
10442
  };
9660
- const handlePointerDown = e => {
9661
- if (focusTargetSlideEl && focusTargetSlideEl !== e.target && !focusTargetSlideEl.contains(e.target)) {
9662
- preventFocusHandler = true;
9663
- }
10443
+ const handlePointerDown = () => {
9664
10444
  swiper.a11y.clicked = true;
9665
10445
  };
9666
10446
  const handlePointerUp = () => {
9667
- preventFocusHandler = false;
9668
10447
  requestAnimationFrame(() => {
9669
10448
  requestAnimationFrame(() => {
9670
10449
  if (!swiper.destroyed) {
@@ -9673,15 +10452,10 @@ function A11y(_ref) {
9673
10452
  });
9674
10453
  });
9675
10454
  };
9676
- const onVisibilityChange = e => {
9677
- visibilityChangedTimestamp = new Date().getTime();
9678
- };
9679
10455
  const handleFocus = e => {
9680
10456
  if (swiper.a11y.clicked) return;
9681
- if (new Date().getTime() - visibilityChangedTimestamp < 100) return;
9682
10457
  const slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`);
9683
10458
  if (!slideEl || !swiper.slides.includes(slideEl)) return;
9684
- focusTargetSlideEl = slideEl;
9685
10459
  const isActive = swiper.slides.indexOf(slideEl) === swiper.activeIndex;
9686
10460
  const isVisible = swiper.params.watchSlidesProgress && swiper.visibleSlides && swiper.visibleSlides.includes(slideEl);
9687
10461
  if (isActive || isVisible) return;
@@ -9691,15 +10465,7 @@ function A11y(_ref) {
9691
10465
  } else {
9692
10466
  swiper.el.scrollTop = 0;
9693
10467
  }
9694
- requestAnimationFrame(() => {
9695
- if (preventFocusHandler) return;
9696
- if (swiper.params.loop) {
9697
- swiper.slideToLoop(parseInt(slideEl.getAttribute('data-swiper-slide-index')), 0);
9698
- } else {
9699
- swiper.slideTo(swiper.slides.indexOf(slideEl), 0);
9700
- }
9701
- preventFocusHandler = false;
9702
- });
10468
+ swiper.slideTo(swiper.slides.indexOf(slideEl), 0);
9703
10469
  };
9704
10470
  const initSlides = () => {
9705
10471
  const params = swiper.params.a11y;
@@ -9764,9 +10530,6 @@ function A11y(_ref) {
9764
10530
  }
9765
10531
 
9766
10532
  // Tab focus
9767
- const document = getDocument();
9768
- document.addEventListener('visibilitychange', onVisibilityChange);
9769
- swiper.el.addEventListener('focus', handleFocus, true);
9770
10533
  swiper.el.addEventListener('focus', handleFocus, true);
9771
10534
  swiper.el.addEventListener('pointerdown', handlePointerDown, true);
9772
10535
  swiper.el.addEventListener('pointerup', handlePointerUp, true);
@@ -9793,14 +10556,11 @@ function A11y(_ref) {
9793
10556
  el.removeEventListener('keydown', onEnterOrSpaceKey);
9794
10557
  });
9795
10558
  }
9796
- const document = getDocument();
9797
- document.removeEventListener('visibilitychange', onVisibilityChange);
10559
+
9798
10560
  // Tab focus
9799
- if (swiper.el && typeof swiper.el !== 'string') {
9800
- swiper.el.removeEventListener('focus', handleFocus, true);
9801
- swiper.el.removeEventListener('pointerdown', handlePointerDown, true);
9802
- swiper.el.removeEventListener('pointerup', handlePointerUp, true);
9803
- }
10561
+ swiper.el.removeEventListener('focus', handleFocus, true);
10562
+ swiper.el.removeEventListener('pointerdown', handlePointerDown, true);
10563
+ swiper.el.removeEventListener('pointerup', handlePointerUp, true);
9804
10564
  }
9805
10565
  on('beforeInit', () => {
9806
10566
  liveRegion = createElement('span', swiper.params.a11y.notificationClass);
@@ -9872,7 +10632,7 @@ function Autoplay(_ref) {
9872
10632
  if (!swiper || swiper.destroyed || !swiper.wrapperEl) return;
9873
10633
  if (e.target !== swiper.wrapperEl) return;
9874
10634
  swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd);
9875
- if (pausedByPointerEnter || e.detail && e.detail.bySwiperTouchMove) {
10635
+ if (pausedByPointerEnter) {
9876
10636
  return;
9877
10637
  }
9878
10638
  resume();
@@ -10043,10 +10803,8 @@ function Autoplay(_ref) {
10043
10803
  }
10044
10804
  };
10045
10805
  const detachMouseEvents = () => {
10046
- if (swiper.el && typeof swiper.el !== 'string') {
10047
- swiper.el.removeEventListener('pointerenter', onPointerEnter);
10048
- swiper.el.removeEventListener('pointerleave', onPointerLeave);
10049
- }
10806
+ swiper.el.removeEventListener('pointerenter', onPointerEnter);
10807
+ swiper.el.removeEventListener('pointerleave', onPointerLeave);
10050
10808
  };
10051
10809
  const attachDocumentEvents = () => {
10052
10810
  const document = getDocument();
@@ -10384,49 +11142,6 @@ const Scroll = ({ children, isPadding = true, style, enableSlideActive = false }
10384
11142
  };
10385
11143
  var Scroll$1 = React.memo(Scroll);
10386
11144
 
10387
- const FormatImage = React.forwardRef((props, ref) => {
10388
- const { src, onLoad, style, className, loading, alt = 'image' } = props;
10389
- const [imgSrc, setImgSrc] = React.useState(src);
10390
- const imgRef = React.useRef(null);
10391
- const [visible, setVisible] = React.useState(false);
10392
- React.useImperativeHandle(ref, () => ({
10393
- setSrc: (v) => {
10394
- if (v)
10395
- setImgSrc(v);
10396
- }
10397
- }));
10398
- React.useEffect(() => {
10399
- if (src)
10400
- setImgSrc(src);
10401
- }, [src]);
10402
- React.useEffect(() => {
10403
- const onShow = () => {
10404
- if (src && !visible && imgRef.current) {
10405
- imgRef.current.src = '';
10406
- imgRef.current.src = src;
10407
- }
10408
- };
10409
- SXP_EVENT_BUS.on(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
10410
- return () => {
10411
- SXP_EVENT_BUS.off(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
10412
- };
10413
- }, [src, visible]);
10414
- return (React.createElement(React.Fragment, null,
10415
- !visible && !imgSrc && React.createElement("div", { style: { width: '100%', height: '100%', zIndex: 1, backgroundColor: '#fff' } }),
10416
- (imgSrc === null || imgSrc === void 0 ? void 0 : imgSrc.includes('.avif')) ? (React.createElement("picture", null,
10417
- React.createElement("source", { type: 'image/avif', srcSet: imgSrc }),
10418
- React.createElement("source", { type: 'image/webp', srcSet: `${imgSrc}?imageMogr2/format/webp` }),
10419
- React.createElement("source", { type: 'image/jpeg', srcSet: `${imgSrc}?imageMogr2/format/jpg` }),
10420
- React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
10421
- setVisible(true);
10422
- onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
10423
- }, alt: alt }))) : (React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
10424
- setVisible(true);
10425
- onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
10426
- }, alt: alt }))));
10427
- });
10428
- var FormatImage$1 = React.memo(FormatImage);
10429
-
10430
11145
  const CommodityGroup = ({ products, data, defImg, style, onCLick, popupDetailData, check }) => {
10431
11146
  var _a;
10432
11147
  const { productView } = useEventReport();
@@ -10516,13 +11231,13 @@ function useVisibleHeight() {
10516
11231
  styleElement.id = 'onetrust-pc-sdk';
10517
11232
  styleElement.setAttribute('type', 'text/css');
10518
11233
  document.head.appendChild(styleElement);
10519
- const css = `
10520
- #onetrust-pc-sdk {
10521
- height: ${finalHeight}px !important;
10522
- }
10523
- #onetrust-pc-sdk #ot-pc-content{
10524
- bottom: ${b}px !important;
10525
- }
11234
+ const css = `
11235
+ #onetrust-pc-sdk {
11236
+ height: ${finalHeight}px !important;
11237
+ }
11238
+ #onetrust-pc-sdk #ot-pc-content{
11239
+ bottom: ${b}px !important;
11240
+ }
10526
11241
  `;
10527
11242
  styleElement.textContent = css;
10528
11243
  }
@@ -11069,10 +11784,10 @@ const CommodityDetail$1 = (_a) => {
11069
11784
  __html: setFontForText((_c = product === null || product === void 0 ? void 0 : product.taxInfo) !== null && _c !== void 0 ? _c : '税费', commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.taxInfo)
11070
11785
  } }),
11071
11786
  React.createElement("div", { hidden: !!product && (!(product === null || product === void 0 ? void 0 : product.info) || (product === null || product === void 0 ? void 0 : product.info) === '') },
11072
- React.createElement(ExpandableText$1, { foldText: tipText === null || tipText === void 0 ? void 0 : tipText.foldText, unfoldText: tipText === null || tipText === void 0 ? void 0 : tipText.unfoldText, onClick: () => setShowModal(true), isPost: isPost, text: (_d = product === null || product === void 0 ? void 0 : product.info) !== null && _d !== void 0 ? _d : `The design inspiration of Tiffany Lock series comes from the power of connection and inclusiveness, and the
11073
- bold and avant-garde visual design interprets the emotional bond connecting my heart. The Tiffany Lock
11074
- collection is unisex and is inspired by the padlock pattern found in the Tiffany Antique Collection. This
11075
- necklace features a stylish and eye-catching oval clasp chain decorated with a lock pattern. Crafted from
11787
+ React.createElement(ExpandableText$1, { foldText: tipText === null || tipText === void 0 ? void 0 : tipText.foldText, unfoldText: tipText === null || tipText === void 0 ? void 0 : tipText.unfoldText, onClick: () => setShowModal(true), isPost: isPost, text: (_d = product === null || product === void 0 ? void 0 : product.info) !== null && _d !== void 0 ? _d : `The design inspiration of Tiffany Lock series comes from the power of connection and inclusiveness, and the
11788
+ bold and avant-garde visual design interprets the emotional bond connecting my heart. The Tiffany Lock
11789
+ collection is unisex and is inspired by the padlock pattern found in the Tiffany Antique Collection. This
11790
+ necklace features a stylish and eye-catching oval clasp chain decorated with a lock pattern. Crafted from
11076
11791
  18-karat gold, this necklace is embellished with hand-set diamonds.`, maxStr: 79, className: 'pb-commondity-content-info', style: commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.info }))));
11077
11792
  };
11078
11793
  const renderBtn = () => {
@@ -12071,7 +12786,7 @@ const CommodityDetailDiroNew$1 = (_a) => {
12071
12786
  const productInfoText = ({ isPost }) => {
12072
12787
  return (React.createElement("div", { hidden: !!product && (!(product === null || product === void 0 ? void 0 : product.info) || (product === null || product === void 0 ? void 0 : product.info) === '') },
12073
12788
  React.createElement(ExpandableText$1, { isPost: isPost, onClick: () => setShowModal(true), className: 'pb-commondityDiroNew-info', style: commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.info, foldText: tipText === null || tipText === void 0 ? void 0 : tipText.foldText, unfoldText: tipText === null || tipText === void 0 ? void 0 : tipText.unfoldText, text: (product === null || product === void 0 ? void 0 : product.info) ||
12074
- `Unveiled at the Spring-Summer 2023 fashion show, the Dior Toujours bag is distinguished by a casual and practical design. Crafted in black calfskin with Macrocannage topstitching, it showcases a spacious interior compartment with a matching pouch to organize essentials. Its leather strap closure keeps items secure while the D of the CD Lock closure twists to adjust the sides and enhance the bag's silhouette. The leather handles can be adjusted using the small notches in order to be able to carry the large bag by hand or wear it over the shoulder. CD Lock and strap closures D.I.O.R. charms Removable interior pouch Adjustable leather handles Dust bag included
12789
+ `Unveiled at the Spring-Summer 2023 fashion show, the Dior Toujours bag is distinguished by a casual and practical design. Crafted in black calfskin with Macrocannage topstitching, it showcases a spacious interior compartment with a matching pouch to organize essentials. Its leather strap closure keeps items secure while the D of the CD Lock closure twists to adjust the sides and enhance the bag's silhouette. The leather handles can be adjusted using the small notches in order to be able to carry the large bag by hand or wear it over the shoulder. CD Lock and strap closures D.I.O.R. charms Removable interior pouch Adjustable leather handles Dust bag included
12075
12790
  Made in Italy` })));
12076
12791
  };
12077
12792
  const getStyle = React.useCallback((style) => {
@@ -18253,10 +18968,10 @@ const MultiPosts$1 = (_a) => {
18253
18968
  const traceInfo = ((_b = recData === null || recData === void 0 ? void 0 : recData.video) === null || _b === void 0 ? void 0 : _b.traceInfo) || ((_c = recData === null || recData === void 0 ? void 0 : recData.product) === null || _c === void 0 ? void 0 : _c.traceInfo) || '';
18254
18969
  const getPropsVal = React.useCallback((index, str) => {
18255
18970
  try {
18256
- return new Function('props', 'str', `if (str) {
18257
- return props?.button${index + 1}${str}
18258
- } else {
18259
- return props?.button${index + 1}
18971
+ return new Function('props', 'str', `if (str) {
18972
+ return props?.button${index + 1}${str}
18973
+ } else {
18974
+ return props?.button${index + 1}
18260
18975
  }`)(props, str);
18261
18976
  }
18262
18977
  catch (_a) { }
@@ -20139,10 +20854,16 @@ const SxpPageRender = ({ globalConfig, descStyle, containerHeight, containerWidt
20139
20854
  React.createElement(Swiper, { style: {
20140
20855
  marginTop: tagHeight
20141
20856
  }, ref: swiperRef, onSlideChange: () => {
20142
- swiperRef.current.swiper.allowTouchMove = false;
20143
- setTimeout(() => {
20144
- swiperRef.current.swiper.allowTouchMove = true;
20145
- }, 500);
20857
+ var _a;
20858
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
20859
+ swiperRef.current.swiper.allowTouchMove = false;
20860
+ setTimeout(() => {
20861
+ var _a;
20862
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
20863
+ swiperRef.current.swiper.allowTouchMove = true;
20864
+ }
20865
+ }, 500);
20866
+ }
20146
20867
  }, onActiveIndexChange: (swiper) => {
20147
20868
  var _a, _b;
20148
20869
  setActiveIndex(swiper.activeIndex);
@@ -21035,10 +21756,16 @@ const DiyStoryPreview = React.forwardRef(({ data = [], globalConfig, tipText, nu
21035
21756
  // className={style['clc-sxp-container']}
21036
21757
  style: { height: containerHeight, position: 'relative', pointerEvents } },
21037
21758
  React.createElement(Swiper, { ref: swiperRef, allowTouchMove: pointerEvents !== 'none', onSlideChange: () => {
21038
- swiperRef.current.swiper.allowTouchMove = false;
21039
- setTimeout(() => {
21040
- swiperRef.current.swiper.allowTouchMove = true;
21041
- }, 500);
21759
+ var _a;
21760
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
21761
+ swiperRef.current.swiper.allowTouchMove = false;
21762
+ setTimeout(() => {
21763
+ var _a;
21764
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
21765
+ swiperRef.current.swiper.allowTouchMove = true;
21766
+ }
21767
+ }, 500);
21768
+ }
21042
21769
  }, onActiveIndexChange: (swiper) => {
21043
21770
  setCurIndex(swiper === null || swiper === void 0 ? void 0 : swiper.activeIndex);
21044
21771
  onActiveChange === null || onActiveChange === void 0 ? void 0 : onActiveChange(swiper.activeIndex);
@@ -21194,6 +21921,7 @@ exports.DiyPortalPreview = index$2;
21194
21921
  exports.DiyStoryPreview = index$1;
21195
21922
  exports.EditorDataProvider = EditorDataProvider;
21196
21923
  exports.Modal = Modal$1;
21924
+ exports.StructurePage = StructurePage;
21197
21925
  exports.SxpDataSourceProvider = SxpDataSourceProvider$1;
21198
21926
  exports.SxpPageCore = index;
21199
21927
  exports.SxpPageRender = SxpPageRender$1;