pb-sxp-ui 1.20.14 → 1.20.16

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 +959 -212
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.css +73 -72
  6. package/dist/index.js +959 -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 +959 -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 +716 -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 +718 -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/pb-ui.js CHANGED
@@ -671,6 +671,10 @@
671
671
  const [popupDetailData, setPopupDetailData] = React.useState();
672
672
  const [waterFallData, setWaterFallData] = React.useState();
673
673
  const [openHashtag, setOpenHashtag] = React.useState(isOpenHashTag);
674
+ // 将 setPopupDetailData 挂载到 window 对象,供 StructurePage 使用
675
+ if (typeof window !== 'undefined') {
676
+ window.setPopupDetailData = setPopupDetailData;
677
+ }
674
678
  const [cacheRtcList, setCacheRtcList] = React.useState([]);
675
679
  const [cacheActiveIndex, setCacheActiveIndex] = React.useState(0);
676
680
  const [isFromHashtag, setIsFromHashtag] = React.useState(false);
@@ -1130,7 +1134,7 @@
1130
1134
  query.pageNum = pageNum;
1131
1135
  result = isDiyH5
1132
1136
  ? yield (bffFetch === null || bffFetch === void 0 ? void 0 : bffFetch('v3/recommend/direct/page/view', { method: 'POST', body: query }))
1133
- : yield (bffFetch === null || bffFetch === void 0 ? void 0 : bffFetch('recommend/direct_page', { method: 'POST', body: query }));
1137
+ : yield (bffFetch === null || bffFetch === void 0 ? void 0 : bffFetch('v1/recommend/direct_page', { method: 'POST', body: query }));
1134
1138
  if (!(result === null || result === void 0 ? void 0 : result.success)) {
1135
1139
  return undefined;
1136
1140
  }
@@ -1358,6 +1362,7 @@
1358
1362
  var _a;
1359
1363
  const prop = match.substring(2, match.length - 2);
1360
1364
  try {
1365
+ // eslint-disable-next-line no-new-func
1361
1366
  let replaceValue = new Function('fix_par', 'product', `return ${prop}`)(fix_par, product === null || product === void 0 ? void 0 : product[0]);
1362
1367
  if (replaceValue) {
1363
1368
  if ((prop === null || prop === void 0 ? void 0 : prop.indexOf('currency')) !== -1 &&
@@ -1941,9 +1946,839 @@
1941
1946
  React.createElement(DataSourceProvider$1, { isSsr: isSsr, enable: enableDataSource }, children)));
1942
1947
  });
1943
1948
 
