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/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,820 @@
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
+ Object.values(materialsModule).forEach((v) => {
1998
+ var _a;
1999
+ if ((_a = v === null || v === void 0 ? void 0 : v.extend) === null || _a === void 0 ? void 0 : _a.type) {
2000
+ RESOLVER$3[v.extend.type] = v;
2001
+ }
2002
+ });
2003
+ }
2004
+ catch (error) {
2005
+ console.warn('Failed to load materials for StructurePage:', error);
2006
+ }
2007
+ // 基础样式定义
2008
+ const baseStyles = {
2009
+ container: {
2010
+ backgroundColor: '#000',
2011
+ overflowY: 'auto',
2012
+ overflowX: 'hidden',
2013
+ padding: 0,
2014
+ boxSizing: 'border-box'
2015
+ },
2016
+ section: {
2017
+ width: '100%',
2018
+ position: 'relative',
2019
+ boxSizing: 'border-box'
2020
+ },
2021
+ // Hero Section
2022
+ heroSection: {
2023
+ width: '100%',
2024
+ height: 'auto',
2025
+ position: 'relative',
2026
+ overflow: 'hidden',
2027
+ backgroundColor: '#000'
2028
+ },
2029
+ heroTopText: {
2030
+ width: '100%',
2031
+ padding: '20px',
2032
+ backgroundColor: '#fff',
2033
+ color: '#000',
2034
+ fontSize: '16px',
2035
+ fontWeight: 'bold',
2036
+ textAlign: 'center',
2037
+ boxSizing: 'border-box'
2038
+ },
2039
+ heroImageContainer: {
2040
+ width: '100%',
2041
+ position: 'relative',
2042
+ overflow: 'hidden'
2043
+ },
2044
+ heroImage: {
2045
+ width: '100%',
2046
+ height: 'auto',
2047
+ display: 'block',
2048
+ objectFit: 'cover'
2049
+ },
2050
+ heroVideo: {
2051
+ width: '100%',
2052
+ height: 'auto',
2053
+ display: 'block',
2054
+ objectFit: 'cover'
2055
+ },
2056
+ heroOverlay: {
2057
+ position: 'absolute',
2058
+ bottom: 0,
2059
+ left: 0,
2060
+ right: 0,
2061
+ padding: '40px 20px',
2062
+ background: 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 100%)',
2063
+ color: '#fff',
2064
+ display: 'flex',
2065
+ justifyContent: 'center',
2066
+ alignItems: 'center'
2067
+ },
2068
+ heroButton: {
2069
+ padding: '12px 30px',
2070
+ backgroundColor: '#fff',
2071
+ color: '#000',
2072
+ border: 'none',
2073
+ fontSize: '14px',
2074
+ fontWeight: 500,
2075
+ cursor: 'pointer',
2076
+ textTransform: 'uppercase'
2077
+ },
2078
+ // Carousel Section
2079
+ carouselSection: {
2080
+ width: '100%',
2081
+ position: 'relative'
2082
+ },
2083
+ carouselImageContainer: {
2084
+ width: '100%',
2085
+ height: 'auto',
2086
+ position: 'relative',
2087
+ overflow: 'hidden'
2088
+ },
2089
+ carouselContainer: {
2090
+ display: 'flex',
2091
+ transition: 'transform 0.5s ease-in-out',
2092
+ width: '100%'
2093
+ },
2094
+ carouselSlide: {
2095
+ minWidth: '100%',
2096
+ position: 'relative'
2097
+ },
2098
+ carouselImage: {
2099
+ width: '100%',
2100
+ height: 'auto',
2101
+ display: 'block',
2102
+ objectFit: 'cover'
2103
+ },
2104
+ carouselVideo: {
2105
+ width: '100%',
2106
+ height: 'auto',
2107
+ display: 'block',
2108
+ objectFit: 'cover'
2109
+ },
2110
+ carouselInfoSection: {
2111
+ width: '100%',
2112
+ padding: '20px',
2113
+ backgroundColor: '#000',
2114
+ color: '#fff',
2115
+ textAlign: 'center'
2116
+ },
2117
+ carouselText: {
2118
+ fontSize: '16px',
2119
+ fontWeight: 'normal',
2120
+ marginBottom: '15px',
2121
+ color: '#fff'
2122
+ },
2123
+ carouselButton: {
2124
+ padding: '10px 25px',
2125
+ backgroundColor: '#fff',
2126
+ color: '#000',
2127
+ border: '1px solid #fff',
2128
+ fontSize: '13px',
2129
+ fontWeight: 500,
2130
+ cursor: 'pointer',
2131
+ textTransform: 'uppercase'
2132
+ },
2133
+ arrowButton: {
2134
+ position: 'absolute',
2135
+ top: '50%',
2136
+ transform: 'translateY(-50%)',
2137
+ width: '40px',
2138
+ height: '40px',
2139
+ backgroundColor: 'rgba(255,255,255,0.8)',
2140
+ border: 'none',
2141
+ borderRadius: '50%',
2142
+ fontSize: '18px',
2143
+ cursor: 'pointer',
2144
+ zIndex: 10,
2145
+ display: 'flex',
2146
+ alignItems: 'center',
2147
+ justifyContent: 'center'
2148
+ },
2149
+ // Highlight Reveal Section
2150
+ highlightSection: {
2151
+ width: '100%',
2152
+ position: 'relative',
2153
+ backgroundColor: '#000'
2154
+ },
2155
+ highlightImageContainer: {
2156
+ width: '100%',
2157
+ aspectRatio: '1/1',
2158
+ position: 'relative',
2159
+ overflow: 'hidden'
2160
+ },
2161
+ highlightImage: {
2162
+ width: '100%',
2163
+ height: '100%',
2164
+ objectFit: 'cover',
2165
+ display: 'block'
2166
+ },
2167
+ highlightInfoSection: {
2168
+ width: '100%',
2169
+ padding: '20px',
2170
+ backgroundColor: '#000',
2171
+ color: '#fff',
2172
+ textAlign: 'center'
2173
+ },
2174
+ highlightTitle: {
2175
+ fontSize: '18px',
2176
+ fontWeight: 'bold',
2177
+ marginBottom: '10px',
2178
+ textAlign: 'center',
2179
+ color: '#fff'
2180
+ },
2181
+ highlightDesc: {
2182
+ fontSize: '14px',
2183
+ marginBottom: '15px',
2184
+ textAlign: 'center',
2185
+ lineHeight: '1.5',
2186
+ color: '#ccc'
2187
+ },
2188
+ highlightButton: {
2189
+ padding: '10px 25px',
2190
+ backgroundColor: 'transparent',
2191
+ color: '#fff',
2192
+ border: '1px solid #fff',
2193
+ fontSize: '13px',
2194
+ fontWeight: 500,
2195
+ cursor: 'pointer',
2196
+ textTransform: 'uppercase'
2197
+ },
2198
+ // Product Grid Section
2199
+ productGrid: {
2200
+ display: 'grid',
2201
+ gridTemplateColumns: '50% 50%',
2202
+ gridAutoRows: 'auto',
2203
+ gap: '0',
2204
+ width: '100%',
2205
+ backgroundColor: '#000',
2206
+ boxSizing: 'border-box',
2207
+ margin: 0,
2208
+ padding: 0,
2209
+ overflow: 'hidden'
2210
+ },
2211
+ productItem: {
2212
+ position: 'relative',
2213
+ backgroundColor: '#000',
2214
+ display: 'block',
2215
+ boxSizing: 'border-box',
2216
+ width: '100%',
2217
+ minWidth: 0,
2218
+ overflow: 'hidden'
2219
+ },
2220
+ productImageContainer: {
2221
+ width: '100%',
2222
+ paddingBottom: '100%',
2223
+ position: 'relative',
2224
+ overflow: 'hidden'
2225
+ },
2226
+ productImage: {
2227
+ position: 'absolute',
2228
+ top: 0,
2229
+ left: 0,
2230
+ width: '100%',
2231
+ height: '100%',
2232
+ objectFit: 'cover',
2233
+ display: 'block'
2234
+ },
2235
+ productCtaContainer: {
2236
+ width: '100%',
2237
+ padding: '15px',
2238
+ backgroundColor: '#000',
2239
+ textAlign: 'center',
2240
+ boxSizing: 'border-box'
2241
+ },
2242
+ productText: {
2243
+ width: '100%',
2244
+ padding: '15px',
2245
+ backgroundColor: '#000',
2246
+ color: '#fff',
2247
+ textAlign: 'center',
2248
+ fontSize: '14px',
2249
+ fontWeight: 'normal',
2250
+ boxSizing: 'border-box'
2251
+ },
2252
+ productButton: {
2253
+ padding: '8px 20px',
2254
+ backgroundColor: 'transparent',
2255
+ color: '#fff',
2256
+ border: '1px solid #fff',
2257
+ fontSize: '12px',
2258
+ fontWeight: 500,
2259
+ cursor: 'pointer',
2260
+ textTransform: 'uppercase',
2261
+ whiteSpace: 'nowrap'
2262
+ },
2263
+ // Footer Section
2264
+ footerSection: {
2265
+ width: '100%',
2266
+ position: 'relative',
2267
+ backgroundColor: '#000'
2268
+ },
2269
+ footerInfoSection: {
2270
+ width: '100%',
2271
+ padding: '20px',
2272
+ backgroundColor: '#000',
2273
+ color: '#fff',
2274
+ textAlign: 'center'
2275
+ },
2276
+ footerText: {
2277
+ fontSize: '18px',
2278
+ fontWeight: 'normal',
2279
+ marginBottom: '15px',
2280
+ lineHeight: '1.4',
2281
+ color: '#fff'
2282
+ },
2283
+ footerButton: {
2284
+ padding: '10px 25px',
2285
+ backgroundColor: 'transparent',
2286
+ color: '#fff',
2287
+ border: '1px solid #fff',
2288
+ fontSize: '13px',
2289
+ fontWeight: 500,
2290
+ cursor: 'pointer',
2291
+ textTransform: 'uppercase',
2292
+ marginBottom: '20px',
2293
+ display: 'inline-block'
2294
+ },
2295
+ footerImageContainer: {
2296
+ width: '100%',
2297
+ aspectRatio: '1/1',
2298
+ overflow: 'hidden'
2299
+ },
2300
+ footerImage: {
2301
+ width: '100%',
2302
+ height: '100%',
2303
+ objectFit: 'cover',
2304
+ display: 'block'
2305
+ }
2306
+ };
2307
+ const StructurePage = (_a) => {
2308
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
2309
+ 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"]);
2310
+ const [data, setData] = React.useState(null);
2311
+ const [loading, setLoading] = React.useState(true);
2312
+ const [error, setError] = React.useState(null);
2313
+ const [carouselIndex, setCarouselIndex] = React.useState(0);
2314
+ const heroVideoRef = React.useRef(null);
2315
+ const carouselVideoRefs = React.useRef([]);
2316
+ // 视频暂停状态管理
2317
+ const [isHeroVideoPaused, setIsHeroVideoPaused] = React.useState(false);
2318
+ const [carouselVideoPausedStates, setCarouselVideoPausedStates] = React.useState([]);
2319
+ // 从 schema 中获取 multiCTAConfig(优先使用 props 传入的)
2320
+ const { schema } = useEditor();
2321
+ const multiCTAConfig = React.useMemo(() => {
2322
+ var _a;
2323
+ return propMultiCTAConfig || ((_a = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _a === void 0 ? void 0 : _a.multiCTAConfig) || {};
2324
+ }, [propMultiCTAConfig, (_b = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _b === void 0 ? void 0 : _b.multiCTAConfig]);
2325
+ // 默认播放图标 URL(直接使用 CDN 地址作为后备)
2326
+ const DEFAULT_PAUSE_ICON = 'https://sxph5-uat.chatlabs.net/pb_static/06f28a2025c74c1cb49be6767316d827.png';
2327
+ // 获取视频播放图标
2328
+ const videoPlayIcon = React.useMemo(() => {
2329
+ var _a, _b;
2330
+ // 优先使用 props 传入的
2331
+ if (propVideoPlayIcon)
2332
+ return propVideoPlayIcon;
2333
+ // 然后使用 schema 配置的
2334
+ 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;
2335
+ if (configIcon) {
2336
+ // 如果是完整 URL,直接使用
2337
+ if (configIcon.startsWith('http://') || configIcon.startsWith('https://')) {
2338
+ return configIcon;
2339
+ }
2340
+ // 如果是相对路径,拼接当前域名
2341
+ if (configIcon.startsWith('/')) {
2342
+ return `${window.location.origin}${configIcon}`;
2343
+ }
2344
+ return configIcon;
2345
+ }
2346
+ // 最后使用默认图标
2347
+ return DEFAULT_PAUSE_ICON;
2348
+ }, [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]);
2349
+ // 处理 CTA 点击
2350
+ const handleCtaClick = React.useCallback((link, interaction, productData, ctaData) => {
2351
+ // 如果配置了交互设置,优先使用交互设置
2352
+ if (interaction) {
2353
+ const { linkType, popupType, popupAni } = interaction;
2354
+ if (linkType === 'popup' && popupType) {
2355
+ // 设置弹窗要显示的产品数据
2356
+ if (productData && typeof window !== 'undefined' && window.setPopupDetailData) {
2357
+ // 构造与原有系统一致的数据结构
2358
+ const popupData = {
2359
+ video: {
2360
+ bindProduct: productData,
2361
+ bindProducts: [productData],
2362
+ bindCta: ctaData
2363
+ }
2364
+ };
2365
+ window.setPopupDetailData(popupData);
2366
+ }
2367
+ // 打开弹窗 - 使用与现有系统一致的方式
2368
+ if (typeof window !== 'undefined' && window.sxpPopup) {
2369
+ // 如果有动画配置,传递动画参数;否则只传弹窗 ID
2370
+ if (popupAni && popupAni.name) {
2371
+ window.sxpPopup(popupType, popupAni);
2372
+ }
2373
+ else {
2374
+ window.sxpPopup(popupType);
2375
+ }
2376
+ }
2377
+ return;
2378
+ }
2379
+ }
2380
+ // 默认行为:打开外部链接
2381
+ if (link) {
2382
+ window.open(link, '_blank');
2383
+ }
2384
+ }, []);
2385
+ // 合并基础样式和编辑器配置的样式
2386
+ const mergeStyles = React.useCallback((baseStyle, configKey) => {
2387
+ if (!editorMode || !multiCTAConfig[configKey]) {
2388
+ return baseStyle;
2389
+ }
2390
+ const config = multiCTAConfig[configKey];
2391
+ // 定义允许的样式属性列表
2392
+ const styleKeys = [
2393
+ 'fontSize', 'color', 'textAlign', 'fontWeight',
2394
+ 'backgroundColor', 'padding', 'margin', 'borderRadius',
2395
+ 'showBorder', 'borderWidth', 'borderColor',
2396
+ 'buttonBackgroundColor', 'buttonTextColor', 'buttonWidth', 'buttonHeight'
2397
+ ];
2398
+ // 只处理样式相关的属性,忽略 interaction 等非样式属性
2399
+ const styleConfig = Object.keys(config)
2400
+ .filter(key => styleKeys.includes(key))
2401
+ .reduce((obj, key) => {
2402
+ obj[key] = config[key];
2403
+ return obj;
2404
+ }, {});
2405
+ // 如果配置中没有任何样式字段(只有 interaction),直接返回基础样式
2406
+ if (Object.keys(styleConfig).length === 0) {
2407
+ return baseStyle;
2408
+ }
2409
+ const customStyle = {};
2410
+ // 应用配置中的样式
2411
+ if (styleConfig.fontSize && typeof styleConfig.fontSize === 'number') {
2412
+ customStyle.fontSize = `${styleConfig.fontSize}px`;
2413
+ }
2414
+ if (styleConfig.color && typeof styleConfig.color === 'string') {
2415
+ customStyle.color = styleConfig.color;
2416
+ }
2417
+ if (styleConfig.textAlign && typeof styleConfig.textAlign === 'string') {
2418
+ customStyle.textAlign = styleConfig.textAlign;
2419
+ }
2420
+ if (styleConfig.fontWeight && typeof styleConfig.fontWeight === 'number') {
2421
+ customStyle.fontWeight = styleConfig.fontWeight;
2422
+ }
2423
+ if (styleConfig.backgroundColor && typeof styleConfig.backgroundColor === 'string') {
2424
+ customStyle.backgroundColor = styleConfig.backgroundColor;
2425
+ }
2426
+ if (styleConfig.padding && typeof styleConfig.padding === 'string') {
2427
+ customStyle.padding = styleConfig.padding;
2428
+ }
2429
+ if (styleConfig.margin && typeof styleConfig.margin === 'string') {
2430
+ customStyle.margin = styleConfig.margin;
2431
+ }
2432
+ if (styleConfig.borderRadius && typeof styleConfig.borderRadius === 'number') {
2433
+ customStyle.borderRadius = `${styleConfig.borderRadius}px`;
2434
+ }
2435
+ if (styleConfig.showBorder && styleConfig.borderWidth && typeof styleConfig.borderWidth === 'number') {
2436
+ customStyle.border = `${styleConfig.borderWidth}px solid ${styleConfig.borderColor || '#d9d9d9'}`;
2437
+ }
2438
+ // 按钮特殊样式
2439
+ if (styleConfig.buttonBackgroundColor && typeof styleConfig.buttonBackgroundColor === 'string') {
2440
+ customStyle.backgroundColor = styleConfig.buttonBackgroundColor;
2441
+ }
2442
+ if (styleConfig.buttonTextColor && typeof styleConfig.buttonTextColor === 'string') {
2443
+ customStyle.color = styleConfig.buttonTextColor;
2444
+ }
2445
+ if (styleConfig.buttonWidth && typeof styleConfig.buttonWidth === 'number') {
2446
+ customStyle.width = `${styleConfig.buttonWidth}px`;
2447
+ }
2448
+ if (styleConfig.buttonHeight && typeof styleConfig.buttonHeight === 'number') {
2449
+ customStyle.height = `${styleConfig.buttonHeight}px`;
2450
+ }
2451
+ return Object.assign(Object.assign({}, baseStyle), customStyle);
2452
+ }, [editorMode, multiCTAConfig]);
2453
+ // 渲染 CTA 按钮或模版组件
2454
+ const renderCTA = React.useCallback((buttonKey, ctaData, productData, fallbackStyle) => {
2455
+ var _a, _b, _c;
2456
+ if (!ctaData) {
2457
+ return null;
2458
+ }
2459
+ const config = multiCTAConfig[buttonKey];
2460
+ const templateType = config === null || config === void 0 ? void 0 : config.templateType;
2461
+ const interaction = config === null || config === void 0 ? void 0 : config.interaction;
2462
+ // 如果配置了模版类型,渲染对应的模版组件
2463
+ if (editorMode && templateType && RESOLVER$3[templateType]) {
2464
+ const TemplateComponent = RESOLVER$3[templateType];
2465
+ const templateExtend = TemplateComponent === null || TemplateComponent === void 0 ? void 0 : TemplateComponent.extend;
2466
+ if (templateExtend) {
2467
+ // 准备模版组件的 props
2468
+ 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);
2469
+ // 渲染模版组件
2470
+ return React.createElement(TemplateComponent, templateProps);
2471
+ }
2472
+ }
2473
+ // 默认渲染按钮
2474
+ 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));
2475
+ }, [multiCTAConfig, editorMode, handleCtaClick, mergeStyles, rest]);
2476
+ // 获取数据 - 只在组件挂载时执行一次
2477
+ React.useEffect(() => {
2478
+ // 重要:在 PB 编辑器模式下,propMultiCTAConfig 只是样式配置,不是数据源
2479
+ // 只有在 CMS 模式 (isCmsMode=false) 且 propMultiCTAConfig 包含实际数据时才跳过 API 调用
2480
+ // 判断是否包含实际数据:检查是否有 heroSection, carouselSection 等数据字段
2481
+ const hasActualData = propMultiCTAConfig && (propMultiCTAConfig.heroSection ||
2482
+ propMultiCTAConfig.carouselSection ||
2483
+ propMultiCTAConfig.highlightRevealSection ||
2484
+ propMultiCTAConfig.productGridSection ||
2485
+ propMultiCTAConfig.footerSection);
2486
+ if (editorMode && hasActualData && !isCmsMode) {
2487
+ setLoading(false);
2488
+ setError(null);
2489
+ // 使用传入的 multiCTAConfig 作为数据源
2490
+ setData(propMultiCTAConfig);
2491
+ return;
2492
+ }
2493
+ // 如果已经有数据了,且在编辑器模式下,不要重新请求
2494
+ if (editorMode && data && !isCmsMode) {
2495
+ return;
2496
+ }
2497
+ setLoading(true);
2498
+ setError(null);
2499
+ // 根据模式决定使用哪个接口
2500
+ let finalApiUrl = apiUrl;
2501
+ let bodyToSend = {};
2502
+ if (isCmsMode) {
2503
+ // CMS 模式:使用 /api/console/ad/multiCta/rec/detail 接口
2504
+ if (!storyId) {
2505
+ console.error('[StructurePage CMS Mode] storyId is required but not provided');
2506
+ setError('storyId is required in CMS mode');
2507
+ setLoading(false);
2508
+ return;
2509
+ }
2510
+ // 构建 CMS 接口的 URL 和请求体
2511
+ // apiUrl 应该是域名(如 http://localhost:8001),然后拼接 /api/console/ad/multiCta/rec/detail
2512
+ finalApiUrl = `${apiUrl}/api/console/ad/multiCta/rec/detail`;
2513
+ bodyToSend = { storyId };
2514
+ }
2515
+ else {
2516
+ // 普通模式:使用原有的 /api/v1/recommend/list 接口
2517
+ const defaultBody = {
2518
+ maxSize: 20,
2519
+ defaultSize: 10,
2520
+ type: 'story'
2521
+ };
2522
+ bodyToSend = requestBody ? Object.assign(Object.assign({}, defaultBody), requestBody) : defaultBody;
2523
+ }
2524
+ // 构建请求头
2525
+ const headers = {
2526
+ 'Content-Type': 'application/json'
2527
+ };
2528
+ if (isCmsMode) {
2529
+ // CMS 模式:使用自定义 headers(如果有传入)
2530
+ if (customHeaders) {
2531
+ Object.assign(headers, customHeaders);
2532
+ }
2533
+ }
2534
+ else {
2535
+ // 普通模式:从 requestBody 或 bodyToSend 中提取 BFF headers
2536
+ if (bodyToSend['x-app-id']) {
2537
+ headers['x-app-id'] = bodyToSend['x-app-id'];
2538
+ delete bodyToSend['x-app-id'];
2539
+ }
2540
+ if (bodyToSend['x-user-id']) {
2541
+ headers['x-user-id'] = bodyToSend['x-user-id'];
2542
+ delete bodyToSend['x-user-id'];
2543
+ }
2544
+ if (bodyToSend['tenant-id']) {
2545
+ headers['tenant-id'] = bodyToSend['tenant-id'];
2546
+ delete bodyToSend['tenant-id'];
2547
+ }
2548
+ }
2549
+ fetch(finalApiUrl, {
2550
+ method: 'POST',
2551
+ headers,
2552
+ body: JSON.stringify(bodyToSend),
2553
+ credentials: 'include'
2554
+ })
2555
+ .then((res) => {
2556
+ if (!res.ok) {
2557
+ throw new Error(`HTTP error! status: ${res.status}`);
2558
+ }
2559
+ return res.json();
2560
+ })
2561
+ .then((result) => {
2562
+ var _a, _b, _c, _d;
2563
+ if (result.code === '0' || result.code === '00000') {
2564
+ // 判断数据结构:CMS 模式和普通模式可能不同
2565
+ let multiCtaData = null;
2566
+ if (isCmsMode) {
2567
+ // CMS 模式:data.multiCta
2568
+ multiCtaData = (_a = result.data) === null || _a === void 0 ? void 0 : _a.multiCta;
2569
+ }
2570
+ else {
2571
+ // 普通模式:data.recList[0].multiCta
2572
+ 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;
2573
+ }
2574
+ if (multiCtaData) {
2575
+ setData(multiCtaData);
2576
+ }
2577
+ else {
2578
+ console.error('[StructurePage] No multiCta data found in response:', result);
2579
+ setError(result.message || 'No multiCta data found');
2580
+ }
2581
+ }
2582
+ else {
2583
+ setError(result.message || 'Failed to load data');
2584
+ }
2585
+ setLoading(false);
2586
+ })
2587
+ .catch((err) => {
2588
+ console.error('[StructurePage] Failed to fetch data:', {
2589
+ error: err,
2590
+ message: err.message,
2591
+ url: finalApiUrl,
2592
+ body: bodyToSend,
2593
+ isCmsMode,
2594
+ storyId
2595
+ });
2596
+ setError(err.message || 'Network error');
2597
+ setLoading(false);
2598
+ });
2599
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2600
+ }, [apiUrl, isCmsMode, storyId, customHeaders]);
2601
+ // 注意:移除了 editorMode 和 propMultiCTAConfig 依赖,因为:
2602
+ // 1. editorMode 和 propMultiCTAConfig 在编辑器中频繁变化
2603
+ // 2. propMultiCTAConfig 只是样式配置,不是数据源
2604
+ // 3. 数据获取只应该在组件挂载时执行一次(除非 apiUrl/storyId 等关键参数变化)
2605
+ // Hero Section 视频自动播放
2606
+ React.useEffect(() => {
2607
+ var _a;
2608
+ if (heroVideoRef.current && ((_a = data === null || data === void 0 ? void 0 : data.heroSection) === null || _a === void 0 ? void 0 : _a.url)) {
2609
+ heroVideoRef.current.play().catch((err) => console.log('Video autoplay failed:', err));
2610
+ setIsHeroVideoPaused(false);
2611
+ }
2612
+ }, [data === null || data === void 0 ? void 0 : data.heroSection]);
2613
+ // 初始化 carousel 视频暂停状态
2614
+ React.useEffect(() => {
2615
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2616
+ // carousel 视频默认不自动播放,所以初始状态应该是暂停(true)
2617
+ setCarouselVideoPausedStates(new Array(data.carouselSection.length).fill(true));
2618
+ }
2619
+ }, [data === null || data === void 0 ? void 0 : data.carouselSection]);
2620
+ // Hero 视频点击处理
2621
+ const handleHeroVideoClick = React.useCallback(() => {
2622
+ if (heroVideoRef.current) {
2623
+ if (heroVideoRef.current.paused) {
2624
+ heroVideoRef.current.play();
2625
+ setIsHeroVideoPaused(false);
2626
+ }
2627
+ else {
2628
+ heroVideoRef.current.pause();
2629
+ setIsHeroVideoPaused(true);
2630
+ }
2631
+ }
2632
+ }, []);
2633
+ // Carousel 视频点击处理
2634
+ const handleCarouselVideoClick = React.useCallback((index) => {
2635
+ const videoRef = carouselVideoRefs.current[index];
2636
+ if (videoRef) {
2637
+ if (videoRef.paused) {
2638
+ videoRef.play();
2639
+ setCarouselVideoPausedStates(prev => {
2640
+ const newStates = [...prev];
2641
+ newStates[index] = false;
2642
+ return newStates;
2643
+ });
2644
+ }
2645
+ else {
2646
+ videoRef.pause();
2647
+ setCarouselVideoPausedStates(prev => {
2648
+ const newStates = [...prev];
2649
+ newStates[index] = true;
2650
+ return newStates;
2651
+ });
2652
+ }
2653
+ }
2654
+ }, []);
2655
+ // Carousel 导航
2656
+ const handleCarouselPrev = () => {
2657
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2658
+ setCarouselIndex((prev) => (prev === 0 ? data.carouselSection.length - 1 : prev - 1));
2659
+ }
2660
+ };
2661
+ const handleCarouselNext = () => {
2662
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2663
+ setCarouselIndex((prev) => (prev === data.carouselSection.length - 1 ? 0 : prev + 1));
2664
+ }
2665
+ };
2666
+ if (loading) {
2667
+ 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..."));
2668
+ }
2669
+ if (error) {
2670
+ 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' }) },
2671
+ React.createElement("div", { style: { fontSize: '18px', marginBottom: '10px' } }, "\u26A0\uFE0F Error"),
2672
+ React.createElement("div", { style: { fontSize: '14px', opacity: 0.8 } }, error)));
2673
+ }
2674
+ if (!data) {
2675
+ 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"));
2676
+ }
2677
+ return (React.createElement("div", { className: className, style: Object.assign(Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth }), containerStyle) },
2678
+ data.heroSection && (React.createElement("div", { style: baseStyles.heroSection },
2679
+ data.heroSection.text && (React.createElement("div", { style: mergeStyles(baseStyles.heroTopText, 'heroTopText') }, data.heroSection.text)),
2680
+ React.createElement("div", { style: baseStyles.heroImageContainer },
2681
+ data.heroSection.url ? (React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: handleHeroVideoClick },
2682
+ React.createElement("video", { ref: heroVideoRef, src: data.heroSection.url, style: baseStyles.heroVideo, autoPlay: true, muted: true, loop: true, playsInline: true, controls: false }),
2683
+ 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,
2684
+ 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))))),
2685
+ data.carouselSection && data.carouselSection.length > 0 && (React.createElement("div", { style: mergeStyles(baseStyles.carouselSection, 'carouselSection') },
2686
+ React.createElement("div", { style: baseStyles.carouselImageContainer },
2687
+ React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.carouselContainer), { transform: `translateX(-${carouselIndex * 100}%)` }) }, data.carouselSection.map((item, index) => {
2688
+ var _a;
2689
+ 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) },
2690
+ React.createElement("video", { ref: (el) => {
2691
+ carouselVideoRefs.current[index] = el;
2692
+ }, src: item.url, style: baseStyles.carouselVideo, muted: true, loop: true, playsInline: true, controls: false }),
2693
+ 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));
2694
+ })),
2695
+ React.createElement("button", { style: Object.assign(Object.assign({}, baseStyles.arrowButton), { left: '10px' }), onClick: handleCarouselPrev }, "\u2039"),
2696
+ React.createElement("button", { style: Object.assign(Object.assign({}, baseStyles.arrowButton), { right: '10px' }), onClick: handleCarouselNext }, "\u203A")),
2697
+ React.createElement("div", { style: mergeStyles(baseStyles.carouselInfoSection, 'carouselSection') },
2698
+ ((_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)),
2699
+ 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)))),
2700
+ data.highlightRevealSection && (React.createElement("div", { style: mergeStyles(baseStyles.highlightSection, 'highlightSection') },
2701
+ React.createElement("div", { style: baseStyles.highlightImageContainer },
2702
+ React.createElement("img", { src: data.highlightRevealSection.landingImageUrl || data.highlightRevealSection.cover, alt: data.highlightRevealSection.title, style: baseStyles.highlightImage })),
2703
+ React.createElement("div", { style: mergeStyles(baseStyles.highlightInfoSection, 'highlightSection') },
2704
+ React.createElement("div", { style: mergeStyles(baseStyles.highlightTitle, 'highlightSection') }, data.highlightRevealSection.title),
2705
+ renderCTA('highlightButton', data.highlightRevealSection.bindCta, data.highlightRevealSection, baseStyles.highlightButton)))),
2706
+ data.productGridSection && data.productGridSection.length > 0 && (React.createElement("div", { style: mergeStyles(baseStyles.productGrid, 'productGrid') }, (() => {
2707
+ // 创建一个6格的网格 (3行 x 2列),根据position放置产品
2708
+ const gridItems = [null, null, null, null, null, null];
2709
+ // 创建产品索引映射表:gridIndex -> 产品在数据数组中的索引(从1开始)
2710
+ const productIndexMap = {};
2711
+ data.productGridSection.forEach((product, idx) => {
2712
+ var _a;
2713
+ const pos = (_a = product.position) === null || _a === void 0 ? void 0 : _a.toLowerCase();
2714
+ let gridIndex = -1;
2715
+ if (pos === 'top_right') {
2716
+ gridIndex = 1; // 第一行右侧
2717
+ }
2718
+ else if (pos === 'top_left') {
2719
+ gridIndex = 0; // 第一行左侧
2720
+ }
2721
+ else if (pos === 'center_left') {
2722
+ gridIndex = 2; // 第二行左侧
2723
+ }
2724
+ else if (pos === 'center_right') {
2725
+ gridIndex = 3; // 第二行右侧
2726
+ }
2727
+ else if (pos === 'bottom_left') {
2728
+ gridIndex = 4; // 第三行左侧
2729
+ }
2730
+ else if (pos === 'bottom_right') {
2731
+ gridIndex = 5; // 第三行右侧
2732
+ }
2733
+ if (gridIndex >= 0) {
2734
+ gridItems[gridIndex] = product;
2735
+ // 映射:网格位置 -> 产品序号(基于数据数组的顺序,从1开始)
2736
+ productIndexMap[gridIndex] = idx + 1;
2737
+ }
2738
+ });
2739
+ return gridItems.map((product, gridIndex) => {
2740
+ // 使用产品在数据数组中的实际索引来确定 buttonKey
2741
+ const productDataIndex = productIndexMap[gridIndex];
2742
+ const buttonKey = `productButton${productDataIndex || gridIndex + 1}`;
2743
+ 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,
2744
+ React.createElement("div", { style: baseStyles.productImageContainer },
2745
+ React.createElement("img", { src: product.landingImageUrl || product.cover,
2746
+ // alt={product.title}
2747
+ style: baseStyles.productImage })),
2748
+ product.bindCta && (React.createElement("div", { style: baseStyles.productCtaContainer }, renderCTA(buttonKey, product.bindCta, product, baseStyles.productButton))))) : (
2749
+ // 空格子
2750
+ React.createElement("div", { style: { width: '100%', paddingBottom: '100%' } }))));
2751
+ });
2752
+ })())),
2753
+ data.footerSection && (React.createElement("div", { style: mergeStyles(baseStyles.footerSection, 'footerSection') },
2754
+ React.createElement("div", { style: mergeStyles(baseStyles.footerInfoSection, 'footerSection') }, renderCTA('footerButton', data.footerSection.bindCta, data.footerSection, baseStyles.footerButton)),
2755
+ React.createElement("div", { style: baseStyles.footerImageContainer },
2756
+ React.createElement("img", { src: data.footerSection.landingImageUrl || data.footerSection.cover, alt: data.footerSection.title, style: baseStyles.footerImage }))))));
2757
+ };
2758
+
1944
2759
  var index$3 = /*#__PURE__*/Object.freeze({
1945
2760
  __proto__: null,
1946
- EditorCore: EditorCore
2761
+ EditorCore: EditorCore,
2762
+ StructurePage: StructurePage
1947
2763
  });
