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/index.cjs CHANGED
@@ -678,6 +678,10 @@ const SxpDataSourceProvider = ({ render, dataSources, utmVal, enableReportEvent
678
678
  const [popupDetailData, setPopupDetailData] = React.useState();
679
679
  const [waterFallData, setWaterFallData] = React.useState();
680
680
  const [openHashtag, setOpenHashtag] = React.useState(isOpenHashTag);
681
+ // 将 setPopupDetailData 挂载到 window 对象,供 StructurePage 使用
682
+ if (typeof window !== 'undefined') {
683
+ window.setPopupDetailData = setPopupDetailData;
684
+ }
681
685
  const [cacheRtcList, setCacheRtcList] = React.useState([]);
682
686
  const [cacheActiveIndex, setCacheActiveIndex] = React.useState(0);
683
687
  const [isFromHashtag, setIsFromHashtag] = React.useState(false);
@@ -1137,7 +1141,7 @@ const SxpDataSourceProvider = ({ render, dataSources, utmVal, enableReportEvent
1137
1141
  query.pageNum = pageNum;
1138
1142
  result = isDiyH5
1139
1143
  ? yield (bffFetch === null || bffFetch === void 0 ? void 0 : bffFetch('v3/recommend/direct/page/view', { method: 'POST', body: query }))
1140
- : yield (bffFetch === null || bffFetch === void 0 ? void 0 : bffFetch('recommend/direct_page', { method: 'POST', body: query }));
1144
+ : yield (bffFetch === null || bffFetch === void 0 ? void 0 : bffFetch('v1/recommend/direct_page', { method: 'POST', body: query }));
1141
1145
  if (!(result === null || result === void 0 ? void 0 : result.success)) {
1142
1146
  return undefined;
1143
1147
  }
@@ -1365,6 +1369,7 @@ const SxpDataSourceProvider = ({ render, dataSources, utmVal, enableReportEvent
1365
1369
  var _a;
1366
1370
  const prop = match.substring(2, match.length - 2);
1367
1371
  try {
1372
+ // eslint-disable-next-line no-new-func
1368
1373
  let replaceValue = new Function('fix_par', 'product', `return ${prop}`)(fix_par, product === null || product === void 0 ? void 0 : product[0]);
1369
1374
  if (replaceValue) {
1370
1375
  if ((prop === null || prop === void 0 ? void 0 : prop.indexOf('currency')) !== -1 &&
@@ -1948,9 +1953,839 @@ const EditorCore = React.forwardRef(({ children, resolver, isSsr, schema, enable
1948
1953
  React.createElement(DataSourceProvider$1, { isSsr: isSsr, enable: enableDataSource }, children)));
1949
1954
  });
1950
1955
 
1956
+ const FormatImage = React.forwardRef((props, ref) => {
1957
+ const { src, onLoad, style, className, loading, alt = 'image' } = props;
1958
+ const [imgSrc, setImgSrc] = React.useState(src);
1959
+ const imgRef = React.useRef(null);
1960
+ const [visible, setVisible] = React.useState(false);
1961
+ React.useImperativeHandle(ref, () => ({
1962
+ setSrc: (v) => {
1963
+ if (v)
1964
+ setImgSrc(v);
1965
+ }
1966
+ }));
1967
+ React.useEffect(() => {
1968
+ if (src)
1969
+ setImgSrc(src);
1970
+ }, [src]);
1971
+ React.useEffect(() => {
1972
+ const onShow = () => {
1973
+ if (src && !visible && imgRef.current) {
1974
+ imgRef.current.src = '';
1975
+ imgRef.current.src = src;
1976
+ }
1977
+ };
1978
+ SXP_EVENT_BUS.on(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
1979
+ return () => {
1980
+ SXP_EVENT_BUS.off(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
1981
+ };
1982
+ }, [src, visible]);
1983
+ return (React.createElement(React.Fragment, null,
1984
+ !visible && !imgSrc && React.createElement("div", { style: { width: '100%', height: '100%', zIndex: 1, backgroundColor: '#fff' } }),
1985
+ (imgSrc === null || imgSrc === void 0 ? void 0 : imgSrc.includes('.avif')) ? (React.createElement("picture", null,
1986
+ React.createElement("source", { type: 'image/avif', srcSet: imgSrc }),
1987
+ React.createElement("source", { type: 'image/webp', srcSet: `${imgSrc}?imageMogr2/format/webp` }),
1988
+ React.createElement("source", { type: 'image/jpeg', srcSet: `${imgSrc}?imageMogr2/format/jpg` }),
1989
+ React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
1990
+ setVisible(true);
1991
+ onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
1992
+ }, alt: alt }))) : (React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
1993
+ setVisible(true);
1994
+ onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
1995
+ }, alt: alt }))));
1996
+ });
1997
+ var FormatImage$1 = React.memo(FormatImage);
1998
+
1999
+ // 动态导入材料库(避免循环依赖)
2000
+ const RESOLVER$3 = {};
2001
+ try {
2002
+ // 尝试动态导入材料库
2003
+ const materialsModule = require('../../materials/sxp');
2004
+ if (materialsModule && typeof materialsModule === 'object') {
2005
+ Object.values(materialsModule).forEach((v) => {
2006
+ var _a;
2007
+ if ((_a = v === null || v === void 0 ? void 0 : v.extend) === null || _a === void 0 ? void 0 : _a.type) {
2008
+ RESOLVER$3[v.extend.type] = v;
2009
+ }
2010
+ });
2011
+ // 调试信息:记录成功加载的组件数量
2012
+ if (Object.keys(RESOLVER$3).length > 0) {
2013
+ console.log('[StructurePage] Successfully loaded materials:', Object.keys(RESOLVER$3));
2014
+ }
2015
+ else {
2016
+ console.warn('[StructurePage] Materials module loaded but no valid components found');
2017
+ }
2018
+ }
2019
+ else {
2020
+ console.warn('[StructurePage] Materials module is not a valid object:', materialsModule);
2021
+ }
2022
+ }
2023
+ catch (error) {
2024
+ console.error('[StructurePage] Failed to load materials for StructurePage:', error);
2025
+ }
2026
+ // 基础样式定义
2027
+ const baseStyles = {
2028
+ container: {
2029
+ backgroundColor: '#000',
2030
+ overflowY: 'auto',
2031
+ overflowX: 'hidden',
2032
+ padding: 0,
2033
+ boxSizing: 'border-box'
2034
+ },
2035
+ section: {
2036
+ width: '100%',
2037
+ position: 'relative',
2038
+ boxSizing: 'border-box'
2039
+ },
2040
+ // Hero Section
2041
+ heroSection: {
2042
+ width: '100%',
2043
+ height: 'auto',
2044
+ position: 'relative',
2045
+ overflow: 'hidden',
2046
+ backgroundColor: '#000'
2047
+ },
2048
+ heroTopText: {
2049
+ width: '100%',
2050
+ padding: '20px',
2051
+ backgroundColor: '#fff',
2052
+ color: '#000',
2053
+ fontSize: '16px',
2054
+ fontWeight: 'bold',
2055
+ textAlign: 'center',
2056
+ boxSizing: 'border-box'
2057
+ },
2058
+ heroImageContainer: {
2059
+ width: '100%',
2060
+ position: 'relative',
2061
+ overflow: 'hidden'
2062
+ },
2063
+ heroImage: {
2064
+ width: '100%',
2065
+ height: 'auto',
2066
+ display: 'block',
2067
+ objectFit: 'cover'
2068
+ },
2069
+ heroVideo: {
2070
+ width: '100%',
2071
+ height: 'auto',
2072
+ display: 'block',
2073
+ objectFit: 'cover'
2074
+ },
2075
+ heroOverlay: {
2076
+ position: 'absolute',
2077
+ bottom: 0,
2078
+ left: 0,
2079
+ right: 0,
2080
+ padding: '40px 20px',
2081
+ background: 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, transparent 100%)',
2082
+ color: '#fff',
2083
+ display: 'flex',
2084
+ justifyContent: 'center',
2085
+ alignItems: 'center'
2086
+ },
2087
+ heroButton: {
2088
+ padding: '12px 30px',
2089
+ backgroundColor: '#fff',
2090
+ color: '#000',
2091
+ border: 'none',
2092
+ fontSize: '14px',
2093
+ fontWeight: 500,
2094
+ cursor: 'pointer',
2095
+ textTransform: 'uppercase'
2096
+ },
2097
+ // Carousel Section
2098
+ carouselSection: {
2099
+ width: '100%',
2100
+ position: 'relative'
2101
+ },
2102
+ carouselImageContainer: {
2103
+ width: '100%',
2104
+ height: 'auto',
2105
+ position: 'relative',
2106
+ overflow: 'hidden'
2107
+ },
2108
+ carouselContainer: {
2109
+ display: 'flex',
2110
+ transition: 'transform 0.5s ease-in-out',
2111
+ width: '100%'
2112
+ },
2113
+ carouselSlide: {
2114
+ minWidth: '100%',
2115
+ position: 'relative'
2116
+ },
2117
+ carouselImage: {
2118
+ width: '100%',
2119
+ height: 'auto',
2120
+ display: 'block',
2121
+ objectFit: 'cover'
2122
+ },
2123
+ carouselVideo: {
2124
+ width: '100%',
2125
+ height: 'auto',
2126
+ display: 'block',
2127
+ objectFit: 'cover'
2128
+ },
2129
+ carouselInfoSection: {
2130
+ width: '100%',
2131
+ padding: '20px',
2132
+ backgroundColor: '#000',
2133
+ color: '#fff',
2134
+ textAlign: 'center'
2135
+ },
2136
+ carouselText: {
2137
+ fontSize: '16px',
2138
+ fontWeight: 'normal',
2139
+ marginBottom: '15px',
2140
+ color: '#fff'
2141
+ },
2142
+ carouselButton: {
2143
+ padding: '10px 25px',
2144
+ backgroundColor: '#fff',
2145
+ color: '#000',
2146
+ border: '1px solid #fff',
2147
+ fontSize: '13px',
2148
+ fontWeight: 500,
2149
+ cursor: 'pointer',
2150
+ textTransform: 'uppercase'
2151
+ },
2152
+ arrowButton: {
2153
+ position: 'absolute',
2154
+ top: '50%',
2155
+ transform: 'translateY(-50%)',
2156
+ width: '40px',
2157
+ height: '40px',
2158
+ backgroundColor: 'rgba(255,255,255,0.8)',
2159
+ border: 'none',
2160
+ borderRadius: '50%',
2161
+ fontSize: '18px',
2162
+ cursor: 'pointer',
2163
+ zIndex: 10,
2164
+ display: 'flex',
2165
+ alignItems: 'center',
2166
+ justifyContent: 'center'
2167
+ },
2168
+ // Highlight Reveal Section
2169
+ highlightSection: {
2170
+ width: '100%',
2171
+ position: 'relative',
2172
+ backgroundColor: '#000'
2173
+ },
2174
+ highlightImageContainer: {
2175
+ width: '100%',
2176
+ aspectRatio: '1/1',
2177
+ position: 'relative',
2178
+ overflow: 'hidden'
2179
+ },
2180
+ highlightImage: {
2181
+ width: '100%',
2182
+ height: '100%',
2183
+ objectFit: 'cover',
2184
+ display: 'block'
2185
+ },
2186
+ highlightInfoSection: {
2187
+ width: '100%',
2188
+ padding: '20px',
2189
+ backgroundColor: '#000',
2190
+ color: '#fff',
2191
+ textAlign: 'center'
2192
+ },
2193
+ highlightTitle: {
2194
+ fontSize: '18px',
2195
+ fontWeight: 'bold',
2196
+ marginBottom: '10px',
2197
+ textAlign: 'center',
2198
+ color: '#fff'
2199
+ },
2200
+ highlightDesc: {
2201
+ fontSize: '14px',
2202
+ marginBottom: '15px',
2203
+ textAlign: 'center',
2204
+ lineHeight: '1.5',
2205
+ color: '#ccc'
2206
+ },
2207
+ highlightButton: {
2208
+ padding: '10px 25px',
2209
+ backgroundColor: 'transparent',
2210
+ color: '#fff',
2211
+ border: '1px solid #fff',
2212
+ fontSize: '13px',
2213
+ fontWeight: 500,
2214
+ cursor: 'pointer',
2215
+ textTransform: 'uppercase'
2216
+ },
2217
+ // Product Grid Section
2218
+ productGrid: {
2219
+ display: 'grid',
2220
+ gridTemplateColumns: '50% 50%',
2221
+ gridAutoRows: 'auto',
2222
+ gap: '0',
2223
+ width: '100%',
2224
+ backgroundColor: '#000',
2225
+ boxSizing: 'border-box',
2226
+ margin: 0,
2227
+ padding: 0,
2228
+ overflow: 'hidden'
2229
+ },
2230
+ productItem: {
2231
+ position: 'relative',
2232
+ backgroundColor: '#000',
2233
+ display: 'block',
2234
+ boxSizing: 'border-box',
2235
+ width: '100%',
2236
+ minWidth: 0,
2237
+ overflow: 'hidden'
2238
+ },
2239
+ productImageContainer: {
2240
+ width: '100%',
2241
+ paddingBottom: '100%',
2242
+ position: 'relative',
2243
+ overflow: 'hidden'
2244
+ },
2245
+ productImage: {
2246
+ position: 'absolute',
2247
+ top: 0,
2248
+ left: 0,
2249
+ width: '100%',
2250
+ height: '100%',
2251
+ objectFit: 'cover',
2252
+ display: 'block'
2253
+ },
2254
+ productCtaContainer: {
2255
+ width: '100%',
2256
+ padding: '15px',
2257
+ backgroundColor: '#000',
2258
+ textAlign: 'center',
2259
+ boxSizing: 'border-box'
2260
+ },
2261
+ productText: {
2262
+ width: '100%',
2263
+ padding: '15px',
2264
+ backgroundColor: '#000',
2265
+ color: '#fff',
2266
+ textAlign: 'center',
2267
+ fontSize: '14px',
2268
+ fontWeight: 'normal',
2269
+ boxSizing: 'border-box'
2270
+ },
2271
+ productButton: {
2272
+ padding: '8px 20px',
2273
+ backgroundColor: 'transparent',
2274
+ color: '#fff',
2275
+ border: '1px solid #fff',
2276
+ fontSize: '12px',
2277
+ fontWeight: 500,
2278
+ cursor: 'pointer',
2279
+ textTransform: 'uppercase',
2280
+ whiteSpace: 'nowrap'
2281
+ },
2282
+ // Footer Section
2283
+ footerSection: {
2284
+ width: '100%',
2285
+ position: 'relative',
2286
+ backgroundColor: '#000'
2287
+ },
2288
+ footerInfoSection: {
2289
+ width: '100%',
2290
+ padding: '20px',
2291
+ backgroundColor: '#000',
2292
+ color: '#fff',
2293
+ textAlign: 'center'
2294
+ },
2295
+ footerText: {
2296
+ fontSize: '18px',
2297
+ fontWeight: 'normal',
2298
+ marginBottom: '15px',
2299
+ lineHeight: '1.4',
2300
+ color: '#fff'
2301
+ },
2302
+ footerButton: {
2303
+ padding: '10px 25px',
2304
+ backgroundColor: 'transparent',
2305
+ color: '#fff',
2306
+ border: '1px solid #fff',
2307
+ fontSize: '13px',
2308
+ fontWeight: 500,
2309
+ cursor: 'pointer',
2310
+ textTransform: 'uppercase',
2311
+ marginBottom: '20px',
2312
+ display: 'inline-block'
2313
+ },
2314
+ footerImageContainer: {
2315
+ width: '100%',
2316
+ aspectRatio: '1/1',
2317
+ overflow: 'hidden'
2318
+ },
2319
+ footerImage: {
2320
+ width: '100%',
2321
+ height: '100%',
2322
+ objectFit: 'cover',
2323
+ display: 'block'
2324
+ }
2325
+ };
2326
+ const StructurePage = (_a) => {
2327
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
2328
+ 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"]);
2329
+ const [data, setData] = React.useState(null);
2330
+ const [loading, setLoading] = React.useState(true);
2331
+ const [error, setError] = React.useState(null);
2332
+ const [carouselIndex, setCarouselIndex] = React.useState(0);
2333
+ const heroVideoRef = React.useRef(null);
2334
+ const carouselVideoRefs = React.useRef([]);
2335
+ // 视频暂停状态管理
2336
+ const [isHeroVideoPaused, setIsHeroVideoPaused] = React.useState(false);
2337
+ const [carouselVideoPausedStates, setCarouselVideoPausedStates] = React.useState([]);
2338
+ // 从 schema 中获取 multiCTAConfig(优先使用 props 传入的)
2339
+ const { schema } = useEditor();
2340
+ const multiCTAConfig = React.useMemo(() => {
2341
+ var _a;
2342
+ return propMultiCTAConfig || ((_a = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _a === void 0 ? void 0 : _a.multiCTAConfig) || {};
2343
+ }, [propMultiCTAConfig, (_b = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _b === void 0 ? void 0 : _b.multiCTAConfig]);
2344
+ // 默认播放图标 URL(直接使用 CDN 地址作为后备)
2345
+ const DEFAULT_PAUSE_ICON = 'https://sxph5-uat.chatlabs.net/pb_static/06f28a2025c74c1cb49be6767316d827.png';
2346
+ // 获取视频播放图标
2347
+ const videoPlayIcon = React.useMemo(() => {
2348
+ var _a, _b;
2349
+ // 优先使用 props 传入的
2350
+ if (propVideoPlayIcon)
2351
+ return propVideoPlayIcon;
2352
+ // 然后使用 schema 配置的
2353
+ 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;
2354
+ if (configIcon) {
2355
+ // 如果是完整 URL,直接使用
2356
+ if (configIcon.startsWith('http://') || configIcon.startsWith('https://')) {
2357
+ return configIcon;
2358
+ }
2359
+ // 如果是相对路径,拼接当前域名
2360
+ if (configIcon.startsWith('/')) {
2361
+ return `${window.location.origin}${configIcon}`;
2362
+ }
2363
+ return configIcon;
2364
+ }
2365
+ // 最后使用默认图标
2366
+ return DEFAULT_PAUSE_ICON;
2367
+ }, [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]);
2368
+ // 处理 CTA 点击
2369
+ const handleCtaClick = React.useCallback((link, interaction, productData, ctaData) => {
2370
+ // 如果配置了交互设置,优先使用交互设置
2371
+ if (interaction) {
2372
+ const { linkType, popupType, popupAni } = interaction;
2373
+ if (linkType === 'popup' && popupType) {
2374
+ // 设置弹窗要显示的产品数据
2375
+ if (productData && typeof window !== 'undefined' && window.setPopupDetailData) {
2376
+ // 构造与原有系统一致的数据结构
2377
+ const popupData = {
2378
+ video: {
2379
+ bindProduct: productData,
2380
+ bindProducts: [productData],
2381
+ bindCta: ctaData
2382
+ }
2383
+ };
2384
+ window.setPopupDetailData(popupData);
2385
+ }
2386
+ // 打开弹窗 - 使用与现有系统一致的方式
2387
+ if (typeof window !== 'undefined' && window.sxpPopup) {
2388
+ // 如果有动画配置,传递动画参数;否则只传弹窗 ID
2389
+ if (popupAni && popupAni.name) {
2390
+ window.sxpPopup(popupType, popupAni);
2391
+ }
2392
+ else {
2393
+ window.sxpPopup(popupType);
2394
+ }
2395
+ }
2396
+ return;
2397
+ }
2398
+ }
2399
+ // 默认行为:打开外部链接
2400
+ if (link) {
2401
+ window.open(link, '_blank');
2402
+ }
2403
+ }, []);
2404
+ // 合并基础样式和编辑器配置的样式
2405
+ const mergeStyles = React.useCallback((baseStyle, configKey) => {
2406
+ if (!editorMode || !multiCTAConfig[configKey]) {
2407
+ return baseStyle;
2408
+ }
2409
+ const config = multiCTAConfig[configKey];
2410
+ // 定义允许的样式属性列表
2411
+ const styleKeys = [
2412
+ 'fontSize', 'color', 'textAlign', 'fontWeight',
2413
+ 'backgroundColor', 'padding', 'margin', 'borderRadius',
2414
+ 'showBorder', 'borderWidth', 'borderColor',
2415
+ 'buttonBackgroundColor', 'buttonTextColor', 'buttonWidth', 'buttonHeight'
2416
+ ];
2417
+ // 只处理样式相关的属性,忽略 interaction 等非样式属性
2418
+ const styleConfig = Object.keys(config)
2419
+ .filter(key => styleKeys.includes(key))
2420
+ .reduce((obj, key) => {
2421
+ obj[key] = config[key];
2422
+ return obj;
2423
+ }, {});
2424
+ // 如果配置中没有任何样式字段(只有 interaction),直接返回基础样式
2425
+ if (Object.keys(styleConfig).length === 0) {
2426
+ return baseStyle;
2427
+ }
2428
+ const customStyle = {};
2429
+ // 应用配置中的样式
2430
+ if (styleConfig.fontSize && typeof styleConfig.fontSize === 'number') {
2431
+ customStyle.fontSize = `${styleConfig.fontSize}px`;
2432
+ }
2433
+ if (styleConfig.color && typeof styleConfig.color === 'string') {
2434
+ customStyle.color = styleConfig.color;
2435
+ }
2436
+ if (styleConfig.textAlign && typeof styleConfig.textAlign === 'string') {
2437
+ customStyle.textAlign = styleConfig.textAlign;
2438
+ }
2439
+ if (styleConfig.fontWeight && typeof styleConfig.fontWeight === 'number') {
2440
+ customStyle.fontWeight = styleConfig.fontWeight;
2441
+ }
2442
+ if (styleConfig.backgroundColor && typeof styleConfig.backgroundColor === 'string') {
2443
+ customStyle.backgroundColor = styleConfig.backgroundColor;
2444
+ }
2445
+ if (styleConfig.padding && typeof styleConfig.padding === 'string') {
2446
+ customStyle.padding = styleConfig.padding;
2447
+ }
2448
+ if (styleConfig.margin && typeof styleConfig.margin === 'string') {
2449
+ customStyle.margin = styleConfig.margin;
2450
+ }
2451
+ if (styleConfig.borderRadius && typeof styleConfig.borderRadius === 'number') {
2452
+ customStyle.borderRadius = `${styleConfig.borderRadius}px`;
2453
+ }
2454
+ if (styleConfig.showBorder && styleConfig.borderWidth && typeof styleConfig.borderWidth === 'number') {
2455
+ customStyle.border = `${styleConfig.borderWidth}px solid ${styleConfig.borderColor || '#d9d9d9'}`;
2456
+ }
2457
+ // 按钮特殊样式
2458
+ if (styleConfig.buttonBackgroundColor && typeof styleConfig.buttonBackgroundColor === 'string') {
2459
+ customStyle.backgroundColor = styleConfig.buttonBackgroundColor;
2460
+ }
2461
+ if (styleConfig.buttonTextColor && typeof styleConfig.buttonTextColor === 'string') {
2462
+ customStyle.color = styleConfig.buttonTextColor;
2463
+ }
2464
+ if (styleConfig.buttonWidth && typeof styleConfig.buttonWidth === 'number') {
2465
+ customStyle.width = `${styleConfig.buttonWidth}px`;
2466
+ }
2467
+ if (styleConfig.buttonHeight && typeof styleConfig.buttonHeight === 'number') {
2468
+ customStyle.height = `${styleConfig.buttonHeight}px`;
2469
+ }
2470
+ return Object.assign(Object.assign({}, baseStyle), customStyle);
2471
+ }, [editorMode, multiCTAConfig]);
2472
+ // 渲染 CTA 按钮或模版组件
2473
+ const renderCTA = React.useCallback((buttonKey, ctaData, productData, fallbackStyle) => {
2474
+ var _a, _b, _c;
2475
+ if (!ctaData) {
2476
+ return null;
2477
+ }
2478
+ const config = multiCTAConfig[buttonKey];
2479
+ const templateType = config === null || config === void 0 ? void 0 : config.templateType;
2480
+ const interaction = config === null || config === void 0 ? void 0 : config.interaction;
2481
+ // 如果配置了模版类型,渲染对应的模版组件
2482
+ if (editorMode && templateType && RESOLVER$3[templateType]) {
2483
+ const TemplateComponent = RESOLVER$3[templateType];
2484
+ const templateExtend = TemplateComponent === null || TemplateComponent === void 0 ? void 0 : TemplateComponent.extend;
2485
+ // 严格检查组件是否有效
2486
+ if (templateExtend && typeof TemplateComponent === 'function') {
2487
+ try {
2488
+ // 准备模版组件的 props
2489
+ 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);
2490
+ // 渲染模版组件
2491
+ return React.createElement(TemplateComponent, templateProps);
2492
+ }
2493
+ catch (error) {
2494
+ console.error(`[StructurePage] Failed to render template component ${templateType}:`, error);
2495
+ // 降级到默认按钮
2496
+ }
2497
+ }
2498
+ }
2499
+ // 默认渲染按钮
2500
+ 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));
2501
+ }, [multiCTAConfig, editorMode, handleCtaClick, mergeStyles, rest]);
2502
+ // 获取数据 - 只在组件挂载时执行一次
2503
+ React.useEffect(() => {
2504
+ // 重要:在 PB 编辑器模式下,propMultiCTAConfig 只是样式配置,不是数据源
2505
+ // 只有在 CMS 模式 (isCmsMode=false) 且 propMultiCTAConfig 包含实际数据时才跳过 API 调用
2506
+ // 判断是否包含实际数据:检查是否有 heroSection, carouselSection 等数据字段
2507
+ const hasActualData = propMultiCTAConfig && (propMultiCTAConfig.heroSection ||
2508
+ propMultiCTAConfig.carouselSection ||
2509
+ propMultiCTAConfig.highlightRevealSection ||
2510
+ propMultiCTAConfig.productGridSection ||
2511
+ propMultiCTAConfig.footerSection);
2512
+ if (editorMode && hasActualData && !isCmsMode) {
2513
+ setLoading(false);
2514
+ setError(null);
2515
+ // 使用传入的 multiCTAConfig 作为数据源
2516
+ setData(propMultiCTAConfig);
2517
+ return;
2518
+ }
2519
+ // 如果已经有数据了,且在编辑器模式下,不要重新请求
2520
+ if (editorMode && data && !isCmsMode) {
2521
+ return;
2522
+ }
2523
+ setLoading(true);
2524
+ setError(null);
2525
+ // 根据模式决定使用哪个接口
2526
+ let finalApiUrl = apiUrl;
2527
+ let bodyToSend = {};
2528
+ if (isCmsMode) {
2529
+ // CMS 模式:使用 /api/console/ad/multiCta/rec/detail 接口
2530
+ if (!storyId) {
2531
+ console.error('[StructurePage CMS Mode] storyId is required but not provided');
2532
+ setError('storyId is required in CMS mode');
2533
+ setLoading(false);
2534
+ return;
2535
+ }
2536
+ // 构建 CMS 接口的 URL 和请求体
2537
+ // apiUrl 应该是域名(如 http://localhost:8001),然后拼接 /api/console/ad/multiCta/rec/detail
2538
+ finalApiUrl = `${apiUrl}/api/console/ad/multiCta/rec/detail`;
2539
+ bodyToSend = { storyId };
2540
+ }
2541
+ else {
2542
+ // 普通模式:使用原有的 /api/v1/recommend/list 接口
2543
+ const defaultBody = {
2544
+ maxSize: 20,
2545
+ defaultSize: 10,
2546
+ type: 'story'
2547
+ };
2548
+ bodyToSend = requestBody ? Object.assign(Object.assign({}, defaultBody), requestBody) : defaultBody;
2549
+ }
2550
+ // 构建请求头
2551
+ const headers = {
2552
+ 'Content-Type': 'application/json'
2553
+ };
2554
+ if (isCmsMode) {
2555
+ // CMS 模式:使用自定义 headers(如果有传入)
2556
+ if (customHeaders) {
2557
+ Object.assign(headers, customHeaders);
2558
+ }
2559
+ }
2560
+ else {
2561
+ // 普通模式:从 requestBody 或 bodyToSend 中提取 BFF headers
2562
+ if (bodyToSend['x-app-id']) {
2563
+ headers['x-app-id'] = bodyToSend['x-app-id'];
2564
+ delete bodyToSend['x-app-id'];
2565
+ }
2566
+ if (bodyToSend['x-user-id']) {
2567
+ headers['x-user-id'] = bodyToSend['x-user-id'];
2568
+ delete bodyToSend['x-user-id'];
2569
+ }
2570
+ if (bodyToSend['tenant-id']) {
2571
+ headers['tenant-id'] = bodyToSend['tenant-id'];
2572
+ delete bodyToSend['tenant-id'];
2573
+ }
2574
+ }
2575
+ fetch(finalApiUrl, {
2576
+ method: 'POST',
2577
+ headers,
2578
+ body: JSON.stringify(bodyToSend),
2579
+ credentials: 'include'
2580
+ })
2581
+ .then((res) => {
2582
+ if (!res.ok) {
2583
+ throw new Error(`HTTP error! status: ${res.status}`);
2584
+ }
2585
+ return res.json();
2586
+ })
2587
+ .then((result) => {
2588
+ var _a, _b, _c, _d;
2589
+ if (result.code === '0' || result.code === '00000') {
2590
+ // 判断数据结构:CMS 模式和普通模式可能不同
2591
+ let multiCtaData = null;
2592
+ if (isCmsMode) {
2593
+ // CMS 模式:data.multiCta
2594
+ multiCtaData = (_a = result.data) === null || _a === void 0 ? void 0 : _a.multiCta;
2595
+ }
2596
+ else {
2597
+ // 普通模式:data.recList[0].multiCta
2598
+ 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;
2599
+ }
2600
+ if (multiCtaData) {
2601
+ setData(multiCtaData);
2602
+ }
2603
+ else {
2604
+ console.error('[StructurePage] No multiCta data found in response:', result);
2605
+ setError(result.message || 'No multiCta data found');
2606
+ }
2607
+ }
2608
+ else {
2609
+ setError(result.message || 'Failed to load data');
2610
+ }
2611
+ setLoading(false);
2612
+ })
2613
+ .catch((err) => {
2614
+ console.error('[StructurePage] Failed to fetch data:', {
2615
+ error: err,
2616
+ message: err.message,
2617
+ url: finalApiUrl,
2618
+ body: bodyToSend,
2619
+ isCmsMode,
2620
+ storyId
2621
+ });
2622
+ setError(err.message || 'Network error');
2623
+ setLoading(false);
2624
+ });
2625
+ // eslint-disable-next-line react-hooks/exhaustive-deps
2626
+ }, [apiUrl, isCmsMode, storyId, customHeaders]);
2627
+ // 注意:移除了 editorMode 和 propMultiCTAConfig 依赖,因为:
2628
+ // 1. editorMode 和 propMultiCTAConfig 在编辑器中频繁变化
2629
+ // 2. propMultiCTAConfig 只是样式配置,不是数据源
2630
+ // 3. 数据获取只应该在组件挂载时执行一次(除非 apiUrl/storyId 等关键参数变化)
2631
+ // Hero Section 视频自动播放
2632
+ React.useEffect(() => {
2633
+ var _a;
2634
+ if (heroVideoRef.current && ((_a = data === null || data === void 0 ? void 0 : data.heroSection) === null || _a === void 0 ? void 0 : _a.url)) {
2635
+ heroVideoRef.current.play().catch((err) => console.log('Video autoplay failed:', err));
2636
+ setIsHeroVideoPaused(false);
2637
+ }
2638
+ }, [data === null || data === void 0 ? void 0 : data.heroSection]);
2639
+ // 初始化 carousel 视频暂停状态
2640
+ React.useEffect(() => {
2641
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2642
+ // carousel 视频默认不自动播放,所以初始状态应该是暂停(true)
2643
+ setCarouselVideoPausedStates(new Array(data.carouselSection.length).fill(true));
2644
+ }
2645
+ }, [data === null || data === void 0 ? void 0 : data.carouselSection]);
2646
+ // Hero 视频点击处理
2647
+ const handleHeroVideoClick = React.useCallback(() => {
2648
+ if (heroVideoRef.current) {
2649
+ if (heroVideoRef.current.paused) {
2650
+ heroVideoRef.current.play();
2651
+ setIsHeroVideoPaused(false);
2652
+ }
2653
+ else {
2654
+ heroVideoRef.current.pause();
2655
+ setIsHeroVideoPaused(true);
2656
+ }
2657
+ }
2658
+ }, []);
2659
+ // Carousel 视频点击处理
2660
+ const handleCarouselVideoClick = React.useCallback((index) => {
2661
+ const videoRef = carouselVideoRefs.current[index];
2662
+ if (videoRef) {
2663
+ if (videoRef.paused) {
2664
+ videoRef.play();
2665
+ setCarouselVideoPausedStates(prev => {
2666
+ const newStates = [...prev];
2667
+ newStates[index] = false;
2668
+ return newStates;
2669
+ });
2670
+ }
2671
+ else {
2672
+ videoRef.pause();
2673
+ setCarouselVideoPausedStates(prev => {
2674
+ const newStates = [...prev];
2675
+ newStates[index] = true;
2676
+ return newStates;
2677
+ });
2678
+ }
2679
+ }
2680
+ }, []);
2681
+ // Carousel 导航
2682
+ const handleCarouselPrev = () => {
2683
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2684
+ setCarouselIndex((prev) => (prev === 0 ? data.carouselSection.length - 1 : prev - 1));
2685
+ }
2686
+ };
2687
+ const handleCarouselNext = () => {
2688
+ if (data === null || data === void 0 ? void 0 : data.carouselSection) {
2689
+ setCarouselIndex((prev) => (prev === data.carouselSection.length - 1 ? 0 : prev + 1));
2690
+ }
2691
+ };
2692
+ if (loading) {
2693
+ 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..."));
2694
+ }
2695
+ if (error) {
2696
+ 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' }) },
2697
+ React.createElement("div", { style: { fontSize: '18px', marginBottom: '10px' } }, "\u26A0\uFE0F Error"),
2698
+ React.createElement("div", { style: { fontSize: '14px', opacity: 0.8 } }, error)));
2699
+ }
2700
+ if (!data) {
2701
+ 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"));
2702
+ }
2703
+ return (React.createElement("div", { className: className, style: Object.assign(Object.assign(Object.assign({}, baseStyles.container), { height: containerHeight, width: containerWidth }), containerStyle) },
2704
+ data.heroSection && (React.createElement("div", { style: baseStyles.heroSection },
2705
+ data.heroSection.text && (React.createElement("div", { style: mergeStyles(baseStyles.heroTopText, 'heroTopText') }, data.heroSection.text)),
2706
+ React.createElement("div", { style: baseStyles.heroImageContainer },
2707
+ data.heroSection.url ? (React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: handleHeroVideoClick },
2708
+ React.createElement("video", { ref: heroVideoRef, src: data.heroSection.url, style: baseStyles.heroVideo, autoPlay: true, muted: true, loop: true, playsInline: true, controls: false }),
2709
+ 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,
2710
+ 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))))),
2711
+ data.carouselSection && data.carouselSection.length > 0 && (React.createElement("div", { style: mergeStyles(baseStyles.carouselSection, 'carouselSection') },
2712
+ React.createElement("div", { style: baseStyles.carouselImageContainer },
2713
+ React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.carouselContainer), { transform: `translateX(-${carouselIndex * 100}%)` }) }, data.carouselSection.map((item, index) => {
2714
+ var _a;
2715
+ 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) },
2716
+ React.createElement("video", { ref: (el) => {
2717
+ carouselVideoRefs.current[index] = el;
2718
+ }, src: item.url, style: baseStyles.carouselVideo, muted: true, loop: true, playsInline: true, controls: false }),
2719
+ 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));
2720
+ })),
2721
+ React.createElement("button", { style: Object.assign(Object.assign({}, baseStyles.arrowButton), { left: '10px' }), onClick: handleCarouselPrev }, "\u2039"),
2722
+ React.createElement("button", { style: Object.assign(Object.assign({}, baseStyles.arrowButton), { right: '10px' }), onClick: handleCarouselNext }, "\u203A")),
2723
+ React.createElement("div", { style: mergeStyles(baseStyles.carouselInfoSection, 'carouselSection') },
2724
+ ((_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)),
2725
+ 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)))),
2726
+ data.highlightRevealSection && (React.createElement("div", { style: mergeStyles(baseStyles.highlightSection, 'highlightSection') },
2727
+ React.createElement("div", { style: baseStyles.highlightImageContainer },
2728
+ React.createElement("img", { src: data.highlightRevealSection.landingImageUrl || data.highlightRevealSection.cover, alt: data.highlightRevealSection.title, style: baseStyles.highlightImage })),
2729
+ React.createElement("div", { style: mergeStyles(baseStyles.highlightInfoSection, 'highlightSection') },
2730
+ React.createElement("div", { style: mergeStyles(baseStyles.highlightTitle, 'highlightSection') }, data.highlightRevealSection.title),
2731
+ renderCTA('highlightButton', data.highlightRevealSection.bindCta, data.highlightRevealSection, baseStyles.highlightButton)))),
2732
+ data.productGridSection && data.productGridSection.length > 0 && (React.createElement("div", { style: mergeStyles(baseStyles.productGrid, 'productGrid') }, (() => {
2733
+ // 创建一个6格的网格 (3行 x 2列),根据position放置产品
2734
+ const gridItems = [null, null, null, null, null, null];
2735
+ // 创建产品索引映射表:gridIndex -> 产品在数据数组中的索引(从1开始)
2736
+ const productIndexMap = {};
2737
+ data.productGridSection.forEach((product, idx) => {
2738
+ var _a;
2739
+ const pos = (_a = product.position) === null || _a === void 0 ? void 0 : _a.toLowerCase();
2740
+ let gridIndex = -1;
2741
+ if (pos === 'top_right') {
2742
+ gridIndex = 1; // 第一行右侧
2743
+ }
2744
+ else if (pos === 'top_left') {
2745
+ gridIndex = 0; // 第一行左侧
2746
+ }
2747
+ else if (pos === 'center_left') {
2748
+ gridIndex = 2; // 第二行左侧
2749
+ }
2750
+ else if (pos === 'center_right') {
2751
+ gridIndex = 3; // 第二行右侧
2752
+ }
2753
+ else if (pos === 'bottom_left') {
2754
+ gridIndex = 4; // 第三行左侧
2755
+ }
2756
+ else if (pos === 'bottom_right') {
2757
+ gridIndex = 5; // 第三行右侧
2758
+ }
2759
+ if (gridIndex >= 0) {
2760
+ gridItems[gridIndex] = product;
2761
+ // 映射:网格位置 -> 产品序号(基于数据数组的顺序,从1开始)
2762
+ productIndexMap[gridIndex] = idx + 1;
2763
+ }
2764
+ });
2765
+ return gridItems.map((product, gridIndex) => {
2766
+ // 使用产品在数据数组中的实际索引来确定 buttonKey
2767
+ const productDataIndex = productIndexMap[gridIndex];
2768
+ const buttonKey = `productButton${productDataIndex || gridIndex + 1}`;
2769
+ 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,
2770
+ React.createElement("div", { style: baseStyles.productImageContainer },
2771
+ React.createElement("img", { src: product.landingImageUrl || product.cover,
2772
+ // alt={product.title}
2773
+ style: baseStyles.productImage })),
2774
+ product.bindCta && (React.createElement("div", { style: baseStyles.productCtaContainer }, renderCTA(buttonKey, product.bindCta, product, baseStyles.productButton))))) : (
2775
+ // 空格子
2776
+ React.createElement("div", { style: { width: '100%', paddingBottom: '100%' } }))));
2777
+ });
2778
+ })())),
2779
+ data.footerSection && (React.createElement("div", { style: mergeStyles(baseStyles.footerSection, 'footerSection') },
2780
+ React.createElement("div", { style: mergeStyles(baseStyles.footerInfoSection, 'footerSection') }, renderCTA('footerButton', data.footerSection.bindCta, data.footerSection, baseStyles.footerButton)),
2781
+ React.createElement("div", { style: baseStyles.footerImageContainer },
2782
+ React.createElement("img", { src: data.footerSection.landingImageUrl || data.footerSection.cover, alt: data.footerSection.title, style: baseStyles.footerImage }))))));
2783
+ };
2784
+
1951
2785
  var index$3 = /*#__PURE__*/Object.freeze({
1952
2786
  __proto__: null,
1953
- EditorCore: EditorCore
2787
+ EditorCore: EditorCore,
2788
+ StructurePage: StructurePage
1954
2789
  });