1949
+ const FormatImage = React.forwardRef((props, ref) => {
1950
+ const { src, onLoad, style, className, loading, alt = 'image' } = props;
1951
+ const [imgSrc, setImgSrc] = React.useState(src);
1952
+ const imgRef = React.useRef(null);
1953
+ const [visible, setVisible] = React.useState(false);
1954
+ React.useImperativeHandle(ref, () => ({
1955
+ setSrc: (v) => {
1956
+ if (v)
1957
+ setImgSrc(v);
1958
+ }
1959
+ }));
1960
+ React.useEffect(() => {
1961
+ if (src)
1962
+ setImgSrc(src);
1963
+ }, [src]);
1964
+ React.useEffect(() => {
1965
+ const onShow = () => {
1966
+ if (src && !visible && imgRef.current) {
1967
+ imgRef.current.src = '';
1968
+ imgRef.current.src = src;
1969
+ }
1970
+ };
1971
+ SXP_EVENT_BUS.on(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
1972
+ return () => {
1973
+ SXP_EVENT_BUS.off(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
1974
+ };
1975
+ }, [src, visible]);
1976
+ return (React.createElement(React.Fragment, null,
1977
+ !visible && !imgSrc && React.createElement("div", { style: { width: '100%', height: '100%', zIndex: 1, backgroundColor: '#fff' } }),
1978
+ (imgSrc === null || imgSrc === void 0 ? void 0 : imgSrc.includes('.avif')) ? (React.createElement("picture", null,
1979
+ React.createElement("source", { type: 'image/avif', srcSet: imgSrc }),
1980
+ React.createElement("source", { type: 'image/webp', srcSet: `${imgSrc}?imageMogr2/format/webp` }),
1981
+ React.createElement("source", { type: 'image/jpeg', srcSet: `${imgSrc}?imageMogr2/format/jpg` }),
1982
+ React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
1983
+ setVisible(true);
1984
+ onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
1985
+ }, alt: alt }))) : (React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
1986
+ setVisible(true);
1987
+ onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
1988
+ }, alt: alt }))));
1989
+ });
1990
+ var FormatImage$1 = React.memo(FormatImage);
1991
+
1992
+ // 动态导入材料库(避免循环依赖)
1993
+ const RESOLVER$3 = {};
1994
+ try {
1995
+ // 尝试动态导入材料库
1996
+ const materialsModule = require('../../materials/sxp');
1997
+ if (materialsModule && typeof materialsModule === 'object') {
1998
+ Object.values(materialsModule).forEach((v) => {
1999
+ var _a;
2000
+ if ((_a = v === null || v === void 0 ? void 0 : v.extend) === null || _a === void 0 ? void 0 : _a.type) {
2001
+ RESOLVER$3[v.extend.type] = v;
2002
+ }
2003
+ });
2004
+ // 调试信息:记录成功加载的组件数量
2005
+ if (Object.keys(RESOLVER$3).length > 0) {
2006
+ console.log('[StructurePage] Successfully loaded materials:', Object.keys(RESOLVER$3));
2007
+ }
2008
+ else {
2009
+ console.warn('[StructurePage] Materials module loaded but no valid components found');
2010
+ }
2011
+ }
2012
+ else {
2013
+ console.warn('[StructurePage] Materials module is not a valid object:', materialsModule);
2014
+ }
2015
+ }
2016
+ catch (error) {
2017
+ console.error('[StructurePage] Failed to load materials for StructurePage:', error);
2018
+ }
2019
+ // 基础样式定义
2020
+ const baseStyles = {
2021
+ container: {
2022
+ backgroundColor: '#000',
2023
+ overflowY: 'auto',
2024
+ overflowX: 'hidden',
2025
+ padding: 0,
2026
+ boxSizing: 'border-box'
2027
+ },
2028
+ section: {
2029
+ width: '100%',
2030
+ position: 'relative',
2031
+ boxSizing: 'border-box'
2032
+ },
2033
+ // Hero Section
2034
+ heroSection: {
2035
+ width: '100%',
2036
+ height: 'auto',
2037
+ position: 'relative',
2038
+ overflow: 'hidden',
2039
+ backgroundColor: '#000'
2040
+ },
2041
+ heroTopText: {
2042
+ width: '100%',
2043
+ padding: '20px',
2044
+ backgroundColor: '#fff',
2045
+ color: '#000',
2046
+ fontSize: '16px',
2047
+ fontWeight: 'bold',
2048
+ textAlign: 'center',
2049
+ boxSizing: 'border-box'
2050
+ },
2051
+ heroImageContainer: {
2052
+ width: '100%',
2053
+ position: 'relative',
2054
+ overflow: 'hidden'
2055
+ },
2056
+ heroImage: {
2057
+ width: '100%',
2058
+ height: 'auto',
2059
+ display: 'block',
2060
+ objectFit: 'cover'
2061
+ },
2062
+ heroVideo: {
2063
+ width: '100%',
2064
+ height: 'auto',
2065
+ display: 'block',
2066
+ objectFit: 'cover'
2067
+ },
2068
+ heroOverlay: {
2069
+ position: 'absolute',
2070
+ bottom: 0,
2071
+ left: 0,
2072
+ right: 0,
2073
+ padding: '40px 20px',
2074
+ background: 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 100%)',
2075
+ color: '#fff',
2076
+ display: 'flex',
2077
+ justifyContent: 'center',
2078
+ alignItems: 'center'
2079
+ },
2080
+ heroButton: {
2081
+ padding: '12px 30px',
2082
+ backgroundColor: '#fff',
2083
+ color: '#000',
2084
+ border: 'none',
2085
+ fontSize: '14px',
2086
+ fontWeight: 500,
2087
+ cursor: 'pointer',
2088
+ textTransform: 'uppercase'
2089
+ },
2090
+ // Carousel Section
2091
+ carouselSection: {
2092
+ width: '100%',
2093
+ position: 'relative'
2094
+ },
2095
+ carouselImageContainer: {
2096
+ width: '100%',
2097
+ height: 'auto',
2098
+ position: 'relative',
2099
+ overflow: 'hidden'
2100
+ },
2101
+ carouselContainer: {
2102
+ display: 'flex',
2103
+ transition: 'transform 0.5s ease-in-out',
2104
+ width: '100%'
2105
+ },
2106
+ carouselSlide: {
2107
+ minWidth: '100%',
2108
+ position: 'relative'
2109
+ },
2110
+ carouselImage: {
2111
+ width: '100%',
2112
+ height: 'auto',
2113
+ display: 'block',
2114
+ objectFit: 'cover'
2115
+ },
2116
+ carouselVideo: {
2117
+ width: '100%',
2118
+ height: 'auto',
2119
+ display: 'block',
2120
+ objectFit: 'cover'
2121
+ },
2122
+ carouselInfoSection: {
2123
+ width: '100%',
2124
+ padding: '20px',
2125
+ backgroundColor: '#000',
2126
+ color: '#fff',
2127
+ textAlign: 'center'
2128
+ },
2129
+ carouselText: {
2130
+ fontSize: '16px',
2131
+ fontWeight: 'normal',
2132
+ marginBottom: '15px',
2133
+ color: '#fff'
2134
+ },
2135
+ carouselButton: {
2136
+ padding: '10px 25px',
2137
+ backgroundColor: '#fff',
2138
+ color: '#000',
2139
+ border: '1px solid #fff',
2140
+ fontSize: '13px',
2141
+ fontWeight: 500,
2142
+ cursor: 'pointer',
2143
+ textTransform: 'uppercase'
2144
+ },
2145
+ arrowButton: {
2146
+ position: 'absolute',
2147
+ top: '50%',
2148
+ transform: 'translateY(-50%)',
2149
+ width: '40px',
2150
+ height: '40px',
2151
+ backgroundColor: 'rgba(255,255,255,0.8)',
2152
+ border: 'none',
2153
+ borderRadius: '50%',
2154
+ fontSize: '18px',
2155
+ cursor: 'pointer',
2156
+ zIndex: 10,
2157
+ display: 'flex',
2158
+ alignItems: 'center',
2159
+ justifyContent: 'center'
2160
+ },
2161
+ // Highlight Reveal Section
2162
+ highlightSection: {
2163
+ width: '100%',
2164
+ position: 'relative',
2165
+ backgroundColor: '#000'
2166
+ },
2167
+ highlightImageContainer: {
2168
+ width: '100%',
2169
+ aspectRatio: '1/1',
2170
+ position: 'relative',
2171
+ overflow: 'hidden'
2172
+ },
2173
+ highlightImage: {
2174
+ width: '100%',
2175
+ height: '100%',
2176
+ objectFit: 'cover',
2177
+ display: 'block'
2178
+ },
2179
+ highlightInfoSection: {
2180
+ width: '100%',
2181
+ padding: '20px',
2182
+ backgroundColor: '#000',
2183
+ color: '#fff',
2184
+ textAlign: 'center'
2185
+ },
2186
+ highlightTitle: {
2187
+ fontSize: '18px',
2188
+ fontWeight: 'bold',
2189
+ marginBottom: '10px',
2190
+ textAlign: 'center',
2191
+ color: '#fff'
2192
+ },
2193
+ highlightDesc: {
2194
+ fontSize: '14px',
2195
+ marginBottom: '15px',
2196
+ textAlign: 'center',
2197
+ lineHeight: '1.5',
2198
+ color: '#ccc'
2199
+ },
2200
+ highlightButton: {
2201
+ padding: '10px 25px',
2202
+ backgroundColor: 'transparent',
2203
+ color: '#fff',
2204
+ border: '1px solid #fff',
2205
+ fontSize: '13px',
2206
+ fontWeight: 500,
2207
+ cursor: 'pointer',
2208
+ textTransform: 'uppercase'
2209
+ },
2210
+ // Product Grid Section
2211
+ productGrid: {
2212
+ display: 'grid',
2213
+ gridTemplateColumns: '50% 50%',
2214
+ gridAutoRows: 'auto',
2215
+ gap: '0',
2216
+ width: '100%',
2217
+ backgroundColor: '#000',
2218
+ boxSizing: 'border-box',
2219
+ margin: 0,
2220
+ padding: 0,
2221
+ overflow: 'hidden'
2222
+ },
2223
+ productItem: {
2224
+ position: 'relative',
2225
+ backgroundColor: '#000',
2226
+ display: 'block',
2227
+ boxSizing: 'border-box',
2228
+ width: '100%',
2229
+ minWidth: 0,
2230
+ overflow: 'hidden'
2231
+ },
2232
+ productImageContainer: {
2233
+ width: '100%',
2234
+ paddingBottom: '100%',
2235
+ position: 'relative',
2236
+ overflow: 'hidden'
2237
+ },
2238
+ productImage: {
2239
+ position: 'absolute',
2240
+ top: 0,
2241
+ left: 0,
2242
+ width: '100%',
2243
+ height: '100%',
2244
+ objectFit: 'cover',
2245
+ display: 'block'
2246
+ },
2247
+ productCtaContainer: {
2248
+ width: '100%',
2249
+ padding: '15px',
2250
+ backgroundColor: '#000',
2251
+ textAlign: 'center',
2252
+ boxSizing: 'border-box'
2253
+ },
2254
+ productText: {
2255
+ width: '100%',
2256
+ padding: '15px',
2257
+ backgroundColor: '#000',
2258
+ color: '#fff',
2259
+ textAlign: 'center',
2260
+ fontSize: '14px',
2261
+ fontWeight: 'normal',
2262
+ boxSizing: 'border-box'
2263
+ },
2264
+ productButton: {
2265
+ padding: '8px 20px',
2266
+ backgroundColor: 'transparent',
2267
+ color: '#fff',
2268
+ border: '1px solid #fff',
2269
+ fontSize: '12px',
2270
+ fontWeight: 500,
2271
+ cursor: 'pointer',
2272
+ textTransform: 'uppercase',
2273
+ whiteSpace: 'nowrap'
2274
+ },
2275
+ // Footer Section
2276
+ footerSection: {
2277
+ width: '100%',
2278
+ position: 'relative',
2279
+ backgroundColor: '#000'
2280
+ },
2281
+ footerInfoSection: {
2282
+ width: '100%',
2283
+ padding: '20px',
2284
+ backgroundColor: '#000',
2285
+ color: '#fff',
2286
+ textAlign: 'center'
2287
+ },
2288
+ footerText: {
2289
+ fontSize: '18px',
2290
+ fontWeight: 'normal',
2291
+ marginBottom: '15px',
2292
+ lineHeight: '1.4',
2293
+ color: '#fff'
2294
+ },
2295
+ footerButton: {
2296
+ padding: '10px 25px',
2297
+ backgroundColor: 'transparent',
2298
+ color: '#fff',
2299
+ border: '1px solid #fff',
2300
+ fontSize: '13px',
2301
+ fontWeight: 500,
2302
+ cursor: 'pointer',
2303
+ textTransform: 'uppercase',
2304
+ marginBottom: '20px',
2305
+ display: 'inline-block'
2306
+ },
2307
+ footerImageContainer: {
2308
+ width: '100%',
2309
+ aspectRatio: '1/1',
2310
+ overflow: 'hidden'
2311
+ },
2312
+ footerImage: {
2313
+ width: '100%',
2314
+ height: '100%',
2315
+ objectFit: 'cover',
2316
+ display: 'block'
2317
+ }
2318
+ };
2319
+ const StructurePage = (_a) => {
2320
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
2321
+ 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"]);
2322
+ const [data, setData] = React.useState(null);
2323
+ const [loading, setLoading] = React.useState(true);
2324
+ const [error, setError] = React.useState(null);
2325
+ const [carouselIndex, setCarouselIndex] = React.useState(0);
2326
+ const heroVideoRef = React.useRef(null);
2327
+ const carouselVideoRefs = React.useRef([]);
2328
+ // 视频暂停状态管理
2329
+ const [isHeroVideoPaused, setIsHeroVideoPaused] = React.useState(false);
2330
+ const [carouselVideoPausedStates, setCarouselVideoPausedStates] = React.useState([]);
2331
+ // 从 schema 中获取 multiCTAConfig(优先使用 props 传入的)
2332
+ const { schema } = useEditor();
2333
+ const multiCTAConfig = React.useMemo(() => {
2334
+ var _a;
2335
+ return propMultiCTAConfig || ((_a = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _a === void 0 ? void 0 : _a.multiCTAConfig) || {};
2336
+ }, [propMultiCTAConfig, (_b = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _b === void 0 ? void 0 : _b.multiCTAConfig]);
2337
+ // 默认播放图标 URL(直接使用 CDN 地址作为后备)
2338
+ const DEFAULT_PAUSE_ICON = 'https://sxph5-uat.chatlabs.net/pb_static/06f28a2025c74c1cb49be6767316d827.png';
2339
+ // 获取视频播放图标
2340
+ const videoPlayIcon = React.useMemo(() => {
2341
+ var _a, _b;
2342
+ // 优先使用 props 传入的
2343
+ if (propVideoPlayIcon)
2344
+ return propVideoPlayIcon;
2345
+ // 然后使用 schema 配置的
2346
+ 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;
2347
+ if (configIcon) {
2348
+ // 如果是完整 URL,直接使用
2349
+ if (configIcon.startsWith('http://') || configIcon.startsWith('https://')) {
2350
+ return configIcon;
2351
+ }
2352
+ // 如果是相对路径,拼接当前域名
2353
+ if (configIcon.startsWith('/')) {
2354
+ return `${window.location.origin}${configIcon}`;
2355
+ }
2356
+ return configIcon;
2357
+ }
2358
+ // 最后使用默认图标
2359
+ return DEFAULT_PAUSE_ICON;
2360
+ }, [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]);
2361
+ // 处理 CTA 点击
2362
+ const handleCtaClick = React.useCallback((link, interaction, productData, ctaData) => {
2363
+ // 如果配置了交互设置,优先使用交互设置
2364
+ if (interaction) {
2365
+ const { linkType, popupType, popupAni } = interaction;
2366
+ if (linkType === 'popup' && popupType) {
2367
+ // 设置弹窗要显示的产品数据
2368
+ if (productData && typeof window !== 'undefined' && window.setPopupDetailData) {
2369
+ // 构造与原有系统一致的数据结构
2370
+ const popupData = {
2371
+ video: {
2372
+ bindProduct: productData,
2373
+ bindProducts: [productData],
2374
+ bindCta: ctaData
2375
+ }
2376
+ };
2377
+ window.setPopupDetailData(popupData);
2378
+ }
2379
+ // 打开弹窗 - 使用与现有系统一致的方式
2380
+ if (typeof window !== 'undefined' && window.sxpPopup) {
2381
+ // 如果有动画配置,传递动画参数;否则只传弹窗 ID
2382
+ if (popupAni && popupAni.name) {
2383
+ window.sxpPopup(popupType, popupAni);
2384
+ }
2385
+ else {
2386
+ window.sxpPopup(popupType);
2387
+ }
2388
+ }
2389
+ return;
2390
+ }
2391
+ }
2392
+ // 默认行为:打开外部链接
2393
+ if (link) {
2394
+ window.open(link, '_blank');
2395
+ }
2396
+ }, []);
2397
+ // 合并基础样式和编辑器配置的样式
2398
+ const mergeStyles = React.useCallback((baseStyle, configKey) => {
2399
+ if (!editorMode || !multiCTAConfig[configKey]) {
2400
+ return baseStyle;
2401
+ }
2402
+ const config = multiCTAConfig[configKey];
2403
+ // 定义允许的样式属性列表
2404
+ const styleKeys = [
2405
+ 'fontSize', 'color', 'textAlign', 'fontWeight',
2406
+ 'backgroundColor', 'padding', 'margin', 'borderRadius',
2407
+ 'showBorder', 'borderWidth', 'borderColor',
2408
+ 'buttonBackgroundColor', 'buttonTextColor', 'buttonWidth', 'buttonHeight'
2409
+ ];
2410
+ // 只处理样式相关的属性,忽略 interaction 等非样式属性
2411
+ const styleConfig = Object.keys(config)
2412
+ .filter(key => styleKeys.includes(key))
2413
+ .reduce((obj, key) => {
2414
+ obj[key] = config[key];
2415
+ return obj;
2416
+ }, {});
2417
+ // 如果配置中没有任何样式字段(只有 interaction),直接返回基础样式
2418
+ if (Object.keys(styleConfig).length === 0) {
2419
+ return baseStyle;
2420
+ }
2421
+ const customStyle = {};
2422
+ // 应用配置中的样式
2423
+ if (styleConfig.fontSize && typeof styleConfig.fontSize === 'number') {
2424
+ customStyle.fontSize = `${styleConfig.fontSize}px`;
2425
+ }
2426
+ if (styleConfig.color && typeof styleConfig.color === 'string') {
2427
+ customStyle.color = styleConfig.color;
2428
+ }
2429
+ if (styleConfig.textAlign && typeof styleConfig.textAlign === 'string') {
2430
+ customStyle.textAlign = styleConfig.textAlign;
2431
+ }
2432
+ if (styleConfig.fontWeight && typeof styleConfig.fontWeight === 'number') {
2433
+ customStyle.fontWeight = styleConfig.fontWeight;
2434
+ }
2435
+ if (styleConfig.backgroundColor && typeof styleConfig.backgroundColor === 'string') {
2436
+ customStyle.backgroundColor = styleConfig.backgroundColor;
2437
+ }
2438
+ if (styleConfig.padding && typeof styleConfig.padding === 'string') {
2439
+ customStyle.padding = styleConfig.padding;
2440
+ }
2441
+ if (styleConfig.margin && typeof styleConfig.margin === 'string') {
2442
+ customStyle.margin = styleConfig.margin;
2443
+ }
2444
+ if (styleConfig.borderRadius && typeof styleConfig.borderRadius === 'number') {
2445
+ customStyle.borderRadius = `${styleConfig.borderRadius}px`;
2446
+ }
2447
+ if (styleConfig.showBorder && styleConfig.borderWidth && typeof styleConfig.borderWidth === 'number') {
2448
+ customStyle.border = `${styleConfig.borderWidth}px solid ${styleConfig.borderColor || '#d9d9d9'}`;
2449
+ }
2450
+ // 按钮特殊样式
2451
+ if (styleConfig.buttonBackgroundColor && typeof styleConfig.buttonBackgroundColor === 'string') {
2452
+ customStyle.backgroundColor = styleConfig.buttonBackgroundColor;
2453
+ }
2454
+ if (styleConfig.buttonTextColor && typeof styleConfig.buttonTextColor === 'string') {
2455
+ customStyle.color = styleConfig.buttonTextColor;
2456
+ }
2457
+ if (styleConfig.buttonWidth && typeof styleConfig.buttonWidth === 'number') {
2458
+ customStyle.width = `${styleConfig.buttonWidth}px`;
2459
+ }
2460
+ if (styleConfig.buttonHeight && typeof styleConfig.buttonHeight === 'number') {
2461
+ customStyle.height = `${styleConfig.buttonHeight}px`;
2462
+ }
2463
+ return Object.assign(Object.assign({}, baseStyle), customStyle);
2464
+ }, [editorMode, multiCTAConfig]);
2465
+ // 渲染 CTA 按钮或模版组件
2466
+ const renderCTA = React.useCallback((buttonKey, ctaData, productData, fallbackStyle) => {
2467
+ var _a, _b, _c;
2468
+ if (!ctaData) {
2469
+ return null;
2470
+ }
2471
+ const config = multiCTAConfig[buttonKey];
2472
+ const templateType = config === null || config === void 0 ? void 0 : config.templateType;
2473
+ const interaction = config === null || config === void 0 ? void 0 : config.interaction;
2474
+ // 如果配置了模版类型,渲染对应的模版组件
2475
+ if (editorMode && templateType && RESOLVER$3[templateType]) {
2476
+ const TemplateComponent = RESOLVER$3[templateType];
2477
+ const templateExtend = TemplateComponent === null || TemplateComponent === void 0 ? void 0 : TemplateComponent.extend;
2478
+ // 严格检查组件是否有效
2479
+ if (templateExtend && typeof TemplateComponent === 'function') {
2480
+ try {
2481
+ // 准备模版组件的 props
2482
+ 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);
2483
+ // 渲染模版组件
2484
+ return React.createElement(TemplateComponent, templateProps);
2485
+ }
2486
+ catch (error) {
2487
+ console.error(`[StructurePage] Failed to render template component ${templateType}:`, error);
2488
+ // 降级到默认按钮
2489
+ }
2490
+ }
2491
+ }
2492
+ // 默认渲染按钮
2493
+ 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));
2494
+ }, [multiCTAConfig, editorMode, handleCtaClick, mergeStyles, rest]);
2495
+ // 获取数据 - 只在组件挂载时执行一次
2496
+ React.useEffect(() => {
2497
+ // 重要:在 PB 编辑器模式下,propMultiCTAConfig 只是样式配置,不是数据源
2498
+ // 只有在 CMS 模式 (isCmsMode=false) 且 propMultiCTAConfig 包含实际数据时才跳过 API 调用
2499
+ // 判断是否包含实际数据:检查是否有 heroSection, carouselSection 等数据字段
2500
+ const hasActualData = propMultiCTAConfig && (propMultiCTAConfig.heroSection ||
2501
+ propMultiCTAConfig.carouselSection ||
2502
+ propMultiCTAConfig.highlightRevealSection ||
2503
+ propMultiCTAConfig.productGridSection ||
2504
+ propMultiCTAConfig.footerSection);
2505
+ if (editorMode && hasActualData && !isCmsMode) {
2506
+ setLoading(false);
2507
+ setError(null);
2508
+ // 使用传入的 multiCTAConfig 作为数据源
2509
+ setData(propMultiCTAConfig);
2510
+ return;
2511
+ }
2512
+ // 如果已经有数据了,且在编辑器模式下,不要重新请求
2513
+ if (editorMode && data && !isCmsMode) {
2514
+ return;
2515
+ }
2516
+ setLoading(true);
2517
+ setError(null);
2518
+ // 根据模式决定使用哪个接口
2519
+ let finalApiUrl = apiUrl;
2520
+ let bodyToSend = {};
2521
+ if (isCmsMode) {
2522
+ // CMS 模式:使用 /api/console/ad/multiCta/rec/detail 接口
2523
+ if (!storyId) {
2524
+ console.error('[StructurePage CMS Mode] storyId is required but not provided');
2525
+ setError('storyId is required in CMS mode');
2526
+ setLoading(false);
2527
+ return;
2528
+ }
2529
+ // 构建 CMS 接口的 URL 和请求体
2530
+ // apiUrl 应该是域名(如 http://localhost:8001),然后拼接 /api/console/ad/multiCta/rec/detail
2531
+ finalApiUrl = `${apiUrl}/api/console/ad/multiCta/rec/detail`;
2532
+ bodyToSend = { storyId };
2533
+ }
2534
+ else {
2535
+ // 普通模式:使用原有的 /api/v1/recommend/list 接口
2536
+ const defaultBody = {
2537
+ maxSize: 20,
2538
+ defaultSize: 10,
2539
+ type: 'story'
2540
+ };
2541
+ bodyToSend = requestBody ? Object.assign(Object.assign({}, defaultBody), requestBody) : defaultBody;
2542
+ }
2543
+ // 构建请求头
2544
+ const headers = {
2545
+ 'Content-Type': 'application/json'
2546
+ };
2547
+ if (isCmsMode) {
2548
+ // CMS 模式:使用自定义 headers(如果有传入)
2549
+ if (customHeaders) {
2550
+ Object.assign(headers, customHeaders);
2551
+ }
2552
+ }
2553
+ else {
2554
+ // 普通模式:从 requestBody 或 bodyToSend 中提取 BFF headers
2555
+ if (bodyToSend['x-app-id']) {
2556
+ headers['x-app-id'] = bodyToSend['x-app-id'];
2557
+ delete bodyToSend['x-app-id'];
2558
+ }
2559
+ if (bodyToSend['x-user-id']) {
2560
+ headers['x-user-id'] = bodyToSend['x-user-id'];
2561
+ delete bodyToSend['x-user-id'];
2562
+ }
2563
+ if (bodyToSend['tenant-id']) {
2564
+ headers['tenant-id'] = bodyToSend['tenant-id'];
2565
+ delete bodyToSend['tenant-id'];
2566
+ }
2567
+ }
2568
+ fetch(finalApiUrl, {
2569
+ method: 'POST',
2570
+ headers,
2571
+ body: JSON.stringify(bodyToSend),
2572
+ credentials: 'include'
2573
+ })
2574
+ .then((res) => {
2575
+ if (!res.ok) {
2576
+ throw new Error(`HTTP error! status: ${res.status}`);
2577
+ }
2578
+ return res.json();
2579
+ })
2580
+ .then((result) => {
2581
+ var _a, _b, _c, _d;
2582
+ if (result.code === '0' || result.code === '00000') {
2583
+ // 判断数据结构:CMS 模式和普通模式可能不同
2584
+ let multiCtaData = null;
2585
+ if (isCmsMode) {
2586
+ // CMS 模式:data.multiCta
2587
+ multiCtaData = (_a = result.data) === null || _a === void 0 ? void 0 : _a.multiCta;
2588
+ }
2589
+ else {
2590
+ // 普通模式:data.recList[0].multiCta
2591
+ 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;
2592
+ }
2593
+ if (multiCtaData) {
2594
+ setData(multiCtaData);
2595
+ }
2596
+ else {
2597
+ console.error('[StructurePage] No multiCta data found in response:', result);
2598
+ setError(result.message || 'No multiCta data found');
2599
+ }
2600
+ }
2601
+ else {
2602
+ setError(result.message || 'Failed to load data');
2603
+ }
2604
+ setLoading(false);
2605
+ })
2606
+ .catch((err) => {
2607
+ console.error('[StructurePage] Failed to fetch data:', {
2608
+ error: err,
2609
+ message: err.message,
2610
+ url: finalApiUrl,
2611
+ body: bodyToSend,
2612
+ isCmsMode,
2613
+ storyId
2614
+ });
2615
+ setError(err.message || 'Network error');
2616
+ setLoading(false);
2617
+ });
2618
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2619
+ }, [apiUrl, isCmsMode, storyId, customHeaders]);
2620
+ // 注意:移除了 editorMode 和 propMultiCTAConfig 依赖,因为:
2621
+ // 1. editorMode 和 propMultiCTAConfig 在编辑器中频繁变化
2622
+ // 2. propMultiCTAConfig 只是样式配置,不是数据源
2623
+ // 3. 数据获取只应该在组件挂载时执行一次(除非 apiUrl/storyId 等关键参数变化)
2624
+ // Hero Section 视频自动播放
2625
+ React.useEffect(() => {
2626
+ var _a;
2627
+ if (heroVideoRef.current && ((_a = data === null || data === void 0 ? void 0 : data.heroSection) === null || _a === void 0 ? void 0 : _a.url)) {
2628
+ heroVideoRef.current.play().catch((err) => console.log('Video autoplay failed:', err));
2629
+ setIsHeroVideoPaused(false);
2630
+ }
2631
+ }, [data === null || data === void 0 ? void 0 : data.heroSection]);
2632
+ // 初始化 carousel 视频暂停状态
2633
+ React.useEffect(() => {
2634
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2635
+ // carousel 视频默认不自动播放,所以初始状态应该是暂停(true)
2636
+ setCarouselVideoPausedStates(new Array(data.carouselSection.length).fill(true));
2637
+ }
2638
+ }, [data === null || data === void 0 ? void 0 : data.carouselSection]);
2639
+ // Hero 视频点击处理
2640
+ const handleHeroVideoClick = React.useCallback(() => {
2641
+ if (heroVideoRef.current) {
2642
+ if (heroVideoRef.current.paused) {
2643
+ heroVideoRef.current.play();
2644
+ setIsHeroVideoPaused(false);
2645
+ }
2646
+ else {
2647
+ heroVideoRef.current.pause();
2648
+ setIsHeroVideoPaused(true);
2649
+ }
2650
+ }
2651
+ }, []);
2652
+ // Carousel 视频点击处理
2653
+ const handleCarouselVideoClick = React.useCallback((index) => {
2654
+ const videoRef = carouselVideoRefs.current[index];
2655
+ if (videoRef) {
2656
+ if (videoRef.paused) {
2657
+ videoRef.play();
2658
+ setCarouselVideoPausedStates(prev => {
2659
+ const newStates = [...prev];
2660
+ newStates[index] = false;
2661
+ return newStates;
2662
+ });
2663
+ }
2664
+ else {
2665
+ videoRef.pause();
2666
+ setCarouselVideoPausedStates(prev => {
2667
+ const newStates = [...prev];
2668
+ newStates[index] = true;
2669
+ return newStates;
2670
+ });
2671
+ }
2672
+ }
2673
+ }, []);
2674
+ // Carousel 导航
2675
+ const handleCarouselPrev = () => {
2676
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2677
+ setCarouselIndex((prev) => (prev === 0 ? data.carouselSection.length - 1 : prev - 1));
2678
+ }
2679
+ };
2680
+ const handleCarouselNext = () => {
2681
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2682
+ setCarouselIndex((prev) => (prev === data.carouselSection.length - 1 ? 0 : prev + 1));
2683
+ }
2684
+ };
2685
+ if (loading) {
2686
+ 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..."));
2687
+ }
2688
+ if (error) {
2689
+ 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' }) },
2690
+ React.createElement("div", { style: { fontSize: '18px', marginBottom: '10px' } }, "\u26A0\uFE0F Error"),
2691
+ React.createElement("div", { style: { fontSize: '14px', opacity: 0.8 } }, error)));
2692
+ }
2693
+ if (!data) {
2694
+ 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"));
2695
+ }
2696
+ return (React.createElement("div", { className: className, style: Object.assign(Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth }), containerStyle) },
2697
+ data.heroSection && (React.createElement("div", { style: baseStyles.heroSection },
2698
+ data.heroSection.text && (React.createElement("div", { style: mergeStyles(baseStyles.heroTopText, 'heroTopText') }, data.heroSection.text)),
2699
+ React.createElement("div", { style: baseStyles.heroImageContainer },
2700
+ data.heroSection.url ? (React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: handleHeroVideoClick },
2701
+ React.createElement("video", { ref: heroVideoRef, src: data.heroSection.url, style: baseStyles.heroVideo, autoPlay: true, muted: true, loop: true, playsInline: true, controls: false }),
2702
+ 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,
2703
+ 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))))),
2704
+ data.carouselSection && data.carouselSection.length > 0 && (React.createElement("div", { style: mergeStyles(baseStyles.carouselSection, 'carouselSection') },
2705
+ React.createElement("div", { style: baseStyles.carouselImageContainer },
2706
+ React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.carouselContainer), { transform: `translateX(-${carouselIndex * 100}%)` }) }, data.carouselSection.map((item, index) => {
2707
+ var _a;
2708
+ 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) },
2709
+ React.createElement("video", { ref: (el) => {
2710
+ carouselVideoRefs.current[index] = el;
2711
+ }, src: item.url, style: baseStyles.carouselVideo, muted: true, loop: true, playsInline: true, controls: false }),
2712
+ 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));
2713
+ })),
2714
+ React.createElement("button", { style: Object.assign(Object.assign({}, baseStyles.arrowButton), { left: '10px' }), onClick: handleCarouselPrev }, "\u2039"),
2715
+ React.createElement("button", { style: Object.assign(Object.assign({}, baseStyles.arrowButton), { right: '10px' }), onClick: handleCarouselNext }, "\u203A")),
2716
+ React.createElement("div", { style: mergeStyles(baseStyles.carouselInfoSection, 'carouselSection') },
2717
+ ((_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)),
2718
+ 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)))),
2719
+ data.highlightRevealSection && (React.createElement("div", { style: mergeStyles(baseStyles.highlightSection, 'highlightSection') },
2720
+ React.createElement("div", { style: baseStyles.highlightImageContainer },
2721
+ React.createElement("img", { src: data.highlightRevealSection.landingImageUrl || data.highlightRevealSection.cover, alt: data.highlightRevealSection.title, style: baseStyles.highlightImage })),
2722
+ React.createElement("div", { style: mergeStyles(baseStyles.highlightInfoSection, 'highlightSection') },
2723
+ React.createElement("div", { style: mergeStyles(baseStyles.highlightTitle, 'highlightSection') }, data.highlightRevealSection.title),
2724
+ renderCTA('highlightButton', data.highlightRevealSection.bindCta, data.highlightRevealSection, baseStyles.highlightButton)))),
2725
+ data.productGridSection && data.productGridSection.length > 0 && (React.createElement("div", { style: mergeStyles(baseStyles.productGrid, 'productGrid') }, (() => {
2726
+ // 创建一个6格的网格 (3行 x 2列),根据position放置产品
2727
+ const gridItems = [null, null, null, null, null, null];
2728
+ // 创建产品索引映射表:gridIndex -> 产品在数据数组中的索引(从1开始)
2729
+ const productIndexMap = {};
2730
+ data.productGridSection.forEach((product, idx) => {
2731
+ var _a;
2732
+ const pos = (_a = product.position) === null || _a === void 0 ? void 0 : _a.toLowerCase();
2733
+ let gridIndex = -1;
2734
+ if (pos === 'top_right') {
2735
+ gridIndex = 1; // 第一行右侧
2736
+ }
2737
+ else if (pos === 'top_left') {
2738
+ gridIndex = 0; // 第一行左侧
2739
+ }
2740
+ else if (pos === 'center_left') {
2741
+ gridIndex = 2; // 第二行左侧
2742
+ }
2743
+ else if (pos === 'center_right') {
2744
+ gridIndex = 3; // 第二行右侧
2745
+ }
2746
+ else if (pos === 'bottom_left') {
2747
+ gridIndex = 4; // 第三行左侧
2748
+ }
2749
+ else if (pos === 'bottom_right') {
2750
+ gridIndex = 5; // 第三行右侧
2751
+ }
2752
+ if (gridIndex >= 0) {
2753
+ gridItems[gridIndex] = product;
2754
+ // 映射:网格位置 -> 产品序号(基于数据数组的顺序,从1开始)
2755
+ productIndexMap[gridIndex] = idx + 1;
2756
+ }
2757
+ });
2758
+ return gridItems.map((product, gridIndex) => {
2759
+ // 使用产品在数据数组中的实际索引来确定 buttonKey
2760
+ const productDataIndex = productIndexMap[gridIndex];
2761
+ const buttonKey = `productButton${productDataIndex || gridIndex + 1}`;
2762
+ 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,
2763
+ React.createElement("div", { style: baseStyles.productImageContainer },
2764
+ React.createElement("img", { src: product.landingImageUrl || product.cover,
2765
+ // alt={product.title}
2766
+ style: baseStyles.productImage })),
2767
+ product.bindCta && (React.createElement("div", { style: baseStyles.productCtaContainer }, renderCTA(buttonKey, product.bindCta, product, baseStyles.productButton))))) : (
2768
+ // 空格子
2769
+ React.createElement("div", { style: { width: '100%', paddingBottom: '100%' } }))));
2770
+ });
2771
+ })())),
2772
+ data.footerSection && (React.createElement("div", { style: mergeStyles(baseStyles.footerSection, 'footerSection') },
2773
+ React.createElement("div", { style: mergeStyles(baseStyles.footerInfoSection, 'footerSection') }, renderCTA('footerButton', data.footerSection.bindCta, data.footerSection, baseStyles.footerButton)),
2774
+ React.createElement("div", { style: baseStyles.footerImageContainer },
2775
+ React.createElement("img", { src: data.footerSection.landingImageUrl || data.footerSection.cover, alt: data.footerSection.title, style: baseStyles.footerImage }))))));
2776
+ };
2777
+
1944
2778
  var index$3 = /*#__PURE__*/Object.freeze({
1945
2779
  __proto__: null,
1946
- EditorCore: EditorCore
2780
+ EditorCore: EditorCore,
2781
+ StructurePage: StructurePage
1947
2782
  });