1948
2764
 
1949
2765
  var interactionRender$h = [
@@ -3892,9 +4708,8 @@
3892
4708
  allSlidesSize += slideSizeValue + (spaceBetween || 0);
3893
4709
  });
3894
4710
  allSlidesSize -= spaceBetween;
3895
- const offsetSize = (params.slidesOffsetBefore || 0) + (params.slidesOffsetAfter || 0);
3896
- if (allSlidesSize + offsetSize < swiperSize) {
3897
- const allSlidesOffset = (swiperSize - allSlidesSize - offsetSize) / 2;
4711
+ if (allSlidesSize < swiperSize) {
4712
+ const allSlidesOffset = (swiperSize - allSlidesSize) / 2;
3898
4713
  snapGrid.forEach((snap, snapIndex) => {
3899
4714
  snapGrid[snapIndex] = snap - allSlidesOffset;
3900
4715
  });
@@ -3998,13 +4813,6 @@
3998
4813
  }
3999
4814
  }
4000
4815
 
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
4816
  function updateSlidesProgress(translate) {
4009
4817
  if (translate === void 0) {
4010
4818
  translate = this && this.translate || 0;
@@ -4020,6 +4828,11 @@
4020
4828
  if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset();
4021
4829
  let offsetCenter = -translate;
4022
4830
  if (rtl) offsetCenter = translate;
4831
+
4832
+ // Visible Slides
4833
+ slides.forEach(slideEl => {
4834
+ slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass);
4835
+ });
4023
4836
  swiper.visibleSlidesIndexes = [];
4024
4837
  swiper.visibleSlides = [];
4025
4838
  let spaceBetween = params.spaceBetween;
@@ -4043,9 +4856,11 @@
4043
4856
  if (isVisible) {
4044
4857
  swiper.visibleSlides.push(slide);
4045
4858
  swiper.visibleSlidesIndexes.push(i);
4859
+ slides[i].classList.add(params.slideVisibleClass);
4860
+ }
4861
+ if (isFullyVisible) {
4862
+ slides[i].classList.add(params.slideFullyVisibleClass);
4046
4863
  }
4047
- toggleSlideClasses$1(slide, isVisible, params.slideVisibleClass);
4048
- toggleSlideClasses$1(slide, isFullyVisible, params.slideFullyVisibleClass);
4049
4864
  slide.progress = rtl ? -slideProgress : slideProgress;
4050
4865
  slide.originalProgress = rtl ? -originalSlideProgress : originalSlideProgress;
4051
4866
  }
