pb-sxp-ui 1.0.24 → 1.0.26

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 (31) hide show
  1. package/dist/index.cjs +100 -34
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +100 -34
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.min.cjs +3 -3
  6. package/dist/index.min.cjs.map +1 -1
  7. package/dist/index.min.js +3 -3
  8. package/dist/index.min.js.map +1 -1
  9. package/dist/pb-ui.js +100 -34
  10. package/dist/pb-ui.js.map +1 -1
  11. package/dist/pb-ui.min.js +3 -3
  12. package/dist/pb-ui.min.js.map +1 -1
  13. package/es/core/components/SxpPageRender/FormatImage.js +7 -6
  14. package/es/core/components/SxpPageRender/PictureGroup/Picture.d.ts +3 -2
  15. package/es/core/components/SxpPageRender/PictureGroup/Picture.js +13 -13
  16. package/es/core/components/SxpPageRender/PictureGroup/index.d.ts +2 -0
  17. package/es/core/components/SxpPageRender/PictureGroup/index.js +4 -3
  18. package/es/core/components/SxpPageRender/VideoWidget/index.d.ts +2 -0
  19. package/es/core/components/SxpPageRender/VideoWidget/index.js +73 -8
  20. package/es/core/components/SxpPageRender/index.d.ts +8 -1
  21. package/es/core/components/SxpPageRender/index.js +2 -2
  22. package/lib/core/components/SxpPageRender/FormatImage.js +6 -5
  23. package/lib/core/components/SxpPageRender/PictureGroup/Picture.d.ts +3 -2
  24. package/lib/core/components/SxpPageRender/PictureGroup/Picture.js +12 -12
  25. package/lib/core/components/SxpPageRender/PictureGroup/index.d.ts +2 -0
  26. package/lib/core/components/SxpPageRender/PictureGroup/index.js +4 -3
  27. package/lib/core/components/SxpPageRender/VideoWidget/index.d.ts +2 -0
  28. package/lib/core/components/SxpPageRender/VideoWidget/index.js +73 -8
  29. package/lib/core/components/SxpPageRender/index.d.ts +8 -1
  30. package/lib/core/components/SxpPageRender/index.js +2 -2
  31. package/package.json +1 -1
@@ -1,15 +1,16 @@
1
- import React, { forwardRef, memo, useImperativeHandle, useState } from 'react';
1
+ import React, { forwardRef, memo, useEffect, useImperativeHandle, useState } from 'react';
2
2
  const FormatImage = forwardRef((props, ref) => {
3
3
  const { src, onLoad, style, className, loading } = props;
4
- const [imgSrc, setImgSrc] = useState(src);
4
+ const [imgSrc, setImgSrc] = useState();
5
5
  useImperativeHandle(ref, () => ({
6
6
  setSrc: (v) => {
7
7
  setImgSrc(v);
8
8
  }
9
9
  }));
10
- if (imgSrc === '' || !imgSrc)
11
- return null;
12
- return (imgSrc === null || imgSrc === void 0 ? void 0 : imgSrc.includes('.avif')) ? (React.createElement("picture", null,
10
+ useEffect(() => {
11
+ setImgSrc(src);
12
+ }, [src]);
13
+ return (React.createElement(React.Fragment, null, (imgSrc === null || imgSrc === void 0 ? void 0 : imgSrc.includes('.avif')) ? (React.createElement("picture", null,
13
14
  React.createElement("source", { type: 'image/avif', srcSet: imgSrc }),
14
15
  React.createElement("source", { type: 'image/webp', srcSet: `${imgSrc}?imageMogr2/format/webp` }),
15
16
  React.createElement("source", { type: 'image/jpeg', srcSet: `${imgSrc}?imageMogr2/format/jpg` }),
@@ -17,6 +18,6 @@ const FormatImage = forwardRef((props, ref) => {
17
18
  onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
18
19
  } }))) : (React.createElement("img", { className: className, src: imgSrc, style: style, loading: loading, onLoad: (e) => {
19
20
  onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
20
- } }));
21
+ } }))));
21
22
  });
22
23
  export default memo(FormatImage);
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
+ import { postConfigType } from '..';
2
3
  interface IPictureProps {
3
4
  src: string;
4
- height: number;
5
- width: number;
5
+ height?: number;
6
+ imgUrlsPostConfig?: postConfigType;
6
7
  }
7
8
  declare const Picture: (props: IPictureProps) => React.JSX.Element;
8
9
  export default Picture;