1948
2783
 
1949
2784
  var interactionRender$h = [
@@ -3892,9 +4727,8 @@
3892
4727
  allSlidesSize += slideSizeValue + (spaceBetween || 0);
3893
4728
  });
3894
4729
  allSlidesSize -= spaceBetween;
3895
- const offsetSize = (params.slidesOffsetBefore || 0) + (params.slidesOffsetAfter || 0);
3896
- if (allSlidesSize + offsetSize < swiperSize) {
3897
- const allSlidesOffset = (swiperSize - allSlidesSize - offsetSize) / 2;
4730
+ if (allSlidesSize < swiperSize) {
4731
+ const allSlidesOffset = (swiperSize - allSlidesSize) / 2;
3898
4732
  snapGrid.forEach((snap, snapIndex) => {
3899
4733
  snapGrid[snapIndex] = snap - allSlidesOffset;
3900
4734
  });
@@ -3998,13 +4832,6 @@
3998
4832
  }
3999
4833
  }
4000
4834
 
4001
- const toggleSlideClasses$1 = (slideEl, condition, className) => {
4002
- if (condition && !slideEl.classList.contains(className)) {
4003
- slideEl.classList.add(className);
4004
- } else if (!condition && slideEl.classList.contains(className)) {
4005
- slideEl.classList.remove(className);
4006
- }
4007
- };
4008
4835
  function updateSlidesProgress(translate) {
4009
4836
  if (translate === void 0) {
4010
4837
  translate = this && this.translate || 0;
@@ -4020,6 +4847,11 @@
4020
4847
  if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset();
4021
4848
  let offsetCenter = -translate;
4022
4849
  if (rtl) offsetCenter = translate;
4850
+
4851
+ // Visible Slides
4852
+ slides.forEach(slideEl => {
4853
+ slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass);
4854
+ });
4023
4855
  swiper.visibleSlidesIndexes = [];
4024
4856
  swiper.visibleSlides = [];
4025
4857
  let spaceBetween = params.spaceBetween;
@@ -4043,9 +4875,11 @@
4043
4875
  if (isVisible) {
4044
4876
  swiper.visibleSlides.push(slide);
4045
4877
  swiper.visibleSlidesIndexes.push(i);
4878
+ slides[i].classList.add(params.slideVisibleClass);
4879
+ }
4880
+ if (isFullyVisible) {
4881
+ slides[i].classList.add(params.slideFullyVisibleClass);
4046
4882
  }
4047
- toggleSlideClasses$1(slide, isVisible, params.slideVisibleClass);
4048
- toggleSlideClasses$1(slide, isFullyVisible, params.slideFullyVisibleClass);
4049
4883
  slide.progress = rtl ? -slideProgress : slideProgress;
4050
4884
  slide.originalProgress = rtl ? -originalSlideProgress : originalSlideProgress;
4051
4885
  }