@@ -4114,13 +4929,6 @@
4114
4929
  swiper.emit('progress', progress);
4115
4930
  }
4116
4931
 
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
4932
  function updateSlidesClasses() {
4125
4933
  const swiper = this;
4126
4934
  const {
@@ -4134,6 +4942,9 @@
4134
4942
  const getFilteredSlide = selector => {
4135
4943
  return elementChildren(slidesEl, `.${params.slideClass}${selector}, swiper-slide${selector}`)[0];
4136
4944
  };
4945
+ slides.forEach(slideEl => {
4946
+ slideEl.classList.remove(params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
4947
+ });
4137
4948
  let activeSlide;
4138
4949
  let prevSlide;
4139
4950
  let nextSlide;
@@ -4156,25 +4967,35 @@
4156
4967
  }
4157
4968
  }
4158
4969
  if (activeSlide) {
4159
- if (!gridEnabled) {
4970
+ // Active classes
4971
+ activeSlide.classList.add(params.slideActiveClass);
4972
+ if (gridEnabled) {
4973
+ if (nextSlide) {
4974
+ nextSlide.classList.add(params.slideNextClass);
4975
+ }
4976
+ if (prevSlide) {
4977
+ prevSlide.classList.add(params.slidePrevClass);
4978
+ }
4979
+ } else {
4160
4980
  // Next Slide
4161
4981
  nextSlide = elementNextAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
4162
4982
  if (params.loop && !nextSlide) {
4163
4983
  nextSlide = slides[0];
4164
4984
  }
4985
+ if (nextSlide) {
4986
+ nextSlide.classList.add(params.slideNextClass);
4987
+ }
4165
4988
 
4166
4989
  // Prev Slide
4167
4990
  prevSlide = elementPrevAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
4168
4991
  if (params.loop && !prevSlide === 0) {
4169
4992
  prevSlide = slides[slides.length - 1];
4170
4993
  }
4994
+ if (prevSlide) {
4995
+ prevSlide.classList.add(params.slidePrevClass);
4996
+ }
4171
4997
  }
4172
4998
  }
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
4999
  swiper.emitSlidesClasses();
4179
5000
  }
4180
5001
 
@@ -4552,7 +5373,6 @@
4552
5373
  swiper.wrapperEl.removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);