1955
2790
 
1956
2791
  var interactionRender$h = [
@@ -3899,9 +4734,8 @@ function updateSlides() {
3899
4734
  allSlidesSize += slideSizeValue + (spaceBetween || 0);
3900
4735
  });
3901
4736
  allSlidesSize -= spaceBetween;
3902
- const offsetSize = (params.slidesOffsetBefore || 0) + (params.slidesOffsetAfter || 0);
3903
- if (allSlidesSize + offsetSize < swiperSize) {
3904
- const allSlidesOffset = (swiperSize - allSlidesSize - offsetSize) / 2;
4737
+ if (allSlidesSize < swiperSize) {
4738
+ const allSlidesOffset = (swiperSize - allSlidesSize) / 2;
3905
4739
  snapGrid.forEach((snap, snapIndex) => {
3906
4740
  snapGrid[snapIndex] = snap - allSlidesOffset;
3907
4741
  });
@@ -4005,13 +4839,6 @@ function updateSlidesOffset() {
4005
4839
  }
4006
4840
  }
4007
4841
 
4008
- const toggleSlideClasses$1 = (slideEl, condition, className) => {
4009
- if (condition && !slideEl.classList.contains(className)) {
4010
- slideEl.classList.add(className);
4011
- } else if (!condition && slideEl.classList.contains(className)) {
4012
- slideEl.classList.remove(className);
4013
- }
4014
- };
4015
4842
  function updateSlidesProgress(translate) {
4016
4843
  if (translate === void 0) {
4017
4844
  translate = this && this.translate || 0;
@@ -4027,6 +4854,11 @@ function updateSlidesProgress(translate) {
4027
4854
  if (typeof slides[0].swiperSlideOffset === 'undefined') swiper.updateSlidesOffset();
4028
4855
  let offsetCenter = -translate;
4029
4856
  if (rtl) offsetCenter = translate;
4857
+
4858
+ // Visible Slides
4859
+ slides.forEach(slideEl => {
4860
+ slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass);
4861
+ });
4030
4862
  swiper.visibleSlidesIndexes = [];
4031
4863
  swiper.visibleSlides = [];
4032
4864
  let spaceBetween = params.spaceBetween;
@@ -4050,9 +4882,11 @@ function updateSlidesProgress(translate) {
4050
4882
  if (isVisible) {
4051
4883
  swiper.visibleSlides.push(slide);
4052
4884
  swiper.visibleSlidesIndexes.push(i);
4885
+ slides[i].classList.add(params.slideVisibleClass);
4886
+ }
4887
+ if (isFullyVisible) {
4888
+ slides[i].classList.add(params.slideFullyVisibleClass);
4053
4889
  }
4054
- toggleSlideClasses$1(slide, isVisible, params.slideVisibleClass);
4055
- toggleSlideClasses$1(slide, isFullyVisible, params.slideFullyVisibleClass);
4056
4890
  slide.progress = rtl ? -slideProgress : slideProgress;
4057
4891
  slide.originalProgress = rtl ? -originalSlideProgress : originalSlideProgress;
4058
4892
  }
@@ -4121,13 +4955,6 @@ function updateProgress(translate) {
4121
4955
  swiper.emit('progress', progress);
4122
4956
  }
4123
4957
 
4124
- const toggleSlideClasses = (slideEl, condition, className) => {
4125
- if (condition && !slideEl.classList.contains(className)) {
4126
- slideEl.classList.add(className);
4127
- } else if (!condition && slideEl.classList.contains(className)) {
4128
- slideEl.classList.remove(className);
4129
- }
4130
- };
4131
4958
  function updateSlidesClasses() {
4132
4959
  const swiper = this;
4133
4960
  const {
@@ -4141,6 +4968,9 @@ function updateSlidesClasses() {
4141
4968
  const getFilteredSlide = selector => {
4142
4969
  return elementChildren(slidesEl, `.${params.slideClass}${selector}, swiper-slide${selector}`)[0];
4143
4970
  };
4971
+ slides.forEach(slideEl => {
4972
+ slideEl.classList.remove(params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
4973
+ });
4144
4974
  let activeSlide;
4145
4975
  let prevSlide;
4146
4976
  let nextSlide;
@@ -4163,25 +4993,35 @@ function updateSlidesClasses() {
4163
4993
  }
4164
4994
  }
4165
4995
  if (activeSlide) {
4166
- if (!gridEnabled) {
4996
+ // Active classes
4997
+ activeSlide.classList.add(params.slideActiveClass);
4998
+ if (gridEnabled) {
4999
+ if (nextSlide) {
5000
+ nextSlide.classList.add(params.slideNextClass);
5001
+ }
5002
+ if (prevSlide) {
5003
+ prevSlide.classList.add(params.slidePrevClass);
5004
+ }
5005
+ } else {
4167
5006
  // Next Slide
4168
5007
  nextSlide = elementNextAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
4169
5008
  if (params.loop && !nextSlide) {
4170
5009
  nextSlide = slides[0];
4171
5010
  }
5011
+ if (nextSlide) {
5012
+ nextSlide.classList.add(params.slideNextClass);
5013
+ }
4172
5014
 
4173
5015
  // Prev Slide
4174
5016
  prevSlide = elementPrevAll(activeSlide, `.${params.slideClass}, swiper-slide`)[0];
4175
5017
  if (params.loop && !prevSlide === 0) {
4176
5018
  prevSlide = slides[slides.length - 1];
4177
5019
  }
5020
+ if (prevSlide) {
5021
+ prevSlide.classList.add(params.slidePrevClass);
5022
+ }
4178
5023
  }
4179
5024
  }
4180
- slides.forEach(slideEl => {
4181
- toggleSlideClasses(slideEl, slideEl === activeSlide, params.slideActiveClass);
4182
- toggleSlideClasses(slideEl, slideEl === nextSlide, params.slideNextClass);
4183
- toggleSlideClasses(slideEl, slideEl === prevSlide, params.slidePrevClass);
4184
- });
4185
5025
  swiper.emitSlidesClasses();
4186
5026
  }
4187
5027
 
@@ -4559,7 +5399,6 @@ function translateTo(translate, speed, runCallbacks, translateBounds, internal)
4559
5399
  swiper.wrapperEl.removeEventListener('transitionend', swiper.onTranslateToWrapperTransitionEnd);
4560
5400
  swiper.onTranslateToWrapperTransitionEnd = null;
4561
5401
  delete swiper.onTranslateToWrapperTransitionEnd;
4562
- swiper.animating = false;
4563
5402
  if (runCallbacks) {
4564
5403
  swiper.emit('transitionEnd');
4565
5404
  }
@@ -4667,6 +5506,9 @@ function slideTo(index, speed, runCallbacks, internal, initial) {
4667
5506
  if (index === void 0) {
4668
5507
  index = 0;
4669
5508
  }
5509
+ if (speed === void 0) {
5510
+ speed = this.params.speed;
5511
+ }
4670
5512
  if (runCallbacks === void 0) {
4671
5513
  runCallbacks = true;
4672
5514
  }
@@ -4686,12 +5528,9 @@ function slideTo(index, speed, runCallbacks, internal, initial) {
4686
5528
  wrapperEl,
4687
5529
  enabled
4688
5530
  } = swiper;
4689
- if (!enabled && !internal && !initial || swiper.destroyed || swiper.animating && params.preventInteractionOnTransition) {
5531
+ if (swiper.animating && params.preventInteractionOnTransition || !enabled && !internal && !initial || swiper.destroyed) {
4690
5532
  return false;
4691
5533
  }
4692
- if (typeof speed === 'undefined') {
4693
- speed = swiper.params.speed;
4694
- }
4695
5534
  const skip = Math.min(swiper.params.slidesPerGroupSkip, slideIndex);
4696
5535
  let snapIndex = skip + Math.floor((slideIndex - skip) / swiper.params.slidesPerGroup);
4697
5536
  if (snapIndex >= snapGrid.length) snapIndex = snapGrid.length - 1;
@@ -4818,6 +5657,9 @@ function slideToLoop(index, speed, runCallbacks, internal) {
4818
5657
  if (index === void 0) {
4819
5658
  index = 0;
4820
5659
  }
5660
+ if (speed === void 0) {
5661
+ speed = this.params.speed;
5662
+ }
4821
5663
  if (runCallbacks === void 0) {
4822
5664
  runCallbacks = true;
4823
5665
  }
@@ -4827,9 +5669,6 @@ function slideToLoop(index, speed, runCallbacks, internal) {
4827
5669
  }
4828
5670
  const swiper = this;
4829
5671
  if (swiper.destroyed) return;
4830
- if (typeof speed === 'undefined') {
4831
- speed = swiper.params.speed;
4832
- }
4833
5672
  const gridEnabled = swiper.grid && swiper.params.grid && swiper.params.grid.rows > 1;
4834
5673
  let newIndex = index;
4835
5674
  if (swiper.params.loop) {
@@ -4861,9 +5700,6 @@ function slideToLoop(index, speed, runCallbacks, internal) {
4861
5700
  if (centeredSlides) {
4862
5701
  needLoopFix = needLoopFix || targetSlideIndex < Math.ceil(slidesPerView / 2);
4863
5702
  }
4864
- if (internal && centeredSlides && swiper.params.slidesPerView !== 'auto' && !gridEnabled) {
4865
- needLoopFix = false;
4866
- }
4867
5703
  if (needLoopFix) {
4868
5704
  const direction = centeredSlides ? targetSlideIndex < swiper.activeIndex ? 'prev' : 'next' : targetSlideIndex - swiper.activeIndex - 1 < swiper.params.slidesPerView ? 'next' : 'prev';
4869
5705
  swiper.loopFix({
@@ -4889,6 +5725,9 @@ function slideToLoop(index, speed, runCallbacks, internal) {
4889
5725
 
4890
5726
  /* eslint no-unused-vars: "off" */
4891
5727
  function slideNext(speed, runCallbacks, internal) {
5728
+ if (speed === void 0) {
5729
+ speed = this.params.speed;
5730
+ }
4892
5731
  if (runCallbacks === void 0) {
4893
5732
  runCallbacks = true;
4894
5733
  }
@@ -4899,9 +5738,6 @@ function slideNext(speed, runCallbacks, internal) {
4899
5738
  animating
4900
5739
  } = swiper;
4901
5740
  if (!enabled || swiper.destroyed) return swiper;
4902
- if (typeof speed === 'undefined') {
4903
- speed = swiper.params.speed;
4904
- }
4905
5741
  let perGroup = params.slidesPerGroup;
4906
5742
  if (params.slidesPerView === 'auto' && params.slidesPerGroup === 1 && params.slidesPerGroupAuto) {
4907
5743
  perGroup = Math.max(swiper.slidesPerViewDynamic('current', true), 1);
@@ -4930,6 +5766,9 @@ function slideNext(speed, runCallbacks, internal) {
4930
5766
 
4931
5767
  /* eslint no-unused-vars: "off" */
4932
5768
  function slidePrev(speed, runCallbacks, internal) {
5769
+ if (speed === void 0) {
5770
+ speed = this.params.speed;
5771
+ }
4933
5772
  if (runCallbacks === void 0) {
4934
5773
  runCallbacks = true;
4935
5774
  }
@@ -4943,9 +5782,6 @@ function slidePrev(speed, runCallbacks, internal) {
4943
5782
  animating
4944
5783
  } = swiper;
4945
5784
  if (!enabled || swiper.destroyed) return swiper;
4946
- if (typeof speed === 'undefined') {
4947
- speed = swiper.params.speed;
4948
- }
4949
5785
  const isVirtual = swiper.virtual && params.virtual.enabled;
4950
5786
  if (params.loop) {
4951
5787
  if (animating && !isVirtual && params.loopPreventsSliding) return false;
@@ -4998,19 +5834,22 @@ function slidePrev(speed, runCallbacks, internal) {
4998
5834
 
4999
5835
  /* eslint no-unused-vars: "off" */
5000
5836
  function slideReset(speed, runCallbacks, internal) {
5837
+ if (speed === void 0) {
5838
+ speed = this.params.speed;
5839
+ }
5001
5840
  if (runCallbacks === void 0) {
5002
5841
  runCallbacks = true;
5003
5842
  }
5004
5843
  const swiper = this;
5005
5844
  if (swiper.destroyed) return;
5006
- if (typeof speed === 'undefined') {
5007
- speed = swiper.params.speed;
5008
- }
5009
5845
  return swiper.slideTo(swiper.activeIndex, speed, runCallbacks, internal);
5010
5846
  }
5011
5847
 
5012
5848
  /* eslint no-unused-vars: "off" */
5013
5849
  function slideToClosest(speed, runCallbacks, internal, threshold) {
5850
+ if (speed === void 0) {
5851
+ speed = this.params.speed;
5852
+ }
5014
5853
  if (runCallbacks === void 0) {
5015
5854
  runCallbacks = true;
5016
5855
  }
@@ -5019,9 +5858,6 @@ function slideToClosest(speed, runCallbacks, internal, threshold) {
5019
5858
  }
5020
5859
  const swiper = this;
5021
5860
  if (swiper.destroyed) return;
5022
- if (typeof speed === 'undefined') {
5023
- speed = swiper.params.speed;
5024
- }
5025
5861
  let index = swiper.activeIndex;
5026
5862
  const skip = Math.min(swiper.params.slidesPerGroupSkip, index);
5027
5863
  const snapIndex = skip + Math.floor((index - skip) / swiper.params.slidesPerGroup);
@@ -5656,7 +6492,7 @@ function onTouchMove(event) {
5656
6492
  data.startMoving = true;
5657
6493
  }
5658
6494
  }
5659
- if (data.isScrolling || e.type === 'touchmove' && data.preventTouchMoveFromPointerMove) {
6495
+ if (data.isScrolling) {
5660
6496
  data.isTouched = false;
5661
6497
  return;
5662
6498
  }
@@ -5698,10 +6534,7 @@ function onTouchMove(event) {
5698
6534
  if (swiper.animating) {
5699
6535
  const evt = new window.CustomEvent('transitionend', {
5700
6536
  bubbles: true,
5701
- cancelable: true,
5702
- detail: {
5703
- bySwiperTouchMove: true
5704
- }
6537
+ cancelable: true
5705
6538
  });
5706
6539
  swiper.wrapperEl.dispatchEvent(evt);
5707
6540
  }
@@ -6095,7 +6928,6 @@ const events = (swiper, method) => {
6095
6928
  const capture = !!params.nested;
6096
6929
  const domMethod = method === 'on' ? 'addEventListener' : 'removeEventListener';
6097
6930
  const swiperMethod = method;
6098
- if (!el || typeof el === 'string') return;
6099
6931
 
6100
6932
  // Touch Events
6101
6933
  document[domMethod]('touchstart', swiper.onDocumentTouchStart, {
@@ -6204,8 +7036,6 @@ function setBreakpoint() {
6204
7036
  const breakpointParams = breakpointOnlyParams || swiper.originalParams;
6205
7037
  const wasMultiRow = isGridEnabled(swiper, params);
6206
7038
  const isMultiRow = isGridEnabled(swiper, breakpointParams);
6207
- const wasGrabCursor = swiper.params.grabCursor;
6208
- const isGrabCursor = breakpointParams.grabCursor;
6209
7039
  const wasEnabled = params.enabled;
6210
7040
  if (wasMultiRow && !isMultiRow) {
6211
7041
  el.classList.remove(`${params.containerModifierClass}grid`, `${params.containerModifierClass}grid-column`);
@@ -6217,11 +7047,6 @@ function setBreakpoint() {
6217
7047
  }
6218
7048
  swiper.emitContainerClasses();
6219
7049
  }
6220
- if (wasGrabCursor && !isGrabCursor) {
6221
- swiper.unsetGrabCursor();
6222
- } else if (!wasGrabCursor && isGrabCursor) {
6223
- swiper.setGrabCursor();
6224
- }
6225
7050
 
6226
7051
  // Toggle navigation, pagination, scrollbar
6227
7052
  ['navigation', 'pagination', 'scrollbar'].forEach(prop => {
@@ -6372,7 +7197,6 @@ function removeClasses() {
6372
7197
  el,
6373
7198
  classNames
6374
7199
  } = swiper;
6375
- if (!el || typeof el === 'string') return;
6376
7200
  el.classList.remove(...classNames);
6377
7201
  swiper.emitContainerClasses();
6378
7202
  }
@@ -7137,12 +7961,8 @@ let Swiper$1 = class Swiper {
7137
7961
  // Cleanup styles
7138
7962
  if (cleanStyles) {
7139
7963
  swiper.removeClasses();
7140
- if (el && typeof el !== 'string') {
7141
- el.removeAttribute('style');
7142
- }
7143
- if (wrapperEl) {
7144
- wrapperEl.removeAttribute('style');
7145
- }
7964
+ el.removeAttribute('style');
7965
+ wrapperEl.removeAttribute('style');
7146
7966
  if (slides && slides.length) {
7147
7967
  slides.forEach(slideEl => {
7148
7968
  slideEl.classList.remove(params.slideVisibleClass, params.slideFullyVisibleClass, params.slideActiveClass, params.slideNextClass, params.slidePrevClass);
@@ -7158,9 +7978,7 @@ let Swiper$1 = class Swiper {
7158
7978
  swiper.off(eventName);
7159
7979
  });
7160
7980
  if (deleteInstance !== false) {
7161
- if (swiper.el && typeof swiper.el !== 'string') {
7162
- swiper.el.swiper = null;
7163
- }
7981
+ swiper.el.swiper = null;
7164
7982
  deleteProps(swiper);
7165
7983
  }
7166
7984
  swiper.destroyed = true;
@@ -7554,7 +8372,7 @@ const updateOnVirtualData = swiper => {
7554
8372
  };
7555
8373
 
7556
8374
  /**
7557
- * Swiper React 11.1.4
8375
+ * Swiper React 11.0.7
7558
8376
  * Most modern mobile touch slider and framework with hardware accelerated transitions
7559
8377
  * https://swiperjs.com
7560
8378
  *
@@ -7562,7 +8380,7 @@ const updateOnVirtualData = swiper => {
7562
8380
  *
7563
8381
  * Released under the MIT License
7564
8382
  *
7565
- * Released on: May 30, 2024
8383
+ * Released on: February 27, 2024
7566
8384
  */
7567
8385
 
7568
8386
 
@@ -8489,10 +9307,8 @@ function Navigation(_ref) {
8489
9307
  }
8490
9308
  if (el) {
8491
9309
  if (typeof el === 'string') res = [...document.querySelectorAll(el)];
8492
- if (swiper.params.uniqueNavElements && typeof el === 'string' && res && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {
9310
+ if (swiper.params.uniqueNavElements && typeof el === 'string' && res.length > 1 && swiper.el.querySelectorAll(el).length === 1) {
8493
9311
  res = swiper.el.querySelector(el);
8494
- } else if (res && res.length === 1) {
8495
- res = res[0];
8496
9312
  }
8497
9313
  }
8498
9314
  if (el && !res) return el;
@@ -8614,14 +9430,7 @@ function Navigation(_ref) {
8614
9430
  nextEl = makeElementsArray(nextEl);
8615
9431
  prevEl = makeElementsArray(prevEl);
8616
9432
  const targetEl = e.target;
8617
- let targetIsButton = prevEl.includes(targetEl) || nextEl.includes(targetEl);
8618
- if (swiper.isElement && !targetIsButton) {
8619
- const path = e.path || e.composedPath && e.composedPath();
8620
- if (path) {
8621
- targetIsButton = path.find(pathEl => nextEl.includes(pathEl) || prevEl.includes(pathEl));
8622
- }
8623
- }
8624
- if (swiper.params.navigation.hideOnClick && !targetIsButton) {
9433
+ if (swiper.params.navigation.hideOnClick && !prevEl.includes(targetEl) && !nextEl.includes(targetEl)) {
8625
9434
  if (swiper.pagination && swiper.params.pagination && swiper.params.pagination.clickable && (swiper.pagination.el === targetEl || swiper.pagination.el.contains(targetEl))) return;
8626
9435
  let isHidden;
8627
9436
  if (nextEl.length) {
@@ -9277,7 +10086,7 @@ function Scrollbar(_ref) {
9277
10086
  dragEl
9278
10087
  } = scrollbar;
9279
10088
  if (!isTouched) return;
9280
- if (e.preventDefault && e.cancelable) e.preventDefault();else e.returnValue = false;
10089
+ if (e.preventDefault) e.preventDefault();else e.returnValue = false;
9281
10090
  setDragPosition(e);
9282
10091
  wrapperEl.style.transitionDuration = '0ms';
9283
10092
  el.style.transitionDuration = '0ms';
@@ -9488,9 +10297,6 @@ function A11y(_ref) {
9488
10297
  clicked: false
9489
10298
  };
9490
10299
  let liveRegion = null;
9491
- let preventFocusHandler;
9492
- let focusTargetSlideEl;
9493
- let visibilityChangedTimestamp = new Date().getTime();
9494
10300
  function notify(message) {
9495
10301
  const notification = liveRegion;
9496
10302
  if (notification.length === 0) return;
@@ -9571,28 +10377,24 @@ function A11y(_ref) {
9571
10377
  if (swiper.pagination && swiper.pagination.el && (targetEl === swiper.pagination.el || swiper.pagination.el.contains(e.target))) {
9572
10378
  if (!e.target.matches(classesToSelector(swiper.params.pagination.bulletClass))) return;
9573
10379
  }
9574
- if (swiper.navigation && swiper.navigation.prevEl && swiper.navigation.nextEl) {
9575
- const prevEls = makeElementsArray(swiper.navigation.prevEl);
9576
- const nextEls = makeElementsArray(swiper.navigation.nextEl);
9577
- if (nextEls.includes(targetEl)) {
9578
- if (!(swiper.isEnd && !swiper.params.loop)) {
9579
- swiper.slideNext();
9580
- }
9581
- if (swiper.isEnd) {
9582
- notify(params.lastSlideMessage);
9583
- } else {
9584
- notify(params.nextSlideMessage);
9585
- }
10380
+ if (swiper.navigation && swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl) {
10381
+ if (!(swiper.isEnd && !swiper.params.loop)) {
10382
+ swiper.slideNext();
9586
10383
  }
9587
- if (prevEls.includes(targetEl)) {
9588
- if (!(swiper.isBeginning && !swiper.params.loop)) {
9589
- swiper.slidePrev();
9590
- }
9591
- if (swiper.isBeginning) {
9592
- notify(params.firstSlideMessage);
9593
- } else {
9594
- notify(params.prevSlideMessage);
9595
- }
10384
+ if (swiper.isEnd) {
10385
+ notify(params.lastSlideMessage);
10386
+ } else {
10387
+ notify(params.nextSlideMessage);
10388
+ }
10389
+ }
10390
+ if (swiper.navigation && swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl) {
10391
+ if (!(swiper.isBeginning && !swiper.params.loop)) {
10392
+ swiper.slidePrev();
10393
+ }
10394
+ if (swiper.isBeginning) {
10395
+ notify(params.firstSlideMessage);
10396
+ } else {
10397
+ notify(params.prevSlideMessage);
9596
10398
  }
9597
10399
  }
9598
10400
  if (swiper.pagination && targetEl.matches(classesToSelector(swiper.params.pagination.bulletClass))) {
@@ -9657,14 +10459,10 @@ function A11y(_ref) {
9657
10459
  addElLabel(el, message);
9658
10460
  addElControls(el, wrapperId);
9659
10461
  };
9660
- const handlePointerDown = e => {
9661
- if (focusTargetSlideEl && focusTargetSlideEl !== e.target && !focusTargetSlideEl.contains(e.target)) {
9662
- preventFocusHandler = true;
9663
- }
10462
+ const handlePointerDown = () => {
9664
10463
  swiper.a11y.clicked = true;
9665
10464
  };
9666
10465
  const handlePointerUp = () => {
9667
- preventFocusHandler = false;
9668
10466
  requestAnimationFrame(() => {
9669
10467
  requestAnimationFrame(() => {
9670
10468
  if (!swiper.destroyed) {
@@ -9673,15 +10471,10 @@ function A11y(_ref) {
9673
10471
  });
9674
10472
  });
9675
10473
  };
9676
- const onVisibilityChange = e => {
9677
- visibilityChangedTimestamp = new Date().getTime();
9678
- };
9679
10474
  const handleFocus = e => {
9680
10475
  if (swiper.a11y.clicked) return;
9681
- if (new Date().getTime() - visibilityChangedTimestamp < 100) return;
9682
10476
  const slideEl = e.target.closest(`.${swiper.params.slideClass}, swiper-slide`);
9683
10477
  if (!slideEl || !swiper.slides.includes(slideEl)) return;
9684
- focusTargetSlideEl = slideEl;
9685
10478
  const isActive = swiper.slides.indexOf(slideEl) === swiper.activeIndex;
9686
10479
  const isVisible = swiper.params.watchSlidesProgress && swiper.visibleSlides && swiper.visibleSlides.includes(slideEl);
9687
10480
  if (isActive || isVisible) return;
@@ -9691,15 +10484,7 @@ function A11y(_ref) {
9691
10484
  } else {
9692
10485
  swiper.el.scrollTop = 0;
9693
10486
  }
9694
- requestAnimationFrame(() => {
9695
- if (preventFocusHandler) return;
9696
- if (swiper.params.loop) {
9697
- swiper.slideToLoop(parseInt(slideEl.getAttribute('data-swiper-slide-index')), 0);
9698
- } else {
9699
- swiper.slideTo(swiper.slides.indexOf(slideEl), 0);
9700
- }
9701
- preventFocusHandler = false;
9702
- });
10487
+ swiper.slideTo(swiper.slides.indexOf(slideEl), 0);
9703
10488
  };
9704
10489
  const initSlides = () => {
9705
10490
  const params = swiper.params.a11y;
@@ -9764,9 +10549,6 @@ function A11y(_ref) {
9764
10549
  }
9765
10550
 
9766
10551
  // Tab focus
9767
- const document = getDocument();
9768
- document.addEventListener('visibilitychange', onVisibilityChange);
9769
- swiper.el.addEventListener('focus', handleFocus, true);
9770
10552
  swiper.el.addEventListener('focus', handleFocus, true);
9771
10553
  swiper.el.addEventListener('pointerdown', handlePointerDown, true);
9772
10554
  swiper.el.addEventListener('pointerup', handlePointerUp, true);
@@ -9793,14 +10575,11 @@ function A11y(_ref) {
9793
10575
  el.removeEventListener('keydown', onEnterOrSpaceKey);
9794
10576
  });
9795
10577
  }
9796
- const document = getDocument();
9797
- document.removeEventListener('visibilitychange', onVisibilityChange);
10578
+
9798
10579
  // Tab focus
9799
- if (swiper.el && typeof swiper.el !== 'string') {
9800
- swiper.el.removeEventListener('focus', handleFocus, true);
9801
- swiper.el.removeEventListener('pointerdown', handlePointerDown, true);
9802
- swiper.el.removeEventListener('pointerup', handlePointerUp, true);
9803
- }
10580
+ swiper.el.removeEventListener('focus', handleFocus, true);
10581
+ swiper.el.removeEventListener('pointerdown', handlePointerDown, true);
10582
+ swiper.el.removeEventListener('pointerup', handlePointerUp, true);
9804
10583
  }
9805
10584
  on('beforeInit', () => {
9806
10585
  liveRegion = createElement('span', swiper.params.a11y.notificationClass);
@@ -9872,7 +10651,7 @@ function Autoplay(_ref) {
9872
10651
  if (!swiper || swiper.destroyed || !swiper.wrapperEl) return;
9873
10652
  if (e.target !== swiper.wrapperEl) return;
9874
10653
  swiper.wrapperEl.removeEventListener('transitionend', onTransitionEnd);
9875
- if (pausedByPointerEnter || e.detail && e.detail.bySwiperTouchMove) {
10654
+ if (pausedByPointerEnter) {
9876
10655
  return;
9877
10656
  }
9878
10657
  resume();
@@ -10043,10 +10822,8 @@ function Autoplay(_ref) {
10043
10822
  }
10044
10823
  };
10045
10824
  const detachMouseEvents = () => {
10046
- if (swiper.el && typeof swiper.el !== 'string') {
10047
- swiper.el.removeEventListener('pointerenter', onPointerEnter);
10048
- swiper.el.removeEventListener('pointerleave', onPointerLeave);
10049
- }
10825
+ swiper.el.removeEventListener('pointerenter', onPointerEnter);
10826
+ swiper.el.removeEventListener('pointerleave', onPointerLeave);
10050
10827
  };
10051
10828
  const attachDocumentEvents = () => {
10052
10829
  const document = getDocument();
@@ -10384,49 +11161,6 @@ const Scroll = ({ children, isPadding = true, style, enableSlideActive = false }
10384
11161
  };
10385
11162
  var Scroll$1 = React.memo(Scroll);
10386
11163
 
10387
- const FormatImage = React.forwardRef((props, ref) => {
10388
- const { src, onLoad, style, className, loading, alt = 'image' } = props;
10389
- const [imgSrc, setImgSrc] = React.useState(src);
10390
- const imgRef = React.useRef(null);
10391
- const [visible, setVisible] = React.useState(false);
10392
- React.useImperativeHandle(ref, () => ({
10393
- setSrc: (v) => {
10394
- if (v)
10395
- setImgSrc(v);
10396
- }
10397
- }));
10398
- React.useEffect(() => {
10399
- if (src)
10400
- setImgSrc(src);
10401
- }, [src]);
10402
- React.useEffect(() => {
10403
- const onShow = () => {
10404
- if (src && !visible && imgRef.current) {
10405
- imgRef.current.src = '';
10406
- imgRef.current.src = src;
10407
- }
10408
- };
10409
- SXP_EVENT_BUS.on(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
10410
- return () => {
10411
- SXP_EVENT_BUS.off(SXP_EVENT_TYPE.PAGE_DID_SHOW, onShow);
10412
- };
10413
- }, [src, visible]);
10414
- return (React.createElement(React.Fragment, null,
10415
- !visible && !imgSrc && React.createElement("div", { style: { width: '100%', height: '100%', zIndex: 1, backgroundColor: '#fff' } }),
10416
- (imgSrc === null || imgSrc === void 0 ? void 0 : imgSrc.includes('.avif')) ? (React.createElement("picture", null,
10417
- React.createElement("source", { type: 'image/avif', srcSet: imgSrc }),
10418
- React.createElement("source", { type: 'image/webp', srcSet: `${imgSrc}?imageMogr2/format/webp` }),
10419
- React.createElement("source", { type: 'image/jpeg', srcSet: `${imgSrc}?imageMogr2/format/jpg` }),
10420
- React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
10421
- setVisible(true);
10422
- onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
10423
- }, alt: alt }))) : (React.createElement("img", { ref: imgRef, className: className, src: imgSrc, style: Object.assign({}, style), loading: loading, onLoad: (e) => {
10424
- setVisible(true);
10425
- onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
10426
- }, alt: alt }))));
10427
- });
10428
- var FormatImage$1 = React.memo(FormatImage);
10429
-
10430
11164
  const CommodityGroup = ({ products, data, defImg, style, onCLick, popupDetailData, check }) => {
10431
11165
  var _a;
10432
11166
  const { productView } = useEventReport();
@@ -10516,13 +11250,13 @@ function useVisibleHeight() {
10516
11250
  styleElement.id = 'onetrust-pc-sdk';
10517
11251
  styleElement.setAttribute('type', 'text/css');
10518
11252
  document.head.appendChild(styleElement);
10519
- const css = `
10520
- #onetrust-pc-sdk {
10521
- height: ${finalHeight}px !important;
10522
- }
10523
- #onetrust-pc-sdk #ot-pc-content{
10524
- bottom: ${b}px !important;
10525
- }
11253
+ const css = `
11254
+ #onetrust-pc-sdk {
11255
+ height: ${finalHeight}px !important;
11256
+ }
11257
+ #onetrust-pc-sdk #ot-pc-content{
11258
+ bottom: ${b}px !important;
11259
+ }
10526
11260
  `;
10527
11261
  styleElement.textContent = css;
10528
11262
  }
@@ -11069,10 +11803,10 @@ const CommodityDetail$1 = (_a) => {
11069
11803
  __html: setFontForText((_c = product === null || product === void 0 ? void 0 : product.taxInfo) !== null && _c !== void 0 ? _c : '税费', commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.taxInfo)
11070
11804
  } }),
11071
11805
  React.createElement("div", { hidden: !!product && (!(product === null || product === void 0 ? void 0 : product.info) || (product === null || product === void 0 ? void 0 : product.info) === '') },
11072
- React.createElement(ExpandableText$1, { foldText: tipText === null || tipText === void 0 ? void 0 : tipText.foldText, unfoldText: tipText === null || tipText === void 0 ? void 0 : tipText.unfoldText, onClick: () => setShowModal(true), isPost: isPost, text: (_d = product === null || product === void 0 ? void 0 : product.info) !== null && _d !== void 0 ? _d : `The design inspiration of Tiffany Lock series comes from the power of connection and inclusiveness, and the
11073
- bold and avant-garde visual design interprets the emotional bond connecting my heart. The Tiffany Lock
11074
- collection is unisex and is inspired by the padlock pattern found in the Tiffany Antique Collection. This
11075
- necklace features a stylish and eye-catching oval clasp chain decorated with a lock pattern. Crafted from
11806
+ 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
11807
+ bold and avant-garde visual design interprets the emotional bond connecting my heart. The Tiffany Lock
11808
+ collection is unisex and is inspired by the padlock pattern found in the Tiffany Antique Collection. This
11809
+ necklace features a stylish and eye-catching oval clasp chain decorated with a lock pattern. Crafted from
11076
11810
  18-karat gold, this necklace is embellished with hand-set diamonds.`, maxStr: 79, className: 'pb-commondity-content-info', style: commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.info }))));
11077
11811
  };
11078
11812
  const renderBtn = () => {
@@ -12071,7 +12805,7 @@ const CommodityDetailDiroNew$1 = (_a) => {
12071
12805
  const productInfoText = ({ isPost }) => {
12072
12806
  return (React.createElement("div", { hidden: !!product && (!(product === null || product === void 0 ? void 0 : product.info) || (product === null || product === void 0 ? void 0 : product.info) === '') },
12073
12807
  React.createElement(ExpandableText$1, { isPost: isPost, onClick: () => setShowModal(true), className: 'pb-commondityDiroNew-info', style: commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.info, foldText: tipText === null || tipText === void 0 ? void 0 : tipText.foldText, unfoldText: tipText === null || tipText === void 0 ? void 0 : tipText.unfoldText, text: (product === null || product === void 0 ? void 0 : product.info) ||
12074
- `Unveiled at the Spring-Summer 2023 fashion show, the Dior Toujours bag is distinguished by a casual and practical design. Crafted in black calfskin with Macrocannage topstitching, it showcases a spacious interior compartment with a matching pouch to organize essentials. Its leather strap closure keeps items secure while the D of the CD Lock closure twists to adjust the sides and enhance the bag's silhouette. The leather handles can be adjusted using the small notches in order to be able to carry the large bag by hand or wear it over the shoulder. CD Lock and strap closures D.I.O.R. charms Removable interior pouch Adjustable leather handles Dust bag included
12808
+ `Unveiled at the Spring-Summer 2023 fashion show, the Dior Toujours bag is distinguished by a casual and practical design. Crafted in black calfskin with Macrocannage topstitching, it showcases a spacious interior compartment with a matching pouch to organize essentials. Its leather strap closure keeps items secure while the D of the CD Lock closure twists to adjust the sides and enhance the bag's silhouette. The leather handles can be adjusted using the small notches in order to be able to carry the large bag by hand or wear it over the shoulder. CD Lock and strap closures D.I.O.R. charms Removable interior pouch Adjustable leather handles Dust bag included
12075
12809
  Made in Italy` })));
12076
12810
  };
12077
12811
  const getStyle = React.useCallback((style) => {
@@ -18253,10 +18987,10 @@ const MultiPosts$1 = (_a) => {
18253
18987
  const traceInfo = ((_b = recData === null || recData === void 0 ? void 0 : recData.video) === null || _b === void 0 ? void 0 : _b.traceInfo) || ((_c = recData === null || recData === void 0 ? void 0 : recData.product) === null || _c === void 0 ? void 0 : _c.traceInfo) || '';
18254
18988
  const getPropsVal = React.useCallback((index, str) => {
18255
18989
  try {
18256
- return new Function('props', 'str', `if (str) {
18257
- return props?.button${index + 1}${str}
18258
- } else {
18259
- return props?.button${index + 1}
18990
+ return new Function('props', 'str', `if (str) {
18991
+ return props?.button${index + 1}${str}
18992
+ } else {
18993
+ return props?.button${index + 1}
18260
18994
  }`)(props, str);
18261
18995
  }
18262
18996
  catch (_a) { }
@@ -20139,10 +20873,16 @@ const SxpPageRender = ({ globalConfig, descStyle, containerHeight, containerWidt
20139
20873
  React.createElement(Swiper, { style: {
20140
20874
  marginTop: tagHeight
20141
20875
  }, ref: swiperRef, onSlideChange: () => {
20142
- swiperRef.current.swiper.allowTouchMove = false;
20143
- setTimeout(() => {
20144
- swiperRef.current.swiper.allowTouchMove = true;
20145
- }, 500);
20876
+ var _a;
20877
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
20878
+ swiperRef.current.swiper.allowTouchMove = false;
20879
+ setTimeout(() => {
20880
+ var _a;
20881
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
20882
+ swiperRef.current.swiper.allowTouchMove = true;
20883
+ }
20884
+ }, 500);
20885
+ }
20146
20886
  }, onActiveIndexChange: (swiper) => {
20147
20887
  var _a, _b;
20148
20888
  setActiveIndex(swiper.activeIndex);
@@ -21035,10 +21775,16 @@ const DiyStoryPreview = React.forwardRef(({ data = [], globalConfig, tipText, nu
21035
21775
  // className={style['clc-sxp-container']}
21036
21776
  style: { height: containerHeight, position: 'relative', pointerEvents } },
21037
21777
  React.createElement(Swiper, { ref: swiperRef, allowTouchMove: pointerEvents !== 'none', onSlideChange: () => {
21038
- swiperRef.current.swiper.allowTouchMove = false;
21039
- setTimeout(() => {
21040
- swiperRef.current.swiper.allowTouchMove = true;
21041
- }, 500);
21778
+ var _a;
21779
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
21780
+ swiperRef.current.swiper.allowTouchMove = false;
21781
+ setTimeout(() => {
21782
+ var _a;
21783
+ if ((_a = swiperRef.current) === null || _a === void 0 ? void 0 : _a.swiper) {
21784
+ swiperRef.current.swiper.allowTouchMove = true;
21785
+ }
21786
+ }, 500);
21787
+ }
21042
21788
  }, onActiveIndexChange: (swiper) => {
21043
21789
  setCurIndex(swiper === null || swiper === void 0 ? void 0 : swiper.activeIndex);
21044
21790
  onActiveChange === null || onActiveChange === void 0 ? void 0 : onActiveChange(swiper.activeIndex);
@@ -21194,6 +21940,7 @@ exports.DiyPortalPreview = index$2;
21194
21940
  exports.DiyStoryPreview = index$1;
21195
21941
  exports.EditorDataProvider = EditorDataProvider;
21196
21942
  exports.Modal = Modal$1;
21943
+ exports.StructurePage = StructurePage;
21197
21944
  exports.SxpDataSourceProvider = SxpDataSourceProvider$1;
21198
21945
  exports.SxpPageCore = index;
21199
21946
  exports.SxpPageRender = SxpPageRender$1;