@@ -4114,13 +4948,6 @@
4114
4948
  swiper.emit('progress', progress);
4115
4949
  }
4116
4950
 
4117
- const toggleSlideClasses = (slideEl, condition, className) => {
4118
- if (condition && !slideEl.classList.contains(className)) {
4119
- slideEl.classList.add(className);
4120
- } else if (!condition && slideEl.classList.contains(className)) {
4121
- slideEl.classList.remove(className);
4122
- }
4123
- };
4124
4951
  function updateSlidesClasses() {
4125
4952
  const swiper = this;
4126
4953
  const {
@@ -4134,6 +4961,9 @@
4134
4961
  const getFilteredSlide = selector => {
4135
4962
  return elementChildren(slidesEl, `.${params.slideClass}${selector}, swiper-slide${selector}`)[0];
4136
4963
  };
4964
+ slides.forEach(slideEl => {
4965
+ slideEl.classList.remove(params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
4966
+ });
4137
4967
  let activeSlide;
4138
4968
  let prevSlide;
4139
4969
  let nextSlide;
@@ -4156,25 +4986,35 @@
4156
4986
  }
4157
4987
  }
4158
4988
  if (activeSlide) {
4159
- if (!gridEnabled) {
4989
+ // Active classes
4990
+ activeSlide.classList.add(params.slideActiveClass);
4991
+ if (gridEnabled) {
4992
+ if (nextSlide) {
4993
+ nextSlide.classList.add(params.slideNextClass);
4994
+ }
4995
+ if (prevSlide) {
4996
+ prevSlide.classList.add(params.slidePrevClass);
4997
+ }
4998
+ } else {
4160
4999
  // Next Slide
4161
5000
  nextSlide = elementNextAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
4162
5001
  if (params.loop && !nextSlide) {
4163
5002
  nextSlide = slides[0];
4164
5003
  }
5004
+ if (nextSlide) {
5005
+ nextSlide.classList.add(params.slideNextClass);
5006
+ }
4165
5007
 
4166
5008
  // Prev Slide
4167
5009
  prevSlide = elementPrevAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
4168
5010
  if (params.loop && !prevSlide === 0) {
4169
5011
  prevSlide = slides[slides.length - 1];
4170
5012
  }
5013
+ if (prevSlide) {
5014
+ prevSlide.classList.add(params.slidePrevClass);
5015
+ }
4171
5016
  }
4172
5017
  }
4173
- slides.forEach(slideEl => {
4174
- toggleSlideClasses(slideEl, slideEl === activeSlide, params.slideActiveClass);
4175
- toggleSlideClasses(slideEl, slideEl === nextSlide, params.slideNextClass);
4176
- toggleSlideClasses(slideEl, slideEl === prevSlide, params.slidePrevClass);
4177
- });
4178
5018
  swiper.emitSlidesClasses();
4179
5019
  }
4180
5020
 
@@ -4552,7 +5392,6 @@
4552
5392
  swiper.wrapperEl.removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);