4553
5374
  swiper.onTranslateToWrapperTransitionEnd = null;
4554
5375
  delete swiper.onTranslateToWrapperTransitionEnd;
4555
- swiper.animating = false;
4556
5376
  if (runCallbacks) {
4557
5377
  swiper.emit('transitionEnd');
4558
5378
  }
@@ -4660,6 +5480,9 @@
4660
5480
  if (index === void 0) {
4661
5481
  index = 0;
4662
5482
  }
5483
+ if (speed === void 0) {
5484
+ speed = this.params.speed;
5485
+ }
4663
5486
  if (runCallbacks === void 0) {
4664
5487
  runCallbacks = true;
4665
5488
  }
@@ -4679,12 +5502,9 @@
4679
5502
  wrapperEl,
4680
5503
  enabled
4681
5504
  } = swiper;
4682
- if (!enabled && !internal && !initial || swiper.destroyed || swiper.animating && params.preventInteractionOnTransition) {
5505
+ if (swiper.animating && params.preventInteractionOnTransition || !enabled && !internal && !initial || swiper.destroyed) {
4683
5506
  return false;
4684
5507
  }
4685
- if (typeof speed === 'undefined') {
4686
- speed = swiper.params.speed;
4687
- }
4688
5508
  const skip = Math.min(swiper.params.slidesPerGroupSkip, slideIndex);
4689
5509
  let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup);