@@ -1,16 +1,16 @@
1
- import React, { useState } from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import FormatImage from '../FormatImage';
3
3
  const Picture = (props) => {
4
- const { src, height, width } = props;
5
- const [blur, setBlur] = useState(false);
6
- const onLoad = (img) => {
7
- const aspectRatio = img.naturalHeight / img.naturalWidth;
8
- const targetAspectRatio = 16 / 9;
9
- const tolerance = 0.05;
10
- if (Math.abs(aspectRatio - targetAspectRatio) > tolerance) {
11
- setBlur(true);
12
- }
13
- };
4
+ const { src, height, imgUrlsPostConfig } = props;
5
+ const blur = useMemo(() => {
6
+ return (imgUrlsPostConfig === null || imgUrlsPostConfig === void 0 ? void 0 : imgUrlsPostConfig.mode) === '2';
7
+ }, [imgUrlsPostConfig]);
8
+ const translateY = useMemo(() => {
9
+ var _a;
10
+ return (imgUrlsPostConfig === null || imgUrlsPostConfig === void 0 ? void 0 : imgUrlsPostConfig.mode) === '2'
11
+ ? `translateY(-${50 + ((_a = imgUrlsPostConfig === null || imgUrlsPostConfig === void 0 ? void 0 : imgUrlsPostConfig.offsetTop) !== null && _a !== void 0 ? _a : 0)}%)`
12
+ : 'translateY(-50%)';
13
+ }, [imgUrlsPostConfig]);
14
14
  return (React.createElement("div", { style: {
15
15
  overflow: 'hidden',
16
16
  height,
@@ -23,13 +23,13 @@ const Picture = (props) => {
23
23
  objectFit: 'cover',
24
24
  filter: blur ? 'blur(10px)' : 'none',
25
25
  transform: blur ? 'scale(1.2)' : 'none'
26
- }, onLoad: onLoad }),
26
+ } }),
27
27
  blur && (React.createElement(FormatImage, { src: src, style: {
28
28
  width: '100%',
29
29
  objectFit: 'contain',
30
30
  position: 'absolute',
31
31
  top: '50%',
32
- transform: 'translateY(-50%)',
32
+ transform: translateY,
33
33
  left: 0,
34
34
  right: 0
35
35
  } }))));
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { RecItemType } from '../typing';
3
+ import { postConfigType } from '..';
3
4
  interface IPictureGroupProps {
4
5
  imgUrls?: string[];
5
6
  width: number;
@@ -8,6 +9,7 @@ interface IPictureGroupProps {
8
9
  index: number;
9
10
  onReportViewImageEnd: (rec: RecItemType) => void;
10
11
  onViewImageStartEvent: (index: number) => void;
12
+ imgUrlsPostConfig?: postConfigType;
11
13
  }
12
14
  declare const _default: React.NamedExoticComponent<IPictureGroupProps>;
13
15
  export default _default;
@@ -3,7 +3,8 @@ import { Autoplay, Pagination } from 'swiper/modules';
3
3
  import { Swiper, SwiperSlide, useSwiperSlide } from 'swiper/react';
4
4
  import Picture from './Picture';
5
5
  import { useSxpDataSource } from '../../../../core/hooks';
6
- const PictureGroup = ({ imgUrls, width, height, rec, index, onReportViewImageEnd, onViewImageStartEvent }) => {
6
+ const PictureGroup = ({ imgUrls, width, height, rec, index, onReportViewImageEnd, onViewImageStartEvent, imgUrlsPostConfig }) => {
7
+ var _a;
7
8
  const ref = useRef();
8
9
  const { isActive } = useSwiperSlide();
9
10
  const { sxpParameter, openHashtag } = useSxpDataSource();
@@ -23,9 +24,9 @@ const PictureGroup = ({ imgUrls, width, height, rec, index, onReportViewImageEnd
23
24
  (ref === null || ref === void 0 ? void 0 : ref.current) && ref.current.swiper.autoplay.stop();
24
25
  }
25
26
  }, [rec, isActive, onReportViewImageEnd, openHashtag, index, onViewImageStartEvent, isLoad]);
26
- return (React.createElement(Swiper, { ref: ref, defaultValue: 0, direction: 'horizontal', modules: [Pagination, Autoplay], pagination: { clickable: true, bulletActiveClass: 'swipe-item-active-bullet' }, height: height, loop: true, autoplay: { delay: 3000 } }, imgUrls === null || imgUrls === void 0 ? void 0 : imgUrls.map((url) => {
27
+ return (React.createElement(Swiper, { ref: ref, defaultValue: 0, direction: 'horizontal', modules: [Pagination, Autoplay], pagination: { clickable: true, bulletActiveClass: 'swipe-item-active-bullet' }, height: height, loop: true, autoplay: { delay: ((_a = imgUrlsPostConfig === null || imgUrlsPostConfig === void 0 ? void 0 : imgUrlsPostConfig.delay) !== null && _a !== void 0 ? _a : 3) * 1000 } }, imgUrls === null || imgUrls === void 0 ? void 0 : imgUrls.map((url) => {
27
28
  return (React.createElement(SwiperSlide, { key: url },
28
- React.createElement(Picture, { src: url, width: width, height: height })));
29
+ React.createElement(Picture, { src: url, height: height, imgUrlsPostConfig: imgUrlsPostConfig })));
29
30
  })));
30
31
  };
31
32
  export default memo(PictureGroup);
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { RecItemType } from '../typing';
3
+ import { postConfigType } from '..';
3
4
  interface IVideoWidgetProps {
4
5
  rec: RecItemType;
5
6
  index: number;
@@ -7,6 +8,7 @@ interface IVideoWidgetProps {
7
8
  data: RecItemType[];
8
9
  muted: boolean;
9
10
  activeIndex?: number;
11
+ videoPostConfig?: postConfigType;
10
12
  }
11
13
  declare const _default: React.NamedExoticComponent<IVideoWidgetProps>;
12
14
  export default _default;
@@ -1,9 +1,10 @@
1
1
  import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
2
  import { useSwiperSlide } from 'swiper/react';
3
3
  import { useIconLink } from '../useIconLink';
4
+ import FormatImage from '../FormatImage';
4
5
  import { useSxpDataSource } from '../../../../core/hooks';
5
6
  import SXP_EVENT_BUS, { SXP_EVENT_TYPE } from '../../../../core/utils/event';
6
- const VideoWidget = ({ rec, index, height, data, muted, activeIndex }) => {
7
+ const VideoWidget = ({ rec, index, height, data, muted, activeIndex, videoPostConfig }) => {
7
8
  const [isPauseVideo, setIsPauseVideo] = useState(false);
8
9
  const videoRef = useRef(null);
9
10
  const { bffEventReport, sxpParameter, waterFallData, openHashtag } = useSxpDataSource();
@@ -11,6 +12,8 @@ const VideoWidget = ({ rec, index, height, data, muted, activeIndex }) => {
11
12
  const [isLoadFinish, setIsLoadFinish] = useState(false);
12
13
  const [isFirstPlay, setIsFirstPlay] = useState(true);
13
14
  const { isActive } = useSwiperSlide();
15
+ const canvasRef = useRef(null);
16
+ const [firstFrameSrc, setFirstFrameSrc] = useState('');
14
17
  useEffect(() => {
15
18
  if (!videoRef.current)
16
19
  return;
@@ -104,8 +107,24 @@ const VideoWidget = ({ rec, index, height, data, muted, activeIndex }) => {
104
107
  });
105
108
  }
106
109
  }, [data, index, bffEventReport]);
110
+ const handLoadeddata = useCallback(() => {
111
+ const video = videoRef === null || videoRef === void 0 ? void 0 : videoRef.current;
112
+ if (!video)
113
+ return;
114
+ const canvas = canvasRef === null || canvasRef === void 0 ? void 0 : canvasRef.current;
115
+ if (!canvas)
116
+ return;
117
+ const ctx = canvas.getContext('2d');
118
+ const targetWidth = window === null || window === void 0 ? void 0 : window.innerWidth;
119
+ const targetHeight = window === null || window === void 0 ? void 0 : window.innerHeight;
120
+ canvas.height = targetHeight;
121
+ canvas.width = targetWidth;
122
+ ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
123
+ setFirstFrameSrc(canvas.toDataURL());
124
+ canvas.remove();
125
+ }, []);
107
126
  useEffect(() => {
108
- var _a, _b;
127
+ var _a, _b, _c;
109
128
  if (!videoRef.current)
110
129
  return;
111
130
  setIsPauseVideo(false);
@@ -117,12 +136,14 @@ const VideoWidget = ({ rec, index, height, data, muted, activeIndex }) => {
117
136
  }
118
137
  (_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('canplay', handleLoadedMetadata);
119
138
  (_b = videoRef.current) === null || _b === void 0 ? void 0 : _b.addEventListener('playing', handlePlaying);
139
+ (_c = videoRef.current) === null || _c === void 0 ? void 0 : _c.addEventListener('loadeddata', handLoadeddata);
120
140
  return () => {
121
- var _a, _b;
141
+ var _a, _b, _c;
122
142
  (_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('canplay', handleLoadedMetadata);
123
143
  (_b = videoRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('playing', handlePlaying);
144
+ (_c = videoRef.current) === null || _c === void 0 ? void 0 : _c.removeEventListener('loadeddata', handLoadeddata);
124
145
  };
125
- }, [handleLoadedMetadata, handlePlaying, rec.video]);
146
+ }, [handleLoadedMetadata, handlePlaying, rec.video, handLoadeddata]);
126
147
  useEffect(() => {
127
148
  var _a;
128
149
  if (!(videoRef === null || videoRef === void 0 ? void 0 : videoRef.current) || !isLoadFinish)
@@ -176,16 +197,60 @@ const VideoWidget = ({ rec, index, height, data, muted, activeIndex }) => {
176
197
  window.removeEventListener('beforeunload', handleBeforeUnload);
177
198
  };
178
199
  }, [activeIndex, index, rec, videoRef, handleClickVideo, isPauseVideo]);
200
+ const blur = useMemo(() => {
201
+ return (videoPostConfig === null || videoPostConfig === void 0 ? void 0 : videoPostConfig.mode) === '2';
202
+ }, [videoPostConfig]);
203
+ const translateY = useMemo(() => {
204
+ var _a;
205
+ return (videoPostConfig === null || videoPostConfig === void 0 ? void 0 : videoPostConfig.mode) === '2'
206
+ ? `translateY(-${50 + ((_a = videoPostConfig === null || videoPostConfig === void 0 ? void 0 : videoPostConfig.offsetTop) !== null && _a !== void 0 ? _a : 0)}%)`
207
+ : 'translateY(-50%)';
208
+ }, [videoPostConfig]);
209
+ const blurBgSrc = useMemo(() => {
210
+ var _a;
211
+ return ((_a = rec === null || rec === void 0 ? void 0 : rec.video) === null || _a === void 0 ? void 0 : _a.cover) || firstFrameSrc;
212
+ }, [firstFrameSrc, rec]);
179
213
  if (!rec.video) {
180
214
  return null;
181
215
  }
182
- return (React.createElement("div", { className: 'video-container', key: rec.video.itemId, onClick: handleClickVideo(), style: {
216
+ return (React.createElement(React.Fragment, null, blur ? (React.createElement("div", { className: 'video-container', key: rec.video.itemId, onClick: handleClickVideo(), style: {
217
+ position: 'relative',
218
+ width: '100%',
219
+ height,
220
+ overflow: 'hidden'
221
+ } },
222
+ React.createElement(FormatImage, { src: blurBgSrc, style: {
223
+ height: '100%',
224
+ width: '100%',
225
+ objectFit: 'cover',
226
+ filter: blur ? 'blur(10px)' : 'none',
227
+ transform: blur ? 'scale(1.2)' : 'none'
228
+ } }),
229
+ React.createElement("canvas", { ref: canvasRef, style: { display: 'none' } }),
230
+ React.createElement("div", { style: {
231
+ position: 'absolute',
232
+ width: '100%',
233
+ height: 'auto',
234
+ top: '50%',
235
+ transform: translateY,
236
+ left: 0,
237
+ right: 0
238
+ } },
239
+ React.createElement("div", { style: { position: 'relative' } },
240
+ React.createElement("video", { id: `pb-video-${index}`, className: 'clc-pb-video', ref: videoRef, crossOrigin: 'anonymous', poster: sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.placeholder_image, muted: true, controls: false, playsInline: true, preload: 'auto', onPause: onPause, onEnded: handleVideoStart, style: {
241
+ width: '100%',
242
+ height: 'auto',
243
+ objectFit: 'contain'
244
+ } }),
245
+ renderPoster,
246
+ React.createElement("img", { hidden: !isPauseVideo, className: 'clc-pb-video-pause', src: PAUSE_ICON }))))) : (React.createElement("div", { className: 'video-container', key: rec.video.itemId, onClick: handleClickVideo(), style: {
183
247
  position: 'relative',
184
248
  width: '100%',
185
- height
249
+ height,
250
+ overflow: 'hidden'
186
251
  } },
187
- React.createElement("video", { id: `pb-video-${index}`, className: 'clc-pb-video', ref: videoRef, poster: sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.placeholder_image, muted: true, controls: false, playsInline: true, preload: 'auto', onPause: onPause, onEnded: handleVideoStart }),
252
+ React.createElement("video", { id: `pb-video-${index}`, className: 'clc-pb-video', ref: videoRef, crossOrigin: 'anonymous', poster: sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.placeholder_image, muted: true, controls: false, playsInline: true, preload: 'auto', onPause: onPause, onEnded: handleVideoStart }),
188
253
  renderPoster,
189
- React.createElement("img", { hidden: !isPauseVideo, className: 'clc-pb-video-pause', src: PAUSE_ICON })));
254
+ React.createElement("img", { hidden: !isPauseVideo, className: 'clc-pb-video-pause', src: PAUSE_ICON })))));
190
255
  };
191
256
  export default memo(VideoWidget);
@@ -1,7 +1,12 @@
1
1
  import { CSSProperties, FC } from 'react';
2
2
  import { RecItemType } from './typing';
3
3
  import './index.less';
4
- interface ISxpPageRenderProps {
4
+ export type postConfigType = {
5
+ mode?: '1' | '2';
6
+ offsetTop?: number;
7
+ delay?: number;
8
+ };
9
+ export interface ISxpPageRenderProps {
5
10
  globalConfig?: {
6
11
  isShowLogo?: boolean;
7
12
  logoUrl?: string;
@@ -19,6 +24,8 @@ interface ISxpPageRenderProps {
19
24
  swipeTipIcon?: string;
20
25
  hashTag?: any[];
21
26
  isOpenTextShadow?: boolean;
27
+ videoPost?: postConfigType;
28
+ imgUrlsPost?: postConfigType;
22
29
  };
23
30
  descStyle?: CSSProperties;
24
31
  tipText?: {
@@ -153,10 +153,10 @@ const SxpPageRender = ({ globalConfig, descStyle, containerHeight = window.inner
153
153
  const renderContent = useCallback((rec, index) => {
154
154
  var _a, _b, _c, _d;
155
155
  if ((_a = rec.video) === null || _a === void 0 ? void 0 : _a.url) {
156
- return (React.createElement(VideoWidget, { rec: rec, index: index, muted: isMuted, data: data, height: height, activeIndex: activeIndex }));
156
+ return (React.createElement(VideoWidget, { rec: rec, index: index, muted: isMuted, data: data, height: height, activeIndex: activeIndex, videoPostConfig: globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.videoPost }));
157
157
  }
158
158
  if ((_b = rec.video) === null || _b === void 0 ? void 0 : _b.imgUrls) {
159
- return (React.createElement(PictureGroup, { key: rec.video.itemId, imgUrls: rec.video.imgUrls, width: containerWidth, height: height, rec: rec, index: index, onReportViewImageEnd: handleReportViewImageEnd, onViewImageStartEvent: handleViewImageStartEvent }));
159
+ return (React.createElement(PictureGroup, { key: rec.video.itemId, imgUrls: rec.video.imgUrls, width: containerWidth, height: height, rec: rec, index: index, onReportViewImageEnd: handleReportViewImageEnd, onViewImageStartEvent: handleViewImageStartEvent, imgUrlsPostConfig: globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.imgUrlsPost }));
160
160
  }
161
161
  if (rec.product && Array.isArray(globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.productPost) && ((_c = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.productPost) === null || _c === void 0 ? void 0 : _c.length) > 0) {
162
162
  return (_d = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.productPost) === null || _d === void 0 ? void 0 : _d.map((value, idx) => {
@@ -4,15 +4,16 @@ const tslib_1 = require("tslib");
4
4
  const react_1 = tslib_1.__importStar(require("react"));
5
5
  const FormatImage = (0, react_1.forwardRef)((props, ref) => {
6
6
  const { src, onLoad, style, className, loading } = props;
7
- const [imgSrc, setImgSrc] = (0, react_1.useState)(src);
7
+ const [imgSrc, setImgSrc] = (0, react_1.useState)();
8
8
  (0, react_1.useImperativeHandle)(ref, () => ({
9
9
  setSrc: (v) => {
10
10
  setImgSrc(v);
11
11
  }
12
12
  }));
13
- if (imgSrc === '' || !imgSrc)
14
- return null;
15
- return (imgSrc === null || imgSrc === void 0 ? void 0 : imgSrc.includes('.avif')) ? (react_1.default.createElement("picture", null,
13
+ (0, react_1.useEffect)(() => {
14
+ setImgSrc(src);
15
+ }, [src]);
16
+ return (react_1.default.createElement(react_1.default.Fragment, null, (imgSrc === null || imgSrc === void 0 ? void 0 : imgSrc.includes('.avif')) ? (react_1.default.createElement("picture", null,
16
17
  react_1.default.createElement("source", { type: 'image/avif', srcSet: imgSrc }),
17
18
  react_1.default.createElement("source", { type: 'image/webp', srcSet: `${imgSrc}?imageMogr2/format/webp` }),
18
19
  react_1.default.createElement("source", { type: 'image/jpeg', srcSet: `${imgSrc}?imageMogr2/format/jpg` }),
@@ -20,6 +21,6 @@ const FormatImage = (0, react_1.forwardRef)((props, ref) => {
20
21
  onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
21
22
  } }))) : (react_1.default.createElement("img", { className: className, src: imgSrc, style: style, loading: loading, onLoad: (e) => {
22
23
  onLoad === null || onLoad === void 0 ? void 0 : onLoad(e.target);
23
- } }));
24
+ } }))));
24
25
  });
25
26
  exports.default = (0, react_1.memo)(FormatImage);
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
+ import { postConfigType } from '..';
2
3
  interface IPictureProps {
3
4
  src: string;
4
- height: number;
5
- width: number;
5
+ height?: number;
6
+ imgUrlsPostConfig?: postConfigType;
6
7
  }
7
8
  declare const Picture: (props: IPictureProps) => React.JSX.Element;
8
9
  export default Picture;
@@ -4,16 +4,16 @@ const tslib_1 = require("tslib");
4
4
  const react_1 = tslib_1.__importStar(require("react"));
5
5
  const FormatImage_1 = tslib_1.__importDefault(require("../FormatImage"));
6
6
  const Picture = (props) => {
7
- const { src, height, width } = props;
8
- const [blur, setBlur] = (0, react_1.useState)(false);
9
- const onLoad = (img) => {
10
- const aspectRatio = img.naturalHeight / img.naturalWidth;
11
- const targetAspectRatio = 16 / 9;
12
- const tolerance = 0.05;
13
- if (Math.abs(aspectRatio - targetAspectRatio) > tolerance) {
14
- setBlur(true);
15
- }
16
- };
7
+ const { src, height, imgUrlsPostConfig } = props;
8
+ const blur = (0, react_1.useMemo)(() => {
9
+ return (imgUrlsPostConfig === null || imgUrlsPostConfig === void 0 ? void 0 : imgUrlsPostConfig.mode) === '2';
10
+ }, [imgUrlsPostConfig]);
11
+ const translateY = (0, react_1.useMemo)(() => {
12
+ var _a;
13
+ return (imgUrlsPostConfig === null || imgUrlsPostConfig === void 0 ? void 0 : imgUrlsPostConfig.mode) === '2'
14
+ ? `translateY(-${50 + ((_a = imgUrlsPostConfig === null || imgUrlsPostConfig === void 0 ? void 0 : imgUrlsPostConfig.offsetTop) !== null && _a !== void 0 ? _a : 0)}%)`
15
+ : 'translateY(-50%)';
16
+ }, [imgUrlsPostConfig]);
17
17
  return (react_1.default.createElement("div", { style: {
18
18
  overflow: 'hidden',
19
19
  height,
@@ -26,13 +26,13 @@ const Picture = (props) => {
26
26
  objectFit: 'cover',
27
27
  filter: blur ? 'blur(10px)' : 'none',
28
28
  transform: blur ? 'scale(1.2)' : 'none'
29
- }, onLoad: onLoad }),
29
+ } }),
30
30
  blur && (react_1.default.createElement(FormatImage_1.default, { src: src, style: {
31
31
  width: '100%',
32
32
  objectFit: 'contain',
33
33
  position: 'absolute',
34
34
  top: '50%',
35
- transform: 'translateY(-50%)',
35
+ transform: translateY,
36
36
  left: 0,
37
37
  right: 0
38
38
  } }))));
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { RecItemType } from '../typing';
3
+ import { postConfigType } from '..';
3
4
  interface IPictureGroupProps {
4
5
  imgUrls?: string[];
5
6
  width: number;
@@ -8,6 +9,7 @@ interface IPictureGroupProps {
8
9
  index: number;
9
10
  onReportViewImageEnd: (rec: RecItemType) => void;
10
11
  onViewImageStartEvent: (index: number) => void;
12
+ imgUrlsPostConfig?: postConfigType;
11
13
  }
12
14
  declare const _default: React.NamedExoticComponent<IPictureGroupProps>;
13
15
  export default _default;
@@ -6,7 +6,8 @@ const modules_1 = require("swiper/modules");
6
6
  const react_2 = require("swiper/react");
7
7
  const Picture_1 = tslib_1.__importDefault(require("./Picture"));
8
8
  const hooks_1 = require("../../../../core/hooks");
9
- const PictureGroup = ({ imgUrls, width, height, rec, index, onReportViewImageEnd, onViewImageStartEvent }) => {
9
+ const PictureGroup = ({ imgUrls, width, height, rec, index, onReportViewImageEnd, onViewImageStartEvent, imgUrlsPostConfig }) => {
10
+ var _a;
10
11
  const ref = (0, react_1.useRef)();
11
12
  const { isActive } = (0, react_2.useSwiperSlide)();
12
13
  const { sxpParameter, openHashtag } = (0, hooks_1.useSxpDataSource)();
@@ -26,9 +27,9 @@ const PictureGroup = ({ imgUrls, width, height, rec, index, onReportViewImageEnd
26
27
  (ref === null || ref === void 0 ? void 0 : ref.current) && ref.current.swiper.autoplay.stop();
27
28
  }
28
29
  }, [rec, isActive, onReportViewImageEnd, openHashtag, index, onViewImageStartEvent, isLoad]);
29
- return (react_1.default.createElement(react_2.Swiper, { ref: ref, defaultValue: 0, direction: 'horizontal', modules: [modules_1.Pagination, modules_1.Autoplay], pagination: { clickable: true, bulletActiveClass: 'swipe-item-active-bullet' }, height: height, loop: true, autoplay: { delay: 3000 } }, imgUrls === null || imgUrls === void 0 ? void 0 : imgUrls.map((url) => {
30
+ return (react_1.default.createElement(react_2.Swiper, { ref: ref, defaultValue: 0, direction: 'horizontal', modules: [modules_1.Pagination, modules_1.Autoplay], pagination: { clickable: true, bulletActiveClass: 'swipe-item-active-bullet' }, height: height, loop: true, autoplay: { delay: ((_a = imgUrlsPostConfig === null || imgUrlsPostConfig === void 0 ? void 0 : imgUrlsPostConfig.delay) !== null && _a !== void 0 ? _a : 3) * 1000 } }, imgUrls === null || imgUrls === void 0 ? void 0 : imgUrls.map((url) => {
30
31
  return (react_1.default.createElement(react_2.SwiperSlide, { key: url },
31
- react_1.default.createElement(Picture_1.default, { src: url, width: width, height: height })));
32
+ react_1.default.createElement(Picture_1.default, { src: url, height: height, imgUrlsPostConfig: imgUrlsPostConfig })));
32
33
  })));
33
34
  };
34
35
  exports.default = (0, react_1.memo)(PictureGroup);
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import { RecItemType } from '../typing';
3
+ import { postConfigType } from '..';
3
4
  interface IVideoWidgetProps {
4
5
  rec: RecItemType;
5
6
  index: number;
@@ -7,6 +8,7 @@ interface IVideoWidgetProps {
7
8
  data: RecItemType[];
8
9
  muted: boolean;
9
10
  activeIndex?: number;
11
+ videoPostConfig?: postConfigType;
10
12
  }
11
13
  declare const _default: React.NamedExoticComponent<IVideoWidgetProps>;
12
14
  export default _default;
@@ -4,9 +4,10 @@ const tslib_1 = require("tslib");
4
4
  const react_1 = tslib_1.__importStar(require("react"));
5
5
  const react_2 = require("swiper/react");
6
6
  const useIconLink_1 = require("../useIconLink");
7
+ const FormatImage_1 = tslib_1.__importDefault(require("../FormatImage"));
7
8
  const hooks_1 = require("../../../../core/hooks");
8
9
  const event_1 = tslib_1.__importStar(require("../../../../core/utils/event"));
9
- const VideoWidget = ({ rec, index, height, data, muted, activeIndex }) => {
10
+ const VideoWidget = ({ rec, index, height, data, muted, activeIndex, videoPostConfig }) => {
10
11
  const [isPauseVideo, setIsPauseVideo] = (0, react_1.useState)(false);
11
12
  const videoRef = (0, react_1.useRef)(null);
12
13
  const { bffEventReport, sxpParameter, waterFallData, openHashtag } = (0, hooks_1.useSxpDataSource)();
@@ -14,6 +15,8 @@ const VideoWidget = ({ rec, index, height, data, muted, activeIndex }) => {
14
15
  const [isLoadFinish, setIsLoadFinish] = (0, react_1.useState)(false);
15
16
  const [isFirstPlay, setIsFirstPlay] = (0, react_1.useState)(true);
16
17
  const { isActive } = (0, react_2.useSwiperSlide)();
18
+ const canvasRef = (0, react_1.useRef)(null);
19
+ const [firstFrameSrc, setFirstFrameSrc] = (0, react_1.useState)('');
17
20
  (0, react_1.useEffect)(() => {
18
21
  if (!videoRef.current)
19
22
  return;
@@ -107,8 +110,24 @@ const VideoWidget = ({ rec, index, height, data, muted, activeIndex }) => {
107
110
  });
108
111
  }
109
112
  }, [data, index, bffEventReport]);
113
+ const handLoadeddata = (0, react_1.useCallback)(() => {
114
+ const video = videoRef === null || videoRef === void 0 ? void 0 : videoRef.current;
115
+ if (!video)
116
+ return;
117
+ const canvas = canvasRef === null || canvasRef === void 0 ? void 0 : canvasRef.current;
118
+ if (!canvas)
119
+ return;
120
+ const ctx = canvas.getContext('2d');
121
+ const targetWidth = window === null || window === void 0 ? void 0 : window.innerWidth;
122
+ const targetHeight = window === null || window === void 0 ? void 0 : window.innerHeight;
123
+ canvas.height = targetHeight;
124
+ canvas.width = targetWidth;
125
+ ctx === null || ctx === void 0 ? void 0 : ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
126
+ setFirstFrameSrc(canvas.toDataURL());
127
+ canvas.remove();
128
+ }, []);
110
129
  (0, react_1.useEffect)(() => {
111
- var _a, _b;
130
+ var _a, _b, _c;
112
131
  if (!videoRef.current)
113
132
  return;
114
133
  setIsPauseVideo(false);
@@ -120,12 +139,14 @@ const VideoWidget = ({ rec, index, height, data, muted, activeIndex }) => {
120
139
  }
121
140
  (_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.addEventListener('canplay', handleLoadedMetadata);
122
141
  (_b = videoRef.current) === null || _b === void 0 ? void 0 : _b.addEventListener('playing', handlePlaying);
142
+ (_c = videoRef.current) === null || _c === void 0 ? void 0 : _c.addEventListener('loadeddata', handLoadeddata);
123
143
  return () => {
124
- var _a, _b;
144
+ var _a, _b, _c;
125
145
  (_a = videoRef.current) === null || _a === void 0 ? void 0 : _a.removeEventListener('canplay', handleLoadedMetadata);
126
146
  (_b = videoRef.current) === null || _b === void 0 ? void 0 : _b.removeEventListener('playing', handlePlaying);
147
+ (_c = videoRef.current) === null || _c === void 0 ? void 0 : _c.removeEventListener('loadeddata', handLoadeddata);
127
148
  };
128
- }, [handleLoadedMetadata, handlePlaying, rec.video]);
149
+ }, [handleLoadedMetadata, handlePlaying, rec.video, handLoadeddata]);
129
150
  (0, react_1.useEffect)(() => {
130
151
  var _a;
131
152
  if (!(videoRef === null || videoRef === void 0 ? void 0 : videoRef.current) || !isLoadFinish)
@@ -179,16 +200,60 @@ const VideoWidget = ({ rec, index, height, data, muted, activeIndex }) => {
179
200
  window.removeEventListener('beforeunload', handleBeforeUnload);
180
201
  };
181
202
  }, [activeIndex, index, rec, videoRef, handleClickVideo, isPauseVideo]);
203
+ const blur = (0, react_1.useMemo)(() => {
204
+ return (videoPostConfig === null || videoPostConfig === void 0 ? void 0 : videoPostConfig.mode) === '2';
205
+ }, [videoPostConfig]);
206
+ const translateY = (0, react_1.useMemo)(() => {
207
+ var _a;
208
+ return (videoPostConfig === null || videoPostConfig === void 0 ? void 0 : videoPostConfig.mode) === '2'
209
+ ? `translateY(-${50 + ((_a = videoPostConfig === null || videoPostConfig === void 0 ? void 0 : videoPostConfig.offsetTop) !== null && _a !== void 0 ? _a : 0)}%)`
210
+ : 'translateY(-50%)';
211
+ }, [videoPostConfig]);
212
+ const blurBgSrc = (0, react_1.useMemo)(() => {
213
+ var _a;
214
+ return ((_a = rec === null || rec === void 0 ? void 0 : rec.video) === null || _a === void 0 ? void 0 : _a.cover) || firstFrameSrc;
215
+ }, [firstFrameSrc, rec]);
182
216
  if (!rec.video) {
183
217
  return null;
184
218
  }
185
- return (react_1.default.createElement("div", { className: 'video-container', key: rec.video.itemId, onClick: handleClickVideo(), style: {
219
+ return (react_1.default.createElement(react_1.default.Fragment, null, blur ? (react_1.default.createElement("div", { className: 'video-container', key: rec.video.itemId, onClick: handleClickVideo(), style: {
220
+ position: 'relative',
221
+ width: '100%',
222
+ height,
223
+ overflow: 'hidden'
224
+ } },
225
+ react_1.default.createElement(FormatImage_1.default, { src: blurBgSrc, style: {
226
+ height: '100%',
227
+ width: '100%',
228
+ objectFit: 'cover',
229
+ filter: blur ? 'blur(10px)' : 'none',
230
+ transform: blur ? 'scale(1.2)' : 'none'
231
+ } }),
232
+ react_1.default.createElement("canvas", { ref: canvasRef, style: { display: 'none' } }),
233
+ react_1.default.createElement("div", { style: {
234
+ position: 'absolute',
235
+ width: '100%',
236
+ height: 'auto',
237
+ top: '50%',
238
+ transform: translateY,
239
+ left: 0,
240
+ right: 0
241
+ } },
242
+ react_1.default.createElement("div", { style: { position: 'relative' } },
243
+ react_1.default.createElement("video", { id: `pb-video-${index}`, className: 'clc-pb-video', ref: videoRef, crossOrigin: 'anonymous', poster: sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.placeholder_image, muted: true, controls: false, playsInline: true, preload: 'auto', onPause: onPause, onEnded: handleVideoStart, style: {
244
+ width: '100%',
245
+ height: 'auto',
246
+ objectFit: 'contain'
247
+ } }),
248
+ renderPoster,
249
+ react_1.default.createElement("img", { hidden: !isPauseVideo, className: 'clc-pb-video-pause', src: PAUSE_ICON }))))) : (react_1.default.createElement("div", { className: 'video-container', key: rec.video.itemId, onClick: handleClickVideo(), style: {
186
250
  position: 'relative',
187
251
  width: '100%',
188
- height
252
+ height,
253
+ overflow: 'hidden'
189
254
  } },
190
- react_1.default.createElement("video", { id: `pb-video-${index}`, className: 'clc-pb-video', ref: videoRef, poster: sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.placeholder_image, muted: true, controls: false, playsInline: true, preload: 'auto', onPause: onPause, onEnded: handleVideoStart }),
255
+ react_1.default.createElement("video", { id: `pb-video-${index}`, className: 'clc-pb-video', ref: videoRef, crossOrigin: 'anonymous', poster: sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.placeholder_image, muted: true, controls: false, playsInline: true, preload: 'auto', onPause: onPause, onEnded: handleVideoStart }),
191
256
  renderPoster,
192
- react_1.default.createElement("img", { hidden: !isPauseVideo, className: 'clc-pb-video-pause', src: PAUSE_ICON })));
257
+ react_1.default.createElement("img", { hidden: !isPauseVideo, className: 'clc-pb-video-pause', src: PAUSE_ICON })))));
193
258
  };
194
259
  exports.default = (0, react_1.memo)(VideoWidget);
@@ -1,7 +1,12 @@
1
1
  import { CSSProperties, FC } from 'react';
2
2
  import { RecItemType } from './typing';
3
3
  import './index.less';
4
- interface ISxpPageRenderProps {
4
+ export type postConfigType = {
5
+ mode?: '1' | '2';
6
+ offsetTop?: number;
7
+ delay?: number;
8
+ };
9
+ export interface ISxpPageRenderProps {
5
10
  globalConfig?: {
6
11
  isShowLogo?: boolean;
7
12
  logoUrl?: string;
@@ -19,6 +24,8 @@ interface ISxpPageRenderProps {
19
24
  swipeTipIcon?: string;
20
25
  hashTag?: any[];
21
26
  isOpenTextShadow?: boolean;
27
+ videoPost?: postConfigType;
28
+ imgUrlsPost?: postConfigType;
22
29
  };
23
30
  descStyle?: CSSProperties;
24
31
  tipText?: {
@@ -156,10 +156,10 @@ const SxpPageRender = ({ globalConfig, descStyle, containerHeight = window.inner
156
156
  const renderContent = (0, react_1.useCallback)((rec, index) => {
157
157
  var _a, _b, _c, _d;
158
158
  if ((_a = rec.video) === null || _a === void 0 ? void 0 : _a.url) {
159
- return (react_1.default.createElement(VideoWidget_1.default, { rec: rec, index: index, muted: isMuted, data: data, height: height, activeIndex: activeIndex }));
159
+ return (react_1.default.createElement(VideoWidget_1.default, { rec: rec, index: index, muted: isMuted, data: data, height: height, activeIndex: activeIndex, videoPostConfig: globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.videoPost }));
160
160
  }
161
161
  if ((_b = rec.video) === null || _b === void 0 ? void 0 : _b.imgUrls) {
162
- return (react_1.default.createElement(PictureGroup_1.default, { key: rec.video.itemId, imgUrls: rec.video.imgUrls, width: containerWidth, height: height, rec: rec, index: index, onReportViewImageEnd: handleReportViewImageEnd, onViewImageStartEvent: handleViewImageStartEvent }));
162
+ return (react_1.default.createElement(PictureGroup_1.default, { key: rec.video.itemId, imgUrls: rec.video.imgUrls, width: containerWidth, height: height, rec: rec, index: index, onReportViewImageEnd: handleReportViewImageEnd, onViewImageStartEvent: handleViewImageStartEvent, imgUrlsPostConfig: globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.imgUrlsPost }));
163
163
  }
164
164
  if (rec.product && Array.isArray(globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.productPost) && ((_c = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.productPost) === null || _c === void 0 ? void 0 : _c.length) > 0) {
165
165
  return (_d = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.productPost) === null || _d === void 0 ? void 0 : _d.map((value, idx) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pb-sxp-ui",
3
- "version": "1.0.24",
3
+ "version": "1.0.26",
4
4
  "description": "React enterprise-class UI components",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",