4553
5393
  swiper.onTranslateToWrapperTransitionEnd = null;
4554
5394
  delete swiper.onTranslateToWrapperTransitionEnd;
4555
- swiper.animating = false;
4556
5395
  if (runCallbacks) {
4557
5396
  swiper.emit('transitionEnd');
4558
5397
  }
@@ -4660,6 +5499,9 @@
4660
5499
  if (index === void 0) {
4661
5500
  index = 0;
4662
5501
  }
5502
+ if (speed === void 0) {
5503
+ speed = this.params.speed;
5504
+ }
4663
5505
  if (runCallbacks === void 0) {
4664
5506
  runCallbacks = true;
4665
5507
  }
@@ -4679,12 +5521,9 @@
4679
5521
  wrapperEl,
4680
5522
  enabled
4681
5523
  } = swiper;
4682
- if (!enabled && !internal && !initial || swiper.destroyed || swiper.animating && params.preventInteractionOnTransition) {
5524
+ if (swiper.animating && params.preventInteractionOnTransition || !enabled && !internal && !initial || swiper.destroyed) {
4683
5525
  return false;
4684
5526
  }
4685
- if (typeof speed === 'undefined') {
4686
- speed = swiper.params.speed;
4687
- }
4688
5527
  const skip = Math.min(swiper.params.slidesPerGroupSkip, slideIndex);
4689
5528
  let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup);