4690
5510
  if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
@@ -4811,6 +5631,9 @@
4811
5631
  if (index === void 0) {
4812
5632
  index = 0;
4813
5633
  }
5634
+ if (speed === void 0) {
5635
+ speed = this.params.speed;
5636
+ }
4814
5637
  if (runCallbacks === void 0) {
4815
5638
  runCallbacks = true;
4816
5639
  }
@@ -4820,9 +5643,6 @@
4820
5643
  }
4821
5644
  const swiper = this;
4822
5645
  if (swiper.destroyed) return;
4823
- if (typeof speed === 'undefined') {
4824
- speed = swiper.params.speed;
4825
- }
4826
5646
  const gridEnabled = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1;
4827
5647
  let newIndex = index;
4828
5648
  if (swiper.params.loop) {
@@ -4854,9 +5674,6 @@
4854
5674
  if (centeredSlides) {
4855
5675
  needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2);
4856
5676
  }
4857
- if (internal && centeredSlides && swiper.params.slidesPerView !== 'auto' && !gridEnabled) {
4858
- needLoopFix = false;
4859
- }
4860
5677
  if (needLoopFix) {
4861
5678
  const direction = centeredSlides ? targetSlideIndex < swiper.activeIndex ? 'prev' : 'next' : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView ? 'next' : 'prev';
4862
5679
  swiper.loopFix({
@@ -4882,6 +5699,9 @@
4882
5699
 
4883
5700
  /* eslint no-unused-vars: "off" */
4884
5701
  function slideNext(speed, runCallbacks, internal) {
5702
+ if (speed === void 0) {
5703
+ speed = this.params.speed;
5704
+ }
4885
5705
  if (runCallbacks === void 0) {
4886
5706
  runCallbacks = true;
4887
5707
  }
@@ -4892,9 +5712,6 @@
4892
5712
  animating
4893
5713
  } = swiper;
4894
5714
  if (!enabled || swiper.destroyed) return swiper;
4895
- if (typeof speed === 'undefined') {
4896
- speed = swiper.params.speed;
4897
- }
4898
5715
  let perGroup = params.slidesPerGroup;
4899
5716
  if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {
4900
5717
  perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1);
@@ -4923,6 +5740,9 @@
4923
5740
 
4924
5741
  /* eslint no-unused-vars: "off" */
4925
5742
  function slidePrev(speed, runCallbacks, internal) {
5743
+ if (speed === void 0) {
5744
+ speed = this.params.speed;
5745
+ }
4926
5746
  if (runCallbacks === void 0) {
4927
5747
  runCallbacks = true;
4928
5748
  }
@@ -4936,9 +5756,6 @@
4936
5756
  animating
4937
5757
  } = swiper;
4938
5758
  if (!enabled || swiper.destroyed) return swiper;
4939
- if (typeof speed === 'undefined') {
4940
- speed = swiper.params.speed;
4941
- }
4942
5759
  const isVirtual = swiper.virtual && params.virtual.enabled;
4943
5760
  if (params.loop) {
4944
5761
  if (animating && !isVirtual && params.loopPreventsSliding) return false;
@@ -4991,19 +5808,22 @@
4991
5808
 
4992
5809
  /* eslint no-unused-vars: "off" */
4993
5810
  function slideReset(speed, runCallbacks, internal) {
5811
+ if (speed === void 0) {
5812
+ speed = this.params.speed;
5813
+ }
4994
5814
  if (runCallbacks === void 0) {
4995
5815
  runCallbacks = true;
4996
5816
  }
4997
5817
  const swiper = this;
4998
5818
  if (swiper.destroyed) return;
4999
- if (typeof speed === 'undefined') {
5000
- speed = swiper.params.speed;
5001
- }
5002
5819
  return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);
5003
5820
  }
5004
5821
 
5005
5822
  /* eslint no-unused-vars: "off" */
5006
5823
  function slideToClosest(speed, runCallbacks, internal, threshold) {
5824
+ if (speed === void 0) {
5825
+ speed = this.params.speed;
5826
+ }
5007
5827
  if (runCallbacks === void 0) {
5008
5828
  runCallbacks = true;
5009
5829
  }
@@ -5012,9 +5832,6 @@
5012
5832
  }
5013
5833
  const swiper = this;
5014
5834
  if (swiper.destroyed) return;
5015
- if (typeof speed === 'undefined') {
5016
- speed = swiper.params.speed;
5017
- }
5018
5835
  let index = swiper.activeIndex;
5019
5836
  const skip = Math.min(swiper.params.slidesPerGroupSkip, index);
5020
5837
  const snapIndex = skip + Math.floor((index - skip) / swiper.params.slidesPerGroup);
@@ -5649,7 +6466,7 @@
5649
6466
  data.startMoving = true;
5650
6467
  }
5651
6468
  }
5652
- if (data.isScrolling || e.type === 'touchmove' && data.preventTouchMoveFromPointerMove) {
6469
+ if (data.isScrolling) {
5653
6470
  data.isTouched = false;
5654
6471
  return;
5655
6472
  }
@@ -5691,10 +6508,7 @@
5691
6508
  if (swiper.animating) {
5692
6509
  const evt = new window.CustomEvent('transitionend', {
5693
6510
  bubbles: true,
5694
- cancelable: true,
5695
- detail: {
5696
- bySwiperTouchMove: true
5697
- }
6511
+ cancelable: true
5698
6512
  });
5699
6513
  swiper.wrapperEl.dispatchEvent(evt);
5700
6514
  }
@@ -6088,7 +6902,6 @@
6088
6902
  const capture = !!params.nested;
6089
6903
  const domMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';
6090
6904
  const swiperMethod = method;
6091
- if (!el || typeof el === 'string') return;
6092
6905
 
6093
6906
  // Touch Events
6094
6907
  document[domMethod]('touchstart', swiper.onDocumentTouchStart, {
@@ -6197,8 +7010,6 @@
6197
7010
  const breakpointParams = breakpointOnlyParams || swiper.originalParams;
6198
7011
  const wasMultiRow = isGridEnabled(swiper, params);
6199
7012
  const isMultiRow = isGridEnabled(swiper, breakpointParams);
6200
- const wasGrabCursor = swiper.params.grabCursor;
6201
- const isGrabCursor = breakpointParams.grabCursor;
6202
7013
  const wasEnabled = params.enabled;
6203
7014
  if (wasMultiRow && !isMultiRow) {
6204
7015
  el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`);
@@ -6210,11 +7021,6 @@
6210
7021
  }
6211
7022
  swiper.emitContainerClasses();
6212
7023
  }
6213
- if (wasGrabCursor && !isGrabCursor) {
6214
- swiper.unsetGrabCursor();
6215
- } else if (!wasGrabCursor && isGrabCursor) {
6216
- swiper.setGrabCursor();
6217
- }
6218
7024
 
6219
7025
  // Toggle navigation, pagination, scrollbar
6220
7026
  ['navigation', 'pagination', 'scrollbar'].forEach(prop => {
@@ -6365,7 +7171,6 @@
6365
7171
  el,
6366
7172
  classNames
6367
7173
  } = swiper;
6368
- if (!el || typeof el === 'string') return;
6369
7174
  el.classList.remove(...classNames);
6370
7175
  swiper.emitContainerClasses();
6371
7176
  }
@@ -7130,12 +7935,8 @@
7130
7935
  // Cleanup styles
7131
7936
  if (cleanStyles) {
7132
7937
  swiper.removeClasses();
7133
- if (el && typeof el !== 'string') {
7134
- el.removeAttribute('style');
7135
- }
7136
- if (wrapperEl) {
7137
- wrapperEl.removeAttribute('style');
7138
- }
7938
+ el.removeAttribute('style');
7939
+ wrapperEl.removeAttribute('style');
7139
7940
  if (slides && slides.length) {
7140
7941
  slides.forEach(slideEl => {
7141
7942
  slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
@@ -7151,9 +7952,7 @@
7151
7952
  swiper.off(eventName);
7152
7953
  });
7153
7954
  if (deleteInstance !== false) {
7154
- if (swiper.el && typeof swiper.el !== 'string') {
7155
- swiper.el.swiper = null;
7156
- }
7955
+ swiper.el.swiper = null;
7157
7956
  deleteProps(swiper);
7158
7957
  }
7159
7958
  swiper.destroyed = true;
@@ -7547,7 +8346,7 @@
7547
8346
  };
7548
8347
 
7549
8348
  /**
7550
- * Swiper React 11.1.4
8349
+ * Swiper React 11.0.7
7551
8350
  * Most modern mobile touch slider and framework with hardware accelerated transitions
7552
8351
  * https://swiperjs.com
7553
8352
  *
@@ -7555,7 +8354,7 @@
7555
8354
  *
7556
8355
  * Released under the MIT License
7557
8356
  *
7558
- * Released on: May 30, 2024
8357
+ * Released on: February 27, 2024
7559
8358
  */
7560
8359
 
7561
8360
 
@@ -8482,10 +9281,8 @@
8482
9281
  }
8483
9282
  if (el) {
8484
9283
  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) {
9284
+ if (swiper.params.uniqueNavElements && typeof el === 'string' && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {
8486
9285
  res = swiper.el.querySelector(el);
8487
- } else if (res && res.length === 1) {
8488
- res = res[0];
8489
9286
  }
8490
9287
  }
8491
9288
  if (el && !res) return el;
@@ -8607,14 +9404,7 @@
8607
9404
  nextEl = makeElementsArray(nextEl);
8608
9405
  prevEl = makeElementsArray(prevEl);
8609
9406
  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) {
9407
+ if (swiper.params.navigation.hideOnClick && !prevEl.includes(targetEl) && !nextEl.includes(targetEl)) {
8618
9408
  if (swiper.pagination && swiper.params.pagination && swiper.params.pagination.clickable && (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) return;
8619
9409
  let isHidden;
8620
9410
  if (nextEl.length) {
@@ -9270,7 +10060,7 @@
9270
10060
  dragEl
9271
10061
  } = scrollbar;
9272
10062
  if (!isTouched) return;
9273
- if (e.preventDefault && e.cancelable) e.preventDefault();else e.returnValue = false;
10063
+ if (e.preventDefault) e.preventDefault();else e.returnValue = false;
9274
10064
  setDragPosition(e);
9275
10065
  wrapperEl.style.transitionDuration = '0ms';
9276
10066
  el.style.transitionDuration = '0ms';
@@ -9481,9 +10271,6 @@
9481
10271
  clicked: false
9482
10272
  };
9483
10273
  let liveRegion = null;
9484
- let preventFocusHandler;
9485
- let focusTargetSlideEl;
9486
- let visibilityChangedTimestamp = new Date().getTime();
9487
10274
  function notify(message) {
9488
10275
  const notification = liveRegion;
9489
10276
  if (notification.length === 0) return;
@@ -9564,28 +10351,24 @@
9564
10351
  if (swiper.pagination && swiper.pagination.el && (targetEl === swiper.pagination.el || swiper.pagination.el.contains(e.target))) {
9565
10352
  if (!e.target.matches(classesToSelector(swiper.params.pagination.bulletClass))) return;
9566
10353
  }
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
- }
10354
+ if (swiper.navigation && swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl) {
10355
+ if (!(swiper.isEnd && !swiper.params.loop)) {
10356
+ swiper.slideNext();
9579
10357
  }
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
- }
10358
+ if (swiper.isEnd) {
10359
+ notify(params.lastSlideMessage);
10360
+ } else {
10361
+ notify(params.nextSlideMessage);
10362
+ }
10363
+ }
10364
+ if (swiper.navigation && swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl) {
10365
+ if (!(swiper.isBeginning && !swiper.params.loop)) {
10366
+ swiper.slidePrev();
10367
+ }
10368
+ if (swiper.isBeginning) {
10369
+ notify(params.firstSlideMessage);
10370
+ } else {
10371
+ notify(params.prevSlideMessage);
9589
10372
  }
9590
10373
  }
9591
10374
  if (swiper.pagination && targetEl.matches(classesToSelector(swiper.params.pagination.bulletClass))) {
@@ -9650,14 +10433,10 @@
9650
10433
  addElLabel(el, message);
9651
10434
  addElControls(el, wrapperId);
9652
10435
  };
9653
- const handlePointerDown = e => {
9654
- if (focusTargetSlideEl && focusTargetSlideEl !== e.target && !focusTargetSlideEl.contains(e.target)) {
9655
- preventFocusHandler = true;
9656
- }
10436
+ const handlePointerDown = () => {
9657
10437
  swiper.a11y.clicked = true;
9658
10438
  };
9659
10439
  const handlePointerUp = () => {
9660
- preventFocusHandler = false;
9661
10440
  requestAnimationFrame(() => {
9662
10441
  requestAnimationFrame(() => {
9663
10442
  if (!swiper.destroyed) {
@@ -9666,15 +10445,10 @@
9666
10445
  });
9667
10446
  });
9668
10447
  };
9669
- const onVisibilityChange = e => {
9670
- visibilityChangedTimestamp = new Date().getTime();
9671
- };
9672
10448
  const handleFocus = e => {
9673
10449
  if (swiper.a11y.clicked) return;
9674
- if (new Date().getTime() - visibilityChangedTimestamp < 100) return;
9675
10450
  const slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`);
9676
10451
  if (!slideEl || !swiper.slides.includes(slideEl)) return;
9677
- focusTargetSlideEl = slideEl;
9678
10452
  const isActive = swiper.slides.indexOf(slideEl) === swiper.activeIndex;
9679
10453
  const isVisible = swiper.params.watchSlidesProgress && swiper.visibleSlides && swiper.visibleSlides.includes(slideEl);
9680
10454
  if (isActive || isVisible) return;
@@ -9684,15 +10458,7 @@
9684
10458
  } else {
9685
10459
  swiper.el.scrollTop = 0;
9686
10460
  }
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
- });
10461
+ swiper.slideTo(swiper.slides.indexOf(slideEl), 0);
9696
10462
  };