4690
5529
  if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
@@ -4811,6 +5650,9 @@
4811
5650
  if (index === void 0) {
4812
5651
  index = 0;
4813
5652
  }
5653
+ if (speed === void 0) {
5654
+ speed = this.params.speed;
5655
+ }
4814
5656
  if (runCallbacks === void 0) {
4815
5657
  runCallbacks = true;
4816
5658
  }
@@ -4820,9 +5662,6 @@
4820
5662
  }
4821
5663
  const swiper = this;
4822
5664
  if (swiper.destroyed) return;
4823
- if (typeof speed === 'undefined') {
4824
- speed = swiper.params.speed;
4825
- }
4826
5665
  const gridEnabled = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1;
4827
5666
  let newIndex = index;
4828
5667
  if (swiper.params.loop) {
@@ -4854,9 +5693,6 @@
4854
5693
  if (centeredSlides) {
4855
5694
  needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2);
4856
5695
  }
4857
- if (internal && centeredSlides && swiper.params.slidesPerView !== 'auto' && !gridEnabled) {
4858
- needLoopFix = false;
4859
- }
4860
5696
  if (needLoopFix) {
4861
5697
  const direction = centeredSlides ? targetSlideIndex < swiper.activeIndex ? 'prev' : 'next' : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView ? 'next' : 'prev';
4862
5698
  swiper.loopFix({
@@ -4882,6 +5718,9 @@
4882
5718
 
4883
5719
  /* eslint no-unused-vars: "off" */
4884
5720
  function slideNext(speed, runCallbacks, internal) {
5721
+ if (speed === void 0) {
5722
+ speed = this.params.speed;
5723
+ }
4885
5724
  if (runCallbacks === void 0) {
4886
5725
  runCallbacks = true;
4887
5726
  }
@@ -4892,9 +5731,6 @@
4892
5731
  animating
4893
5732
  } = swiper;
4894
5733
  if (!enabled || swiper.destroyed) return swiper;
4895
- if (typeof speed === 'undefined') {
4896
- speed = swiper.params.speed;
4897
- }
4898
5734
  let perGroup = params.slidesPerGroup;
4899
5735
  if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {
4900
5736
  perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1);
@@ -4923,6 +5759,9 @@
4923
5759
 
4924
5760
  /* eslint no-unused-vars: "off" */
4925
5761
  function slidePrev(speed, runCallbacks, internal) {
5762
+ if (speed === void 0) {
5763
+ speed = this.params.speed;
5764
+ }
4926
5765
  if (runCallbacks === void 0) {
4927
5766
  runCallbacks = true;
4928
5767
  }
@@ -4936,9 +5775,6 @@
4936
5775
  animating
4937
5776
  } = swiper;
4938
5777
  if (!enabled || swiper.destroyed) return swiper;
4939
- if (typeof speed === 'undefined') {
4940
- speed = swiper.params.speed;
4941
- }
4942
5778
  const isVirtual = swiper.virtual && params.virtual.enabled;
4943
5779
  if (params.loop) {
4944
5780
  if (animating && !isVirtual && params.loopPreventsSliding) return false;
@@ -4991,19 +5827,22 @@
4991
5827
 
4992
5828
  /* eslint no-unused-vars: "off" */
4993
5829
  function slideReset(speed, runCallbacks, internal) {
5830
+ if (speed === void 0) {
5831
+ speed = this.params.speed;
5832
+ }
4994
5833
  if (runCallbacks === void 0) {
4995
5834
  runCallbacks = true;
4996
5835
  }
4997
5836
  const swiper = this;
4998
5837
  if (swiper.destroyed) return;
4999
- if (typeof speed === 'undefined') {
5000
- speed = swiper.params.speed;
5001
- }
5002
5838
  return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);
5003
5839
  }
5004
5840
 
5005
5841
  /* eslint no-unused-vars: "off" */
5006
5842
  function slideToClosest(speed, runCallbacks, internal, threshold) {
5843
+ if (speed === void 0) {
5844
+ speed = this.params.speed;
5845
+ }
5007
5846
  if (runCallbacks === void 0) {
5008
5847
  runCallbacks = true;
5009
5848
  }
@@ -5012,9 +5851,6 @@
5012
5851
  }
5013
5852
  const swiper = this;
5014
5853
  if (swiper.destroyed) return;
5015
- if (typeof speed === 'undefined') {
5016
- speed = swiper.params.speed;
5017
- }
5018
5854
  let index = swiper.activeIndex;
5019
5855
  const skip = Math.min(swiper.params.slidesPerGroupSkip, index);
5020
5856
  const snapIndex = skip + Math.floor((index - skip) / swiper.params.slidesPerGroup);
@@ -5649,7 +6485,7 @@
5649
6485
  data.startMoving = true;
5650
6486
  }
5651
6487
  }
5652
- if (data.isScrolling || e.type === 'touchmove' && data.preventTouchMoveFromPointerMove) {
6488
+ if (data.isScrolling) {
5653
6489
  data.isTouched = false;
5654
6490
  return;
5655
6491
  }
@@ -5691,10 +6527,7 @@
5691
6527
  if (swiper.animating) {
5692
6528
  const evt = new window.CustomEvent('transitionend', {
5693
6529
  bubbles: true,
5694
- cancelable: true,
5695
- detail: {
5696
- bySwiperTouchMove: true
5697
- }
6530
+ cancelable: true
5698
6531
  });
5699
6532
  swiper.wrapperEl.dispatchEvent(evt);
5700
6533
  }
@@ -6088,7 +6921,6 @@
6088
6921
  const capture = !!params.nested;
6089
6922
  const domMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';
6090
6923
  const swiperMethod = method;
6091
- if (!el || typeof el === 'string') return;
6092
6924
 
6093
6925
  // Touch Events
6094
6926
  document[domMethod]('touchstart', swiper.onDocumentTouchStart, {
@@ -6197,8 +7029,6 @@
6197
7029
  const breakpointParams = breakpointOnlyParams || swiper.originalParams;
6198
7030
  const wasMultiRow = isGridEnabled(swiper, params);
6199
7031
  const isMultiRow = isGridEnabled(swiper, breakpointParams);
6200
- const wasGrabCursor = swiper.params.grabCursor;
6201
- const isGrabCursor = breakpointParams.grabCursor;
6202
7032
  const wasEnabled = params.enabled;
6203
7033
  if (wasMultiRow && !isMultiRow) {
6204
7034
  el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`);
@@ -6210,11 +7040,6 @@
6210
7040
  }
6211
7041
  swiper.emitContainerClasses();
6212
7042
  }
6213
- if (wasGrabCursor && !isGrabCursor) {
6214
- swiper.unsetGrabCursor();
6215
- } else if (!wasGrabCursor && isGrabCursor) {
6216
- swiper.setGrabCursor();
6217
- }
6218
7043
 
6219
7044
  // Toggle navigation, pagination, scrollbar
6220
7045
  ['navigation', 'pagination', 'scrollbar'].forEach(prop => {
@@ -6365,7 +7190,6 @@
6365
7190
  el,
6366
7191
  classNames
6367
7192
  } = swiper;
6368
- if (!el || typeof el === 'string') return;
6369
7193
  el.classList.remove(...classNames);
6370
7194
  swiper.emitContainerClasses();
6371
7195
  }
@@ -7130,12 +7954,8 @@
7130
7954
  // Cleanup styles
7131
7955
  if (cleanStyles) {
7132
7956
  swiper.removeClasses();
7133
- if (el && typeof el !== 'string') {
7134
- el.removeAttribute('style');
7135
- }
7136
- if (wrapperEl) {
7137
- wrapperEl.removeAttribute('style');
7138
- }
7957
+ el.removeAttribute('style');
7958
+ wrapperEl.removeAttribute('style');
7139
7959
  if (slides && slides.length) {
7140
7960
  slides.forEach(slideEl => {
7141
7961
  slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
@@ -7151,9 +7971,7 @@
7151
7971
  swiper.off(eventName);
7152
7972
  });
7153
7973
  if (deleteInstance !== false) {
7154
- if (swiper.el && typeof swiper.el !== 'string') {
7155
- swiper.el.swiper = null;
7156
- }
7974
+ swiper.el.swiper = null;
7157
7975
  deleteProps(swiper);
7158
7976
  }
7159
7977
  swiper.destroyed = true;
@@ -7547,7 +8365,7 @@
7547
8365
  };
7548
8366
 
7549
8367
  /**
7550
- * Swiper React 11.1.4
8368
+ * Swiper React 11.0.7
7551
8369
  * Most modern mobile touch slider and framework with hardware accelerated transitions
7552
8370
  * https://swiperjs.com
7553
8371
  *
@@ -7555,7 +8373,7 @@
7555
8373
  *
7556
8374
  * Released under the MIT License
7557
8375
  *
7558
- * Released on: May 30, 2024
8376
+ * Released on: February 27, 2024
7559
8377
  */
7560
8378
 
7561
8379
 
@@ -8482,10 +9300,8 @@
8482
9300
  }
8483
9301
  if (el) {
8484
9302
  if (typeof el === 'string') res = [...document.querySelectorAll(el)];
8485
- if (swiper.params.uniqueNavElements && typeof el === 'string' && res && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {
9303
+ if (swiper.params.uniqueNavElements && typeof el === 'string' && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {
8486
9304
  res = swiper.el.querySelector(el);
8487
- } else if (res && res.length === 1) {
8488
- res = res[0];
8489
9305
  }
8490
9306
  }
8491
9307
  if (el && !res) return el;
@@ -8607,14 +9423,7 @@
8607
9423
  nextEl = makeElementsArray(nextEl);
8608
9424
  prevEl = makeElementsArray(prevEl);
8609
9425
  const targetEl = e.target;
8610
- let targetIsButton = prevEl.includes(targetEl) || nextEl.includes(targetEl);
8611
- if (swiper.isElement && !targetIsButton) {
8612
- const path = e.path || e.composedPath && e.composedPath();
8613
- if (path) {
8614
- targetIsButton = path.find(pathEl => nextEl.includes(pathEl) || prevEl.includes(pathEl));
8615
- }
8616
- }
8617
- if (swiper.params.navigation.hideOnClick && !targetIsButton) {
9426
+ if (swiper.params.navigation.hideOnClick && !prevEl.includes(targetEl) && !nextEl.includes(targetEl)) {
8618
9427
  if (swiper.pagination && swiper.params.pagination && swiper.params.pagination.clickable && (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) return;
8619
9428
  let isHidden;
8620
9429
  if (nextEl.length) {
@@ -9270,7 +10079,7 @@
9270
10079
  dragEl
9271
10080
  } = scrollbar;
9272
10081
  if (!isTouched) return;
9273
- if (e.preventDefault && e.cancelable) e.preventDefault();else e.returnValue = false;
10082
+ if (e.preventDefault) e.preventDefault();else e.returnValue = false;
9274
10083
  setDragPosition(e);
9275
10084
  wrapperEl.style.transitionDuration = '0ms';
9276
10085
  el.style.transitionDuration = '0ms';
@@ -9481,9 +10290,6 @@
9481
10290
  clicked: false
9482
10291
  };
9483
10292
  let liveRegion = null;
9484
- let preventFocusHandler;
9485
- let focusTargetSlideEl;
9486
- let visibilityChangedTimestamp = new Date().getTime();
9487
10293
  function notify(message) {
9488
10294
  const notification = liveRegion;
9489
10295
  if (notification.length === 0) return;
@@ -9564,28 +10370,24 @@
9564
10370
  if (swiper.pagination && swiper.pagination.el && (targetEl === swiper.pagination.el || swiper.pagination.el.contains(e.target))) {
9565
10371
  if (!e.target.matches(classesToSelector(swiper.params.pagination.bulletClass))) return;
9566
10372
  }
9567
- if (swiper.navigation && swiper.navigation.prevEl && swiper.navigation.nextEl) {
9568
- const prevEls = makeElementsArray(swiper.navigation.prevEl);
9569
- const nextEls = makeElementsArray(swiper.navigation.nextEl);
9570
- if (nextEls.includes(targetEl)) {
9571
- if (!(swiper.isEnd && !swiper.params.loop)) {
9572
- swiper.slideNext();
9573
- }
9574
- if (swiper.isEnd) {
9575
- notify(params.lastSlideMessage);
9576
- } else {
9577
- notify(params.nextSlideMessage);
9578
- }
10373
+ if (swiper.navigation && swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl) {
10374
+ if (!(swiper.isEnd && !swiper.params.loop)) {
10375
+ swiper.slideNext();
9579
10376
  }
9580
- if (prevEls.includes(targetEl)) {
9581
- if (!(swiper.isBeginning && !swiper.params.loop)) {
9582
- swiper.slidePrev();
9583
- }
9584
- if (swiper.isBeginning) {
9585
- notify(params.firstSlideMessage);
9586
- } else {
9587
- notify(params.prevSlideMessage);
9588
- }
10377
+ if (swiper.isEnd) {
10378
+ notify(params.lastSlideMessage);
10379
+ } else {
10380
+ notify(params.nextSlideMessage);
10381
+ }
10382
+ }
10383
+ if (swiper.navigation && swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl) {
10384
+ if (!(swiper.isBeginning && !swiper.params.loop)) {
10385
+ swiper.slidePrev();
10386
+ }
10387
+ if (swiper.isBeginning) {
10388
+ notify(params.firstSlideMessage);
10389
+ } else {
10390
+ notify(params.prevSlideMessage);
9589
10391
  }
9590
10392
  }
9591
10393
  if (swiper.pagination && targetEl.matches(classesToSelector(swiper.params.pagination.bulletClass))) {
@@ -9650,14 +10452,10 @@
9650
10452
  addElLabel(el, message);
9651
10453
  addElControls(el, wrapperId);
9652
10454
  };
9653
- const handlePointerDown = e => {
9654
- if (focusTargetSlideEl && focusTargetSlideEl !== e.target && !focusTargetSlideEl.contains(e.target)) {
9655
- preventFocusHandler = true;
9656
- }
10455
+ const handlePointerDown = () => {
9657
10456
  swiper.a11y.clicked = true;
9658
10457
  };
9659
10458
  const handlePointerUp = () => {
9660
- preventFocusHandler = false;
9661
10459
  requestAnimationFrame(() => {
9662
10460
  requestAnimationFrame(() => {
9663
10461
  if (!swiper.destroyed) {
@@ -9666,15 +10464,10 @@
9666
10464
  });
9667
10465
  });
9668
10466
  };
9669
- const onVisibilityChange = e => {
9670
- visibilityChangedTimestamp = new Date().getTime();
9671
- };
9672
10467
  const handleFocus = e => {
9673
10468
  if (swiper.a11y.clicked) return;
9674
- if (new Date().getTime() - visibilityChangedTimestamp < 100) return;
9675
10469
  const slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`);
9676
10470
  if (!slideEl || !swiper.slides.includes(slideEl)) return;
9677
- focusTargetSlideEl = slideEl;
9678
10471
  const isActive = swiper.slides.indexOf(slideEl) === swiper.activeIndex;
9679
10472
  const isVisible = swiper.params.watchSlidesProgress && swiper.visibleSlides && swiper.visibleSlides.includes(slideEl);
9680
10473
  if (isActive || isVisible) return;
@@ -9684,15 +10477,7 @@
9684
10477
  } else {
9685
10478
  swiper.el.scrollTop = 0;
9686
10479
  }
9687
- requestAnimationFrame(() => {
9688
- if (preventFocusHandler) return;
9689
- if (swiper.params.loop) {
9690
- swiper.slideToLoop(parseInt(slideEl.getAttribute('data-swiper-slide-index')), 0);
9691
- } else {
9692
- swiper.slideTo(swiper.slides.indexOf(slideEl), 0);
9693
- }
9694
- preventFocusHandler = false;
9695
- });
10480
+ swiper.slideTo(swiper.slides.indexOf(slideEl), 0);
9696
10481
  };
9697
10482
  const initSlides = () => {
9698
10483
  const params = swiper.params.a11y;
@@ -9757,9 +10542,6 @@
9757
10542
  }
9758
10543
 
9759
10544
  // Tab focus
9760
- const document = getDocument();
9761
- document.addEventListener('visibilitychange', onVisibilityChange);
9762
- swiper.el.addEventListener('focus', handleFocus, true);
9763
10545
  swiper.el.addEventListener('focus', handleFocus, true);
9764
10546
  swiper.el.addEventListener('pointerdown', handlePointerDown, true);
9765
10547
  swiper.el.addEventListener('pointerup', handlePointerUp, true);
@@ -9786,14 +10568,11 @@
9786
10568
  el.removeEventListener('keydown', onEnterOrSpaceKey);
9787
10569
  });