9697
10463
  const initSlides = () => {
9698
10464
  const params = swiper.params.a11y;
@@ -9757,9 +10523,6 @@
9757
10523
  }
9758
10524
 
9759
10525
  // Tab focus
9760
- const document = getDocument();
9761
- document.addEventListener('visibilitychange', onVisibilityChange);
9762
- swiper.el.addEventListener('focus', handleFocus, true);
9763
10526
  swiper.el.addEventListener('focus', handleFocus, true);
9764
10527
  swiper.el.addEventListener('pointerdown', handlePointerDown, true);
9765
10528
  swiper.el.addEventListener('pointerup', handlePointerUp, true);
@@ -9786,14 +10549,11 @@
9786
10549
  el.removeEventListener('keydown', onEnterOrSpaceKey);
9787
10550
  });
9788
10551
  }
9789
- const document = getDocument();
9790
- document.removeEventListener('visibilitychange', onVisibilityChange);
10552
+
9791
10553
  // 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
- }
10554
+ swiper.el.removeEventListener('focus', handleFocus, true);
10555
+ swiper.el.removeEventListener('pointerdown', handlePointerDown, true);
10556
+ swiper.el.removeEventListener('pointerup', handlePointerUp, true);
9797
10557
  }
9798
10558
  on('beforeInit', () => {
9799
10559
  liveRegion = createElement('span', swiper.params.a11y.notificationClass);
@@ -9865,7 +10625,7 @@
9865
10625
  if (!swiper || swiper.destroyed || !swiper.wrapperEl) return;
9866
10626
  if (e.target !== swiper.wrapperEl) return;
9867
10627
  swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd);
9868
- if (pausedByPointerEnter || e.detail && e.detail.bySwiperTouchMove) {
10628
+ if (pausedByPointerEnter) {
9869
10629
  return;
9870
10630
  }
9871
10631
  resume();
@@ -10036,10 +10796,8 @@
10036
10796
  }
10037
10797
  };
10038
10798
  const detachMouseEvents = () => {
10039
- if (swiper.el && typeof swiper.el !== 'string') {
10040
- swiper.el.removeEventListener('pointerenter', onPointerEnter);
10041
- swiper.el.removeEventListener('pointerleave', onPointerLeave);
10042
- }
10799
+ swiper.el.removeEventListener('pointerenter', onPointerEnter);
10800
+ swiper.el.removeEventListener('pointerleave', onPointerLeave);
10043
10801
  };
10044
10802
  const attachDocumentEvents = () => {
10045
10803
  const document = getDocument();
@@ -10377,49 +11135,6 @@
10377
11135
  };
10378
11136
  var Scroll$1 = React.memo(Scroll);
10379
11137
 
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
11138
  const CommodityGroup = ({ products, data, defImg, style, onCLick, popupDetailData, check }) => {
10424
11139
  var _a;
10425
11140
  const { productView } = useEventReport();
@@ -10509,13 +11224,13 @@
10509
11224
  styleElement.id = 'onetrust-pc-sdk';
10510
11225
  styleElement.setAttribute('type', 'text/css');
10511
11226
  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
- }
11227
+ const css = `
11228
+ #onetrust-pc-sdk {
11229
+ height: ${finalHeight}px !important;
11230
+ }
11231
+ #onetrust-pc-sdk #ot-pc-content{
11232
+ bottom: ${b}px !important;
11233
+ }
10519
11234
  `;