9788
10570
  }
9789
- const document = getDocument();
9790
- document.removeEventListener('visibilitychange', onVisibilityChange);
10571
+
9791
10572
  // Tab focus
9792
- if (swiper.el && typeof swiper.el !== 'string') {
9793
- swiper.el.removeEventListener('focus', handleFocus, true);
9794
- swiper.el.removeEventListener('pointerdown', handlePointerDown, true);
9795
- swiper.el.removeEventListener('pointerup', handlePointerUp, true);
9796
- }
10573
+ swiper.el.removeEventListener('focus', handleFocus, true);
10574
+ swiper.el.removeEventListener('pointerdown', handlePointerDown, true);
10575
+ swiper.el.removeEventListener('pointerup', handlePointerUp, true);
9797
10576
  }
9798
10577
  on('beforeInit', () => {
9799
10578
  liveRegion = createElement('span', swiper.params.a11y.notificationClass);
@@ -9865,7 +10644,7 @@
9865
10644
  if (!swiper || swiper.destroyed || !swiper.wrapperEl) return;
9866
10645
  if (e.target !== swiper.wrapperEl) return;
9867
10646
  swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd);
9868
- if (pausedByPointerEnter || e.detail && e.detail.bySwiperTouchMove) {
10647
+ if (pausedByPointerEnter) {
9869
10648
  return;
9870
10649
  }
9871
10650
  resume();
@@ -10036,10 +10815,8 @@
10036
10815
  }
10037
10816
  };