10520
11235
  styleElement.textContent = css;
10521
11236
  }
@@ -11062,10 +11777,10 @@
11062
11777
  __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
11778
  } }),
11064
11779
  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
11780
+ 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
11781
+ bold and avant-garde visual design interprets the emotional bond connecting my heart. The Tiffany Lock
11782
+ collection is unisex and is inspired by the padlock pattern found in the Tiffany Antique Collection. This
11783
+ necklace features a stylish and eye-catching oval clasp chain decorated with a lock pattern. Crafted from
11069
11784
  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
11785
  };
11071
11786
  const renderBtn = () => {
@@ -12064,7 +12779,7 @@
12064
12779
  const productInfoText = ({ isPost }) => {
12065
12780
  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
12781
  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
12782
+ `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
12783
  Made in Italy` })));
12069
12784
  };
12070
12785
  const getStyle = React.useCallback((style) => {
@@ -18246,10 +18961,10 @@ Made in Italy` })));
18246
18961
  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
18962
  const getPropsVal = React.useCallback((index, str) => {
18248
18963
  try {
18249
- return new Function('props', 'str', `if (str) {
18250
- return props?.button${index + 1}${str}
18251
- } else {
18252
- return props?.button${index + 1}
18964
+ return new Function('props', 'str', `if (str) {
18965
+ return props?.button${index + 1}${str}
18966
+ } else {
18967
+ return props?.button${index + 1}
18253
18968
  }`)(props, str);
18254
18969
  }
18255
18970
  catch (_a) { }
@@ -20132,10 +20847,16 @@ Made in Italy` })));
20132
20847
  React.createElement(Swiper, { style: {
20133
20848
  marginTop: tagHeight
20134
20849
  }, ref: swiperRef, onSlideChange: () => {
20135
- swiperRef.current.swiper.allowTouchMove = false;
20136
- setTimeout(() => {
20137
- swiperRef.current.swiper.allowTouchMove = true;
20138
- }, 500);
20850
+ var _a;
20851
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
20852
+ swiperRef.current.swiper.allowTouchMove = false;
20853
+ setTimeout(() => {
20854
+ var _a;
20855
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
20856
+ swiperRef.current.swiper.allowTouchMove = true;
20857
+ }
20858
+ }, 500);
20859
+ }
20139
20860
  }, onActiveIndexChange: (swiper) => {
20140
20861
  var _a, _b;
20141
20862
  setActiveIndex(swiper.activeIndex);
@@ -21028,10 +21749,16 @@ Made in Italy` })));
21028
21749
  // className={style['clc-sxp-container']}
21029
21750
  style: { height: containerHeight, position: 'relative', pointerEvents } },
21030
21751
  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);
21752
+ var _a;
21753
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
21754
+ swiperRef.current.swiper.allowTouchMove = false;
21755
+ setTimeout(() => {
21756
+ var _a;
21757
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
21758
+ swiperRef.current.swiper.allowTouchMove = true;
21759
+ }
21760
+ }, 500);
21761
+ }
21035
21762
  }, onActiveIndexChange: (swiper) => {
21036
21763
  setCurIndex(swiper === null || swiper === void 0 ? void 0 : swiper.activeIndex);
21037
21764
  onActiveChange === null || onActiveChange === void 0 ? void 0 : onActiveChange(swiper.activeIndex);
@@ -21187,6 +21914,7 @@ Made in Italy` })));
21187
21914
  exports.DiyStoryPreview = index$1;
21188
21915
  exports.EditorDataProvider = EditorDataProvider;
21189
21916
  exports.Modal = Modal$1;
21917
+ exports.StructurePage = StructurePage;
21190
21918
  exports.SxpDataSourceProvider = SxpDataSourceProvider$1;
21191
21919
  exports.SxpPageCore = index;
21192
21920
  exports.SxpPageRender = SxpPageRender$1;