10038
10817
  const detachMouseEvents = () => {
10039
- if (swiper.el && typeof swiper.el !== 'string') {
10040
- swiper.el.removeEventListener('pointerenter', onPointerEnter);
10041
- swiper.el.removeEventListener('pointerleave', onPointerLeave);
10042
- }
10818
+ swiper.el.removeEventListener('pointerenter', onPointerEnter);
10819
+ swiper.el.removeEventListener('pointerleave', onPointerLeave);
10043
10820
  };
10044
10821
  const attachDocumentEvents = () => {
10045
10822
  const document = getDocument();
@@ -10377,49 +11154,6 @@
10377
11154
  };
10378
11155
  var Scroll$1 = React.memo(Scroll);
10379
11156
 
10380
- const FormatImage = React.forwardRef((props, ref) => {
10381
- const { src, onLoad, style, className, loading, alt = 'image' } = props;
10382
- const [imgSrc, setImgSrc] = React.useState(src);
10383
- const imgRef = React.useRef(null);
10384
- const [visible, setVisible] = React.useState(false);
10385
- React.useImperativeHandle(ref, () => ({
10386
- setSrc: (v) => {
10387
- if (v)
10388
- setImgSrc(v);
10389
- }
10390
- }));
10391
- React.useEffect(() => {
10392
- if (src)
10393
- setImgSrc(src);
10394
- }, [src]);
10395
- React.useEffect(() => {
10396
- const onShow = () => {
10397
- if (src && !visible && imgRef.current) {
10398
- imgRef.current.src = '';
10399
- imgRef.current.src = src;
10400
- }
10401
- };
10402
- SXP_EVENT_BUS.on(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
10403
- return () => {
10404
- SXP_EVENT_BUS.off(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
10405
- };
10406
- }, [src, visible]);
10407
- return (React.createElement(React.Fragment, null,
10408
- !visible && !imgSrc && React.createElement("div", { style: { width: '100%', height: '100%', zIndex: 1, backgroundColor: '#fff' } }),
10409
- (imgSrc === null || imgSrc === void 0 ? void 0 : imgSrc.includes('.avif')) ? (React.createElement("picture", null,
10410
- React.createElement("source", { type: 'image/avif', srcSet: imgSrc }),
10411
- React.createElement("source", { type: 'image/webp', srcSet: `${imgSrc}?imageMogr2/format/webp` }),
10412
- React.createElement("source", { type: 'image/jpeg', srcSet: `${imgSrc}?imageMogr2/format/jpg` }),
10413
- React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
10414
- setVisible(true);
10415
- onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
10416
- }, alt: alt }))) : (React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
10417
- setVisible(true);
10418
- onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
10419
- }, alt: alt }))));
10420
- });
10421
- var FormatImage$1 = React.memo(FormatImage);
10422
-
10423
11157
  const CommodityGroup = ({ products, data, defImg, style, onCLick, popupDetailData, check }) => {
10424
11158
  var _a;
10425
11159
  const { productView } = useEventReport();
@@ -10509,13 +11243,13 @@
10509
11243
  styleElement.id = 'onetrust-pc-sdk';
10510
11244
  styleElement.setAttribute('type', 'text/css');
10511
11245
  document.head.appendChild(styleElement);
10512
- const css = `
10513
- #onetrust-pc-sdk {
10514
- height: ${finalHeight}px !important;
10515
- }
10516
- #onetrust-pc-sdk #ot-pc-content{
10517
- bottom: ${b}px !important;
10518
- }
11246
+ const css = `
11247
+ #onetrust-pc-sdk {
11248
+ height: ${finalHeight}px !important;
11249
+ }
11250
+ #onetrust-pc-sdk #ot-pc-content{
11251
+ bottom: ${b}px !important;
11252
+ }
10519
11253
  `;
10520
11254
  styleElement.textContent = css;
10521
11255
  }
@@ -11062,10 +11796,10 @@
11062
11796
  __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)
11063
11797
  } }),
11064
11798
  React.createElement("div", { hidden: !!product && (!(product === null || product === void 0 ? void 0 : product.info) || (product === null || product === void 0 ? void 0 : product.info) === '') },
11065
- 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
11066
- bold and avant-garde visual design interprets the emotional bond connecting my heart. The Tiffany Lock
11067
- collection is unisex and is inspired by the padlock pattern found in the Tiffany Antique Collection. This
11068
- necklace features a stylish and eye-catching oval clasp chain decorated with a lock pattern. Crafted from
11799
+ 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
11800
+ bold and avant-garde visual design interprets the emotional bond connecting my heart. The Tiffany Lock
11801
+ collection is unisex and is inspired by the padlock pattern found in the Tiffany Antique Collection. This
11802
+ necklace features a stylish and eye-catching oval clasp chain decorated with a lock pattern. Crafted from
11069
11803
  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 }))));
11070
11804
  };
11071
11805
  const renderBtn = () => {
@@ -12064,7 +12798,7 @@
12064
12798
  const productInfoText = ({ isPost }) => {
12065
12799
  return (React.createElement("div", { hidden: !!product && (!(product === null || product === void 0 ? void 0 : product.info) || (product === null || product === void 0 ? void 0 : product.info) === '') },
12066
12800
  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) ||
12067
- `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
12801
+ `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
12068
12802
  Made in Italy` })));
12069
12803
  };
12070
12804
  const getStyle = React.useCallback((style) => {
@@ -18246,10 +18980,10 @@ Made in Italy` })));
18246
18980
  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) || '';
18247
18981
  const getPropsVal = React.useCallback((index, str) => {
18248
18982
  try {
18249
- return new Function('props', 'str', `if (str) {
18250
- return props?.button${index + 1}${str}
18251
- } else {
18252
- return props?.button${index + 1}
18983
+ return new Function('props', 'str', `if (str) {
18984
+ return props?.button${index + 1}${str}
18985
+ } else {
18986
+ return props?.button${index + 1}
18253
18987
  }`)(props, str);
18254
18988
  }
18255
18989
  catch (_a) { }
@@ -20132,10 +20866,16 @@ Made in Italy` })));
20132
20866
  React.createElement(Swiper, { style: {
20133
20867
  marginTop: tagHeight
20134
20868
  }, ref: swiperRef, onSlideChange: () => {
20135
- swiperRef.current.swiper.allowTouchMove = false;
20136
- setTimeout(() => {
20137
- swiperRef.current.swiper.allowTouchMove = true;
20138
- }, 500);
20869
+ var _a;
20870
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
20871
+ swiperRef.current.swiper.allowTouchMove = false;
20872
+ setTimeout(() => {
20873
+ var _a;
20874
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
20875
+ swiperRef.current.swiper.allowTouchMove = true;
20876
+ }
20877
+ }, 500);
20878
+ }
20139
20879
  }, onActiveIndexChange: (swiper) => {
20140
20880
  var _a, _b;
20141
20881
  setActiveIndex(swiper.activeIndex);
@@ -21028,10 +21768,16 @@ Made in Italy` })));
21028
21768
  // className={style['clc-sxp-container']}
21029
21769
  style: { height: containerHeight, position: 'relative', pointerEvents } },
21030
21770
  React.createElement(Swiper, { ref: swiperRef, allowTouchMove: pointerEvents !== 'none', onSlideChange: () => {
21031
- swiperRef.current.swiper.allowTouchMove = false;
21032
- setTimeout(() => {
21033
- swiperRef.current.swiper.allowTouchMove = true;
21034
- }, 500);
21771
+ var _a;
21772
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
21773
+ swiperRef.current.swiper.allowTouchMove = false;
21774
+ setTimeout(() => {
21775
+ var _a;
21776
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
21777
+ swiperRef.current.swiper.allowTouchMove = true;
21778
+ }
21779
+ }, 500);
21780
+ }
21035
21781
  }, onActiveIndexChange: (swiper) => {
21036
21782
  setCurIndex(swiper === null || swiper === void 0 ? void 0 : swiper.activeIndex);
21037
21783
  onActiveChange === null || onActiveChange === void 0 ? void 0 : onActiveChange(swiper.activeIndex);
@@ -21187,6 +21933,7 @@ Made in Italy` })));
21187
21933
  exports.DiyStoryPreview = index$1;
21188
21934
  exports.EditorDataProvider = EditorDataProvider;
21189
21935
  exports.Modal = Modal$1;
21936
+ exports.StructurePage = StructurePage;
21190
21937
  exports.SxpDataSourceProvider = SxpDataSourceProvider$1;
21191
21938
  exports.SxpPageCore = index;
21192
21939
  exports.SxpPageRender = SxpPageRender$1;