@folklore/ads 0.0.3 → 0.0.5
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.
- package/dist/cjs.js +428 -22
- package/dist/es.js +410 -22
- package/package.json +2 -2
package/dist/cjs.js
CHANGED
|
@@ -2,24 +2,99 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var debounce = require('lodash/debounce');
|
|
6
5
|
var PropTypes = require('prop-types');
|
|
6
|
+
var classNames = require('classnames');
|
|
7
7
|
var React = require('react');
|
|
8
|
+
var isArray = require('lodash/isArray');
|
|
9
|
+
var uniqBy = require('lodash/uniqBy');
|
|
10
|
+
var sortBy = require('lodash/sortBy');
|
|
11
|
+
var debounce = require('lodash/debounce');
|
|
8
12
|
var EventEmitter = require('wolfy87-eventemitter');
|
|
9
13
|
var isObject = require('lodash/isObject');
|
|
10
14
|
var createDebug = require('debug');
|
|
11
|
-
var isArray = require('lodash/isArray');
|
|
12
15
|
var jsxRuntime = require('react/jsx-runtime');
|
|
16
|
+
var hooks = require('@folklore/hooks');
|
|
17
|
+
var tracking = require('@folklore/tracking');
|
|
13
18
|
|
|
14
19
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
15
20
|
|
|
16
|
-
var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
|
|
17
21
|
var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
|
|
22
|
+
var classNames__default = /*#__PURE__*/_interopDefaultLegacy(classNames);
|
|
18
23
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
24
|
+
var isArray__default = /*#__PURE__*/_interopDefaultLegacy(isArray);
|
|
25
|
+
var uniqBy__default = /*#__PURE__*/_interopDefaultLegacy(uniqBy);
|
|
26
|
+
var sortBy__default = /*#__PURE__*/_interopDefaultLegacy(sortBy);
|
|
27
|
+
var debounce__default = /*#__PURE__*/_interopDefaultLegacy(debounce);
|
|
19
28
|
var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
|
|
20
29
|
var isObject__default = /*#__PURE__*/_interopDefaultLegacy(isObject);
|
|
21
30
|
var createDebug__default = /*#__PURE__*/_interopDefaultLegacy(createDebug);
|
|
22
|
-
|
|
31
|
+
|
|
32
|
+
const adPath = PropTypes__default["default"].string;
|
|
33
|
+
const adSize = PropTypes__default["default"].oneOfType([PropTypes__default["default"].arrayOf(PropTypes__default["default"].number), PropTypes__default["default"].arrayOf(PropTypes__default["default"].string), PropTypes__default["default"].string, PropTypes__default["default"].arrayOf(PropTypes__default["default"].oneOfType([PropTypes__default["default"].arrayOf(PropTypes__default["default"].number), PropTypes__default["default"].arrayOf(PropTypes__default["default"].string), PropTypes__default["default"].string]))]);
|
|
34
|
+
const adSizeMapping = PropTypes__default["default"].arrayOf(PropTypes__default["default"].arrayOf(PropTypes__default["default"].oneOfType([PropTypes__default["default"].arrayOf(PropTypes__default["default"].number), adSize])));
|
|
35
|
+
const adPosition = PropTypes__default["default"].shape({
|
|
36
|
+
size: adSize,
|
|
37
|
+
sizeMapping: PropTypes__default["default"].objectOf(adSize)
|
|
38
|
+
});
|
|
39
|
+
const adPositions = PropTypes__default["default"].objectOf(adPosition);
|
|
40
|
+
const adViewports = PropTypes__default["default"].objectOf(PropTypes__default["default"].arrayOf(PropTypes__default["default"].number));
|
|
41
|
+
const adTargeting = PropTypes__default["default"].shape({
|
|
42
|
+
domain: PropTypes__default["default"].string
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
var propTypes$3 = /*#__PURE__*/Object.freeze({
|
|
46
|
+
__proto__: null,
|
|
47
|
+
adPath: adPath,
|
|
48
|
+
adSize: adSize,
|
|
49
|
+
adSizeMapping: adSizeMapping,
|
|
50
|
+
adPosition: adPosition,
|
|
51
|
+
adPositions: adPositions,
|
|
52
|
+
adViewports: adViewports,
|
|
53
|
+
adTargeting: adTargeting
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const getAdSizes = sizes => {
|
|
57
|
+
if (isArray__default["default"](sizes)) {
|
|
58
|
+
return uniqBy__default["default"](isArray__default["default"](sizes[0]) || sizes[0] === 'fluid' ? sizes.filter(size => size !== 'fluid').reduce((allSizes, size) => [...allSizes, ...getAdSizes(size)], []) : [sizes].filter(size => size !== 'fluid'), size => size.join('x'));
|
|
59
|
+
}
|
|
60
|
+
return sizes.split('x').map(it => parseInt(it, 10));
|
|
61
|
+
};
|
|
62
|
+
const getMinimumAdSize = sizes => getAdSizes(sizes).reduce((minimumSize, size) => ({
|
|
63
|
+
width: Math.min(minimumSize.width, size[0]),
|
|
64
|
+
height: Math.min(minimumSize.height, size[1])
|
|
65
|
+
}), {
|
|
66
|
+
width: Infinity,
|
|
67
|
+
height: Infinity
|
|
68
|
+
});
|
|
69
|
+
const sizeFitsInViewport = (size, viewport) => size === 'fluid' && viewport[0] > 600 || size !== 'fluid' && (viewport[0] === 0 || size[0] <= viewport[0]) && (viewport[1] === 0 || size[1] <= viewport[1]);
|
|
70
|
+
const getSortedViewports = viewports => sortBy__default["default"](Object.keys(viewports).map(name => ({
|
|
71
|
+
name,
|
|
72
|
+
size: viewports[name]
|
|
73
|
+
})), viewport => viewport.size[0]).reverse();
|
|
74
|
+
const buildSizeMappingFromViewports = (sizeMapping, viewports) => getSortedViewports(viewports).reduce((newSizeMapping, _ref) => {
|
|
75
|
+
let {
|
|
76
|
+
name,
|
|
77
|
+
size: viewPortSize
|
|
78
|
+
} = _ref;
|
|
79
|
+
return typeof sizeMapping[name] !== 'undefined' ? [...newSizeMapping, [viewPortSize, sizeMapping[name]]] : newSizeMapping;
|
|
80
|
+
}, []);
|
|
81
|
+
const buildSizeMappingFromSizes = (sizes, viewports) => getSortedViewports(viewports).map(_ref2 => {
|
|
82
|
+
let {
|
|
83
|
+
name,
|
|
84
|
+
size: viewPortSize
|
|
85
|
+
} = _ref2;
|
|
86
|
+
return [viewPortSize, sizes.filter(size => sizeFitsInViewport(size, name === 'default' ? [300, 300] : viewPortSize))];
|
|
87
|
+
});
|
|
88
|
+
const getSizeMappingFromPosition = (_ref3, viewports) => {
|
|
89
|
+
let {
|
|
90
|
+
size: allSizes = [],
|
|
91
|
+
sizeMapping = null
|
|
92
|
+
} = _ref3;
|
|
93
|
+
if (sizeMapping === true) {
|
|
94
|
+
return buildSizeMappingFromSizes(allSizes, viewports);
|
|
95
|
+
}
|
|
96
|
+
return sizeMapping !== null ? buildSizeMappingFromViewports(sizeMapping, viewports) : null;
|
|
97
|
+
};
|
|
23
98
|
|
|
24
99
|
class AdSlot extends EventEmitter__default["default"] {
|
|
25
100
|
constructor(id, path, size) {
|
|
@@ -189,7 +264,7 @@ class AdSlot extends EventEmitter__default["default"] {
|
|
|
189
264
|
}
|
|
190
265
|
|
|
191
266
|
/* globals refreshDisabledLineItems: [] */
|
|
192
|
-
const debug = createDebug__default["default"]('
|
|
267
|
+
const debug = createDebug__default["default"]('folklore:ads');
|
|
193
268
|
class AdsManager extends EventEmitter__default["default"] {
|
|
194
269
|
static index = 0;
|
|
195
270
|
static createAdId() {
|
|
@@ -545,23 +620,10 @@ const positions = {
|
|
|
545
620
|
}
|
|
546
621
|
};
|
|
547
622
|
|
|
548
|
-
PropTypes__default["default"].string;
|
|
549
|
-
const adSize = PropTypes__default["default"].oneOfType([PropTypes__default["default"].arrayOf(PropTypes__default["default"].number), PropTypes__default["default"].arrayOf(PropTypes__default["default"].string), PropTypes__default["default"].string, PropTypes__default["default"].arrayOf(PropTypes__default["default"].oneOfType([PropTypes__default["default"].arrayOf(PropTypes__default["default"].number), PropTypes__default["default"].arrayOf(PropTypes__default["default"].string), PropTypes__default["default"].string]))]);
|
|
550
|
-
PropTypes__default["default"].arrayOf(PropTypes__default["default"].arrayOf(PropTypes__default["default"].oneOfType([PropTypes__default["default"].arrayOf(PropTypes__default["default"].number), adSize])));
|
|
551
|
-
const adPosition = PropTypes__default["default"].shape({
|
|
552
|
-
size: adSize,
|
|
553
|
-
sizeMapping: PropTypes__default["default"].objectOf(adSize)
|
|
554
|
-
});
|
|
555
|
-
PropTypes__default["default"].objectOf(adPosition);
|
|
556
|
-
const adViewports = PropTypes__default["default"].objectOf(PropTypes__default["default"].arrayOf(PropTypes__default["default"].number));
|
|
557
|
-
PropTypes__default["default"].shape({
|
|
558
|
-
domain: PropTypes__default["default"].string
|
|
559
|
-
});
|
|
560
|
-
|
|
561
623
|
/* eslint-disable react/jsx-props-no-spreading */
|
|
562
624
|
const AdsContext = /*#__PURE__*/React__default["default"].createContext(null);
|
|
563
625
|
const useAdsContext = () => React.useContext(AdsContext);
|
|
564
|
-
const propTypes = {
|
|
626
|
+
const propTypes$2 = {
|
|
565
627
|
children: PropTypes__default["default"].node.isRequired,
|
|
566
628
|
defaultSlotPath: PropTypes__default["default"].string,
|
|
567
629
|
slotsPath: PropTypes__default["default"].objectOf(PropTypes__default["default"].string),
|
|
@@ -572,7 +634,7 @@ const propTypes = {
|
|
|
572
634
|
positions: adViewports,
|
|
573
635
|
viewports: adViewports
|
|
574
636
|
};
|
|
575
|
-
const defaultProps = {
|
|
637
|
+
const defaultProps$2 = {
|
|
576
638
|
defaultSlotPath: null,
|
|
577
639
|
slotsPath: null,
|
|
578
640
|
enableSingleRequest: true,
|
|
@@ -653,10 +715,354 @@ function AdsProvider(_ref) {
|
|
|
653
715
|
children: children
|
|
654
716
|
});
|
|
655
717
|
}
|
|
656
|
-
AdsProvider.propTypes = propTypes;
|
|
657
|
-
AdsProvider.defaultProps = defaultProps;
|
|
718
|
+
AdsProvider.propTypes = propTypes$2;
|
|
719
|
+
AdsProvider.defaultProps = defaultProps$2;
|
|
720
|
+
|
|
721
|
+
const AdsTargetingContext = /*#__PURE__*/React__default["default"].createContext(null);
|
|
722
|
+
const useAdsTargeting = () => React.useContext(AdsTargetingContext);
|
|
723
|
+
const propTypes$1 = {
|
|
724
|
+
children: PropTypes__default["default"].node.isRequired,
|
|
725
|
+
// eslint-disable-next-line react/forbid-prop-types
|
|
726
|
+
targeting: PropTypes__default["default"].object
|
|
727
|
+
};
|
|
728
|
+
const defaultProps$1 = {
|
|
729
|
+
targeting: {
|
|
730
|
+
domain: typeof window !== 'undefined' ? `${window.location.protocol}//${window.location.host}` : null
|
|
731
|
+
}
|
|
732
|
+
};
|
|
733
|
+
function AdsTargetingProvider(_ref) {
|
|
734
|
+
let {
|
|
735
|
+
children,
|
|
736
|
+
targeting
|
|
737
|
+
} = _ref;
|
|
738
|
+
return /*#__PURE__*/jsxRuntime.jsx(AdsTargetingContext.Provider, {
|
|
739
|
+
value: targeting,
|
|
740
|
+
children: children
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
AdsTargetingProvider.propTypes = propTypes$1;
|
|
744
|
+
AdsTargetingProvider.defaultProps = defaultProps$1;
|
|
745
|
+
|
|
746
|
+
function useTrackAd() {
|
|
747
|
+
const tracking$1 = tracking.useTracking() || null;
|
|
748
|
+
const trackEvent = React.useCallback((action, slot, renderEvent) => {
|
|
749
|
+
if (tracking$1 !== null && typeof tracking$1.trackAd !== 'undefined') {
|
|
750
|
+
tracking$1.trackAd(action, slot, renderEvent);
|
|
751
|
+
}
|
|
752
|
+
}, [tracking$1]);
|
|
753
|
+
return trackEvent;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
function useAd(path, size) {
|
|
757
|
+
let {
|
|
758
|
+
sizeMapping = null,
|
|
759
|
+
targeting = null,
|
|
760
|
+
categoryExclusions = null,
|
|
761
|
+
refreshInterval = null,
|
|
762
|
+
alwaysRender = false,
|
|
763
|
+
onRender = null,
|
|
764
|
+
disabled = false,
|
|
765
|
+
trackEvents = true,
|
|
766
|
+
rootMargin = '300px'
|
|
767
|
+
} = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
768
|
+
const {
|
|
769
|
+
ads: adsManager,
|
|
770
|
+
ready: adsReady
|
|
771
|
+
} = useAdsContext();
|
|
772
|
+
const trackAd = useTrackAd();
|
|
773
|
+
const track = React.useCallback(function () {
|
|
774
|
+
if (trackEvents) {
|
|
775
|
+
trackAd(...arguments);
|
|
776
|
+
}
|
|
777
|
+
}, [trackEvents, trackAd]);
|
|
778
|
+
|
|
779
|
+
// Check for visibility
|
|
780
|
+
const {
|
|
781
|
+
ref: refObserver,
|
|
782
|
+
entry: {
|
|
783
|
+
isIntersecting
|
|
784
|
+
}
|
|
785
|
+
} = hooks.useIntersectionObserver({
|
|
786
|
+
rootMargin,
|
|
787
|
+
disabled
|
|
788
|
+
});
|
|
789
|
+
|
|
790
|
+
// Window blur
|
|
791
|
+
const [windowActive, setWindowActive] = React.useState(true); // eslint-disable-line
|
|
792
|
+
const onWindowBlur = React.useCallback(() => setWindowActive(false), [setWindowActive]);
|
|
793
|
+
const onWindowFocus = React.useCallback(() => setWindowActive(true), [setWindowActive]);
|
|
794
|
+
hooks.useWindowEvent('blur', onWindowBlur);
|
|
795
|
+
hooks.useWindowEvent('focus', onWindowFocus);
|
|
796
|
+
const isVisible = isIntersecting; /* && windowActive */
|
|
797
|
+
|
|
798
|
+
// Current render event
|
|
799
|
+
const [renderEvent, setRenderEvent] = React.useState(null);
|
|
800
|
+
|
|
801
|
+
// Create slot
|
|
802
|
+
const currentSlot = React.useRef(null);
|
|
803
|
+
const slot = React.useMemo(() => {
|
|
804
|
+
if (currentSlot.current !== null) {
|
|
805
|
+
adsManager.destroySlot(currentSlot.current);
|
|
806
|
+
currentSlot.current = null;
|
|
807
|
+
}
|
|
808
|
+
currentSlot.current = path !== null && !disabled ? adsManager.createSlot(path, size, {
|
|
809
|
+
visible: isVisible,
|
|
810
|
+
sizeMapping,
|
|
811
|
+
targeting,
|
|
812
|
+
categoryExclusions
|
|
813
|
+
}) : null;
|
|
814
|
+
// if (currentSlot.current !== null && adsReady) {
|
|
815
|
+
// adsManager.defineSlot(currentSlot.current);
|
|
816
|
+
// }
|
|
817
|
+
return currentSlot.current;
|
|
818
|
+
}, [adsManager, path, disabled, size, sizeMapping, targeting, alwaysRender, categoryExclusions]);
|
|
819
|
+
|
|
820
|
+
// Set visibility
|
|
821
|
+
React.useEffect(() => {
|
|
822
|
+
if (slot !== null) {
|
|
823
|
+
slot.setVisible(isVisible);
|
|
824
|
+
}
|
|
825
|
+
}, [slot, isVisible]);
|
|
826
|
+
|
|
827
|
+
// Render ad when visible
|
|
828
|
+
React.useEffect(() => {
|
|
829
|
+
const slotReady = slot !== null && !slot.isDefined();
|
|
830
|
+
if (adsReady && slotReady && (alwaysRender || isVisible)) {
|
|
831
|
+
adsManager.defineSlot(slot);
|
|
832
|
+
adsManager.displaySlot(slot);
|
|
833
|
+
track('Init', slot);
|
|
834
|
+
}
|
|
835
|
+
}, [adsManager, adsReady, slot, alwaysRender, isIntersecting, track]);
|
|
836
|
+
|
|
837
|
+
// Refresh ads slot
|
|
838
|
+
React.useEffect(() => {
|
|
839
|
+
let interval = null;
|
|
840
|
+
const slotReady = slot !== null && slot.isDefined();
|
|
841
|
+
if (adsReady && slotReady && isVisible && refreshInterval !== null) {
|
|
842
|
+
interval = setInterval(() => {
|
|
843
|
+
adsManager.refreshSlot(slot);
|
|
844
|
+
track('Refresh', slot);
|
|
845
|
+
}, refreshInterval);
|
|
846
|
+
}
|
|
847
|
+
return () => {
|
|
848
|
+
if (interval !== null) {
|
|
849
|
+
clearInterval(interval);
|
|
850
|
+
}
|
|
851
|
+
};
|
|
852
|
+
}, [adsManager, adsReady, slot, isVisible, refreshInterval, track]);
|
|
853
|
+
|
|
854
|
+
// Listen to render event
|
|
855
|
+
React.useEffect(() => {
|
|
856
|
+
if (slot === null) {
|
|
857
|
+
return () => {};
|
|
858
|
+
}
|
|
859
|
+
const onSlotRender = event => {
|
|
860
|
+
setRenderEvent(event);
|
|
861
|
+
if (onRender !== null) {
|
|
862
|
+
onRender(event);
|
|
863
|
+
}
|
|
864
|
+
const {
|
|
865
|
+
isEmpty = true
|
|
866
|
+
} = event || {};
|
|
867
|
+
if (isEmpty) {
|
|
868
|
+
track('Empty', slot);
|
|
869
|
+
} else {
|
|
870
|
+
track('Render', slot, event);
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
slot.on('render', onSlotRender);
|
|
874
|
+
return () => slot.off('render', onSlotRender);
|
|
875
|
+
}, [slot, disabled, setRenderEvent, onRender, track]);
|
|
876
|
+
|
|
877
|
+
// Destroy slot
|
|
878
|
+
React.useEffect(() => () => {
|
|
879
|
+
if (slot !== null) {
|
|
880
|
+
currentSlot.current = null;
|
|
881
|
+
adsManager.destroySlot(slot);
|
|
882
|
+
}
|
|
883
|
+
}, []);
|
|
884
|
+
return {
|
|
885
|
+
refObserver,
|
|
886
|
+
disabled: adsManager.isDisabled(),
|
|
887
|
+
id: slot !== null ? slot.getElementId() : null,
|
|
888
|
+
isRendered: slot !== null && slot.isRendered(),
|
|
889
|
+
isEmpty: slot !== null ? slot.isEmpty() : true,
|
|
890
|
+
isVisible: slot !== null ? slot.isVisible() : true,
|
|
891
|
+
width: null,
|
|
892
|
+
height: null,
|
|
893
|
+
renderEvent,
|
|
894
|
+
...(slot !== null ? slot.getRenderedSize() : null)
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
const propTypes = {
|
|
899
|
+
position: PropTypes__default["default"].string.isRequired,
|
|
900
|
+
slot: PropTypes__default["default"].string,
|
|
901
|
+
path: adPath,
|
|
902
|
+
size: adSize,
|
|
903
|
+
sizeMapping: adSizeMapping,
|
|
904
|
+
targeting: adTargeting,
|
|
905
|
+
refreshInterval: PropTypes__default["default"].number,
|
|
906
|
+
alwaysRender: PropTypes__default["default"].bool,
|
|
907
|
+
disabled: PropTypes__default["default"].bool,
|
|
908
|
+
className: PropTypes__default["default"].string,
|
|
909
|
+
emptyClassName: PropTypes__default["default"].string,
|
|
910
|
+
adClassName: PropTypes__default["default"].string,
|
|
911
|
+
onRender: PropTypes__default["default"].func
|
|
912
|
+
};
|
|
913
|
+
const defaultProps = {
|
|
914
|
+
path: null,
|
|
915
|
+
slot: 'default',
|
|
916
|
+
size: null,
|
|
917
|
+
sizeMapping: null,
|
|
918
|
+
targeting: null,
|
|
919
|
+
refreshInterval: null,
|
|
920
|
+
alwaysRender: true,
|
|
921
|
+
disabled: false,
|
|
922
|
+
className: null,
|
|
923
|
+
emptyClassName: null,
|
|
924
|
+
adClassName: null,
|
|
925
|
+
onRender: null
|
|
926
|
+
};
|
|
927
|
+
function Ad(_ref) {
|
|
928
|
+
let {
|
|
929
|
+
position: positionName,
|
|
930
|
+
slot: slotName,
|
|
931
|
+
path,
|
|
932
|
+
size,
|
|
933
|
+
sizeMapping,
|
|
934
|
+
targeting,
|
|
935
|
+
refreshInterval,
|
|
936
|
+
alwaysRender,
|
|
937
|
+
disabled,
|
|
938
|
+
className,
|
|
939
|
+
emptyClassName,
|
|
940
|
+
adClassName,
|
|
941
|
+
onRender
|
|
942
|
+
} = _ref;
|
|
943
|
+
const {
|
|
944
|
+
viewports,
|
|
945
|
+
positions,
|
|
946
|
+
slotsPath
|
|
947
|
+
} = useAdsContext();
|
|
948
|
+
const position = positionName !== null ? positions[positionName] || null : null;
|
|
949
|
+
const finalPath = path || (slotName !== null ? slotsPath[slotName] : null) || (positionName !== null ? slotsPath[positionName] : null);
|
|
950
|
+
const finalSize = size !== null ? size : position.size;
|
|
951
|
+
|
|
952
|
+
// Targeting
|
|
953
|
+
const contextTargeting = useAdsTargeting();
|
|
954
|
+
const finalSizeMapping = React.useMemo(() => sizeMapping !== null ? sizeMapping : getSizeMappingFromPosition(position, viewports), [sizeMapping, position, viewports]);
|
|
955
|
+
const allTargeting = React.useMemo(() => contextTargeting !== null || targeting !== null || positionName !== null ? {
|
|
956
|
+
position: positionName,
|
|
957
|
+
...contextTargeting,
|
|
958
|
+
...targeting
|
|
959
|
+
} : null, [contextTargeting, targeting, positionName]);
|
|
960
|
+
const finalAdTargeting = React.useMemo(() => {
|
|
961
|
+
const {
|
|
962
|
+
refreshAds = null,
|
|
963
|
+
...otherProps
|
|
964
|
+
} = allTargeting || {};
|
|
965
|
+
return {
|
|
966
|
+
refreshInterval: refreshAds !== null && refreshAds === 'inactive' ? null : refreshInterval,
|
|
967
|
+
targeting: otherProps || {}
|
|
968
|
+
};
|
|
969
|
+
}, [allTargeting, refreshInterval]);
|
|
970
|
+
|
|
971
|
+
// Create ad
|
|
972
|
+
const {
|
|
973
|
+
disabled: adsDisabled,
|
|
974
|
+
id,
|
|
975
|
+
width,
|
|
976
|
+
height,
|
|
977
|
+
isEmpty,
|
|
978
|
+
isRendered,
|
|
979
|
+
refObserver
|
|
980
|
+
} = useAd(finalPath, finalSize, {
|
|
981
|
+
sizeMapping: finalSizeMapping,
|
|
982
|
+
targeting: finalAdTargeting.targeting,
|
|
983
|
+
refreshInterval: finalAdTargeting.refreshInterval,
|
|
984
|
+
alwaysRender,
|
|
985
|
+
onRender,
|
|
986
|
+
disabled
|
|
987
|
+
});
|
|
988
|
+
|
|
989
|
+
// Get size
|
|
990
|
+
const lastRenderedSize = React.useRef(null);
|
|
991
|
+
const wasDisabled = React.useRef(disabled);
|
|
992
|
+
const waitingNextRender = React.useMemo(() => {
|
|
993
|
+
if (disabled) {
|
|
994
|
+
wasDisabled.current = true;
|
|
995
|
+
} else if (!disabled && isRendered) {
|
|
996
|
+
wasDisabled.current = false;
|
|
997
|
+
}
|
|
998
|
+
return wasDisabled.current && !isRendered;
|
|
999
|
+
}, [isRendered]);
|
|
1000
|
+
const sizeStyle = React.useMemo(() => {
|
|
1001
|
+
if (disabled || waitingNextRender) {
|
|
1002
|
+
return lastRenderedSize.current;
|
|
1003
|
+
}
|
|
1004
|
+
const {
|
|
1005
|
+
width: minimumWidth,
|
|
1006
|
+
height: minimumHeight
|
|
1007
|
+
} = getMinimumAdSize(finalSizeMapping !== null ? finalSizeMapping.reduce((allSizes, sizeMap) => [...allSizes, sizeMap[1]], [finalSize]) : finalSize);
|
|
1008
|
+
if (isRendered) {
|
|
1009
|
+
lastRenderedSize.current = !isEmpty ? {
|
|
1010
|
+
width,
|
|
1011
|
+
height
|
|
1012
|
+
} : null;
|
|
1013
|
+
}
|
|
1014
|
+
return {
|
|
1015
|
+
width: isRendered ? width : minimumWidth,
|
|
1016
|
+
height: isRendered ? height : minimumHeight
|
|
1017
|
+
};
|
|
1018
|
+
}, [id, disabled, finalSize, finalSizeMapping, width, height, isRendered, isEmpty]);
|
|
1019
|
+
const keepSize = (disabled || waitingNextRender) && lastRenderedSize.current !== null;
|
|
1020
|
+
if (id === null && !keepSize) {
|
|
1021
|
+
return null;
|
|
1022
|
+
}
|
|
1023
|
+
return /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
1024
|
+
id: id !== null ? `${id}-container` : null,
|
|
1025
|
+
className: classNames__default["default"]([className, {
|
|
1026
|
+
[emptyClassName]: emptyClassName !== null && isEmpty && !keepSize
|
|
1027
|
+
}]),
|
|
1028
|
+
ref: refObserver,
|
|
1029
|
+
style: isEmpty && !keepSize ? {
|
|
1030
|
+
height: 0,
|
|
1031
|
+
paddingBottom: 0,
|
|
1032
|
+
overflow: 'hidden',
|
|
1033
|
+
opacity: 0
|
|
1034
|
+
} : null,
|
|
1035
|
+
children: /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
1036
|
+
className: adClassName,
|
|
1037
|
+
style: {
|
|
1038
|
+
...sizeStyle,
|
|
1039
|
+
margin: 'auto'
|
|
1040
|
+
},
|
|
1041
|
+
children: /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
1042
|
+
id: id
|
|
1043
|
+
})
|
|
1044
|
+
})
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
Ad.propTypes = propTypes;
|
|
1048
|
+
Ad.defaultProps = defaultProps;
|
|
658
1049
|
|
|
1050
|
+
exports.Ad = Ad;
|
|
659
1051
|
exports.AdSlot = AdSlot;
|
|
660
1052
|
exports.AdsManager = AdsManager;
|
|
661
1053
|
exports.AdsProvider = AdsProvider;
|
|
1054
|
+
exports.AdsTargetingProvider = AdsTargetingProvider;
|
|
1055
|
+
exports.PropTypes = propTypes$3;
|
|
1056
|
+
exports.buildSizeMappingFromSizes = buildSizeMappingFromSizes;
|
|
1057
|
+
exports.buildSizeMappingFromViewports = buildSizeMappingFromViewports;
|
|
1058
|
+
exports.getAdSizes = getAdSizes;
|
|
1059
|
+
exports.getMinimumAdSize = getMinimumAdSize;
|
|
1060
|
+
exports.getSizeMappingFromPosition = getSizeMappingFromPosition;
|
|
1061
|
+
exports.getSortedViewports = getSortedViewports;
|
|
1062
|
+
exports.positions = positions;
|
|
1063
|
+
exports.sizeFitsInViewport = sizeFitsInViewport;
|
|
1064
|
+
exports.useAd = useAd;
|
|
662
1065
|
exports.useAdsContext = useAdsContext;
|
|
1066
|
+
exports.useAdsTargeting = useAdsTargeting;
|
|
1067
|
+
exports.useAdsTracking = useTrackAd;
|
|
1068
|
+
exports.viewports = viewports;
|
package/dist/es.js
CHANGED
|
@@ -1,11 +1,83 @@
|
|
|
1
|
-
import debounce from 'lodash/debounce';
|
|
2
1
|
import PropTypes from 'prop-types';
|
|
3
|
-
import
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import React, { useContext, useState, useRef, useMemo, useEffect, useCallback } from 'react';
|
|
4
|
+
import isArray from 'lodash/isArray';
|
|
5
|
+
import uniqBy from 'lodash/uniqBy';
|
|
6
|
+
import sortBy from 'lodash/sortBy';
|
|
7
|
+
import debounce from 'lodash/debounce';
|
|
4
8
|
import EventEmitter from 'wolfy87-eventemitter';
|
|
5
9
|
import isObject from 'lodash/isObject';
|
|
6
10
|
import createDebug from 'debug';
|
|
7
|
-
import isArray from 'lodash/isArray';
|
|
8
11
|
import { jsx } from 'react/jsx-runtime';
|
|
12
|
+
import { useIntersectionObserver, useWindowEvent } from '@folklore/hooks';
|
|
13
|
+
import { useTracking } from '@folklore/tracking';
|
|
14
|
+
|
|
15
|
+
const adPath = PropTypes.string;
|
|
16
|
+
const adSize = PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.arrayOf(PropTypes.string), PropTypes.string, PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.arrayOf(PropTypes.string), PropTypes.string]))]);
|
|
17
|
+
const adSizeMapping = PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), adSize])));
|
|
18
|
+
const adPosition = PropTypes.shape({
|
|
19
|
+
size: adSize,
|
|
20
|
+
sizeMapping: PropTypes.objectOf(adSize)
|
|
21
|
+
});
|
|
22
|
+
const adPositions = PropTypes.objectOf(adPosition);
|
|
23
|
+
const adViewports = PropTypes.objectOf(PropTypes.arrayOf(PropTypes.number));
|
|
24
|
+
const adTargeting = PropTypes.shape({
|
|
25
|
+
domain: PropTypes.string
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
var propTypes$3 = /*#__PURE__*/Object.freeze({
|
|
29
|
+
__proto__: null,
|
|
30
|
+
adPath: adPath,
|
|
31
|
+
adSize: adSize,
|
|
32
|
+
adSizeMapping: adSizeMapping,
|
|
33
|
+
adPosition: adPosition,
|
|
34
|
+
adPositions: adPositions,
|
|
35
|
+
adViewports: adViewports,
|
|
36
|
+
adTargeting: adTargeting
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const getAdSizes = sizes => {
|
|
40
|
+
if (isArray(sizes)) {
|
|
41
|
+
return uniqBy(isArray(sizes[0]) || sizes[0] === 'fluid' ? sizes.filter(size => size !== 'fluid').reduce((allSizes, size) => [...allSizes, ...getAdSizes(size)], []) : [sizes].filter(size => size !== 'fluid'), size => size.join('x'));
|
|
42
|
+
}
|
|
43
|
+
return sizes.split('x').map(it => parseInt(it, 10));
|
|
44
|
+
};
|
|
45
|
+
const getMinimumAdSize = sizes => getAdSizes(sizes).reduce((minimumSize, size) => ({
|
|
46
|
+
width: Math.min(minimumSize.width, size[0]),
|
|
47
|
+
height: Math.min(minimumSize.height, size[1])
|
|
48
|
+
}), {
|
|
49
|
+
width: Infinity,
|
|
50
|
+
height: Infinity
|
|
51
|
+
});
|
|
52
|
+
const sizeFitsInViewport = (size, viewport) => size === 'fluid' && viewport[0] > 600 || size !== 'fluid' && (viewport[0] === 0 || size[0] <= viewport[0]) && (viewport[1] === 0 || size[1] <= viewport[1]);
|
|
53
|
+
const getSortedViewports = viewports => sortBy(Object.keys(viewports).map(name => ({
|
|
54
|
+
name,
|
|
55
|
+
size: viewports[name]
|
|
56
|
+
})), viewport => viewport.size[0]).reverse();
|
|
57
|
+
const buildSizeMappingFromViewports = (sizeMapping, viewports) => getSortedViewports(viewports).reduce((newSizeMapping, _ref) => {
|
|
58
|
+
let {
|
|
59
|
+
name,
|
|
60
|
+
size: viewPortSize
|
|
61
|
+
} = _ref;
|
|
62
|
+
return typeof sizeMapping[name] !== 'undefined' ? [...newSizeMapping, [viewPortSize, sizeMapping[name]]] : newSizeMapping;
|
|
63
|
+
}, []);
|
|
64
|
+
const buildSizeMappingFromSizes = (sizes, viewports) => getSortedViewports(viewports).map(_ref2 => {
|
|
65
|
+
let {
|
|
66
|
+
name,
|
|
67
|
+
size: viewPortSize
|
|
68
|
+
} = _ref2;
|
|
69
|
+
return [viewPortSize, sizes.filter(size => sizeFitsInViewport(size, name === 'default' ? [300, 300] : viewPortSize))];
|
|
70
|
+
});
|
|
71
|
+
const getSizeMappingFromPosition = (_ref3, viewports) => {
|
|
72
|
+
let {
|
|
73
|
+
size: allSizes = [],
|
|
74
|
+
sizeMapping = null
|
|
75
|
+
} = _ref3;
|
|
76
|
+
if (sizeMapping === true) {
|
|
77
|
+
return buildSizeMappingFromSizes(allSizes, viewports);
|
|
78
|
+
}
|
|
79
|
+
return sizeMapping !== null ? buildSizeMappingFromViewports(sizeMapping, viewports) : null;
|
|
80
|
+
};
|
|
9
81
|
|
|
10
82
|
class AdSlot extends EventEmitter {
|
|
11
83
|
constructor(id, path, size) {
|
|
@@ -175,7 +247,7 @@ class AdSlot extends EventEmitter {
|
|
|
175
247
|
}
|
|
176
248
|
|
|
177
249
|
/* globals refreshDisabledLineItems: [] */
|
|
178
|
-
const debug = createDebug('
|
|
250
|
+
const debug = createDebug('folklore:ads');
|
|
179
251
|
class AdsManager extends EventEmitter {
|
|
180
252
|
static index = 0;
|
|
181
253
|
static createAdId() {
|
|
@@ -531,23 +603,10 @@ const positions = {
|
|
|
531
603
|
}
|
|
532
604
|
};
|
|
533
605
|
|
|
534
|
-
PropTypes.string;
|
|
535
|
-
const adSize = PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.arrayOf(PropTypes.string), PropTypes.string, PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.arrayOf(PropTypes.string), PropTypes.string]))]);
|
|
536
|
-
PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), adSize])));
|
|
537
|
-
const adPosition = PropTypes.shape({
|
|
538
|
-
size: adSize,
|
|
539
|
-
sizeMapping: PropTypes.objectOf(adSize)
|
|
540
|
-
});
|
|
541
|
-
PropTypes.objectOf(adPosition);
|
|
542
|
-
const adViewports = PropTypes.objectOf(PropTypes.arrayOf(PropTypes.number));
|
|
543
|
-
PropTypes.shape({
|
|
544
|
-
domain: PropTypes.string
|
|
545
|
-
});
|
|
546
|
-
|
|
547
606
|
/* eslint-disable react/jsx-props-no-spreading */
|
|
548
607
|
const AdsContext = /*#__PURE__*/React.createContext(null);
|
|
549
608
|
const useAdsContext = () => useContext(AdsContext);
|
|
550
|
-
const propTypes = {
|
|
609
|
+
const propTypes$2 = {
|
|
551
610
|
children: PropTypes.node.isRequired,
|
|
552
611
|
defaultSlotPath: PropTypes.string,
|
|
553
612
|
slotsPath: PropTypes.objectOf(PropTypes.string),
|
|
@@ -558,7 +617,7 @@ const propTypes = {
|
|
|
558
617
|
positions: adViewports,
|
|
559
618
|
viewports: adViewports
|
|
560
619
|
};
|
|
561
|
-
const defaultProps = {
|
|
620
|
+
const defaultProps$2 = {
|
|
562
621
|
defaultSlotPath: null,
|
|
563
622
|
slotsPath: null,
|
|
564
623
|
enableSingleRequest: true,
|
|
@@ -639,7 +698,336 @@ function AdsProvider(_ref) {
|
|
|
639
698
|
children: children
|
|
640
699
|
});
|
|
641
700
|
}
|
|
642
|
-
AdsProvider.propTypes = propTypes;
|
|
643
|
-
AdsProvider.defaultProps = defaultProps;
|
|
701
|
+
AdsProvider.propTypes = propTypes$2;
|
|
702
|
+
AdsProvider.defaultProps = defaultProps$2;
|
|
703
|
+
|
|
704
|
+
const AdsTargetingContext = /*#__PURE__*/React.createContext(null);
|
|
705
|
+
const useAdsTargeting = () => useContext(AdsTargetingContext);
|
|
706
|
+
const propTypes$1 = {
|
|
707
|
+
children: PropTypes.node.isRequired,
|
|
708
|
+
// eslint-disable-next-line react/forbid-prop-types
|
|
709
|
+
targeting: PropTypes.object
|
|
710
|
+
};
|
|
711
|
+
const defaultProps$1 = {
|
|
712
|
+
targeting: {
|
|
713
|
+
domain: typeof window !== 'undefined' ? `${window.location.protocol}//${window.location.host}` : null
|
|
714
|
+
}
|
|
715
|
+
};
|
|
716
|
+
function AdsTargetingProvider(_ref) {
|
|
717
|
+
let {
|
|
718
|
+
children,
|
|
719
|
+
targeting
|
|
720
|
+
} = _ref;
|
|
721
|
+
return /*#__PURE__*/jsx(AdsTargetingContext.Provider, {
|
|
722
|
+
value: targeting,
|
|
723
|
+
children: children
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
AdsTargetingProvider.propTypes = propTypes$1;
|
|
727
|
+
AdsTargetingProvider.defaultProps = defaultProps$1;
|
|
728
|
+
|
|
729
|
+
function useTrackAd() {
|
|
730
|
+
const tracking = useTracking() || null;
|
|
731
|
+
const trackEvent = useCallback((action, slot, renderEvent) => {
|
|
732
|
+
if (tracking !== null && typeof tracking.trackAd !== 'undefined') {
|
|
733
|
+
tracking.trackAd(action, slot, renderEvent);
|
|
734
|
+
}
|
|
735
|
+
}, [tracking]);
|
|
736
|
+
return trackEvent;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
function useAd(path, size) {
|
|
740
|
+
let {
|
|
741
|
+
sizeMapping = null,
|
|
742
|
+
targeting = null,
|
|
743
|
+
categoryExclusions = null,
|
|
744
|
+
refreshInterval = null,
|
|
745
|
+
alwaysRender = false,
|
|
746
|
+
onRender = null,
|
|
747
|
+
disabled = false,
|
|
748
|
+
trackEvents = true,
|
|
749
|
+
rootMargin = '300px'
|
|
750
|
+
} = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
751
|
+
const {
|
|
752
|
+
ads: adsManager,
|
|
753
|
+
ready: adsReady
|
|
754
|
+
} = useAdsContext();
|
|
755
|
+
const trackAd = useTrackAd();
|
|
756
|
+
const track = useCallback(function () {
|
|
757
|
+
if (trackEvents) {
|
|
758
|
+
trackAd(...arguments);
|
|
759
|
+
}
|
|
760
|
+
}, [trackEvents, trackAd]);
|
|
761
|
+
|
|
762
|
+
// Check for visibility
|
|
763
|
+
const {
|
|
764
|
+
ref: refObserver,
|
|
765
|
+
entry: {
|
|
766
|
+
isIntersecting
|
|
767
|
+
}
|
|
768
|
+
} = useIntersectionObserver({
|
|
769
|
+
rootMargin,
|
|
770
|
+
disabled
|
|
771
|
+
});
|
|
772
|
+
|
|
773
|
+
// Window blur
|
|
774
|
+
const [windowActive, setWindowActive] = useState(true); // eslint-disable-line
|
|
775
|
+
const onWindowBlur = useCallback(() => setWindowActive(false), [setWindowActive]);
|
|
776
|
+
const onWindowFocus = useCallback(() => setWindowActive(true), [setWindowActive]);
|
|
777
|
+
useWindowEvent('blur', onWindowBlur);
|
|
778
|
+
useWindowEvent('focus', onWindowFocus);
|
|
779
|
+
const isVisible = isIntersecting; /* && windowActive */
|
|
780
|
+
|
|
781
|
+
// Current render event
|
|
782
|
+
const [renderEvent, setRenderEvent] = useState(null);
|
|
783
|
+
|
|
784
|
+
// Create slot
|
|
785
|
+
const currentSlot = useRef(null);
|
|
786
|
+
const slot = useMemo(() => {
|
|
787
|
+
if (currentSlot.current !== null) {
|
|
788
|
+
adsManager.destroySlot(currentSlot.current);
|
|
789
|
+
currentSlot.current = null;
|
|
790
|
+
}
|
|
791
|
+
currentSlot.current = path !== null && !disabled ? adsManager.createSlot(path, size, {
|
|
792
|
+
visible: isVisible,
|
|
793
|
+
sizeMapping,
|
|
794
|
+
targeting,
|
|
795
|
+
categoryExclusions
|
|
796
|
+
}) : null;
|
|
797
|
+
// if (currentSlot.current !== null && adsReady) {
|
|
798
|
+
// adsManager.defineSlot(currentSlot.current);
|
|
799
|
+
// }
|
|
800
|
+
return currentSlot.current;
|
|
801
|
+
}, [adsManager, path, disabled, size, sizeMapping, targeting, alwaysRender, categoryExclusions]);
|
|
802
|
+
|
|
803
|
+
// Set visibility
|
|
804
|
+
useEffect(() => {
|
|
805
|
+
if (slot !== null) {
|
|
806
|
+
slot.setVisible(isVisible);
|
|
807
|
+
}
|
|
808
|
+
}, [slot, isVisible]);
|
|
809
|
+
|
|
810
|
+
// Render ad when visible
|
|
811
|
+
useEffect(() => {
|
|
812
|
+
const slotReady = slot !== null && !slot.isDefined();
|
|
813
|
+
if (adsReady && slotReady && (alwaysRender || isVisible)) {
|
|
814
|
+
adsManager.defineSlot(slot);
|
|
815
|
+
adsManager.displaySlot(slot);
|
|
816
|
+
track('Init', slot);
|
|
817
|
+
}
|
|
818
|
+
}, [adsManager, adsReady, slot, alwaysRender, isIntersecting, track]);
|
|
819
|
+
|
|
820
|
+
// Refresh ads slot
|
|
821
|
+
useEffect(() => {
|
|
822
|
+
let interval = null;
|
|
823
|
+
const slotReady = slot !== null && slot.isDefined();
|
|
824
|
+
if (adsReady && slotReady && isVisible && refreshInterval !== null) {
|
|
825
|
+
interval = setInterval(() => {
|
|
826
|
+
adsManager.refreshSlot(slot);
|
|
827
|
+
track('Refresh', slot);
|
|
828
|
+
}, refreshInterval);
|
|
829
|
+
}
|
|
830
|
+
return () => {
|
|
831
|
+
if (interval !== null) {
|
|
832
|
+
clearInterval(interval);
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
}, [adsManager, adsReady, slot, isVisible, refreshInterval, track]);
|
|
836
|
+
|
|
837
|
+
// Listen to render event
|
|
838
|
+
useEffect(() => {
|
|
839
|
+
if (slot === null) {
|
|
840
|
+
return () => {};
|
|
841
|
+
}
|
|
842
|
+
const onSlotRender = event => {
|
|
843
|
+
setRenderEvent(event);
|
|
844
|
+
if (onRender !== null) {
|
|
845
|
+
onRender(event);
|
|
846
|
+
}
|
|
847
|
+
const {
|
|
848
|
+
isEmpty = true
|
|
849
|
+
} = event || {};
|
|
850
|
+
if (isEmpty) {
|
|
851
|
+
track('Empty', slot);
|
|
852
|
+
} else {
|
|
853
|
+
track('Render', slot, event);
|
|
854
|
+
}
|
|
855
|
+
};
|
|
856
|
+
slot.on('render', onSlotRender);
|
|
857
|
+
return () => slot.off('render', onSlotRender);
|
|
858
|
+
}, [slot, disabled, setRenderEvent, onRender, track]);
|
|
859
|
+
|
|
860
|
+
// Destroy slot
|
|
861
|
+
useEffect(() => () => {
|
|
862
|
+
if (slot !== null) {
|
|
863
|
+
currentSlot.current = null;
|
|
864
|
+
adsManager.destroySlot(slot);
|
|
865
|
+
}
|
|
866
|
+
}, []);
|
|
867
|
+
return {
|
|
868
|
+
refObserver,
|
|
869
|
+
disabled: adsManager.isDisabled(),
|
|
870
|
+
id: slot !== null ? slot.getElementId() : null,
|
|
871
|
+
isRendered: slot !== null && slot.isRendered(),
|
|
872
|
+
isEmpty: slot !== null ? slot.isEmpty() : true,
|
|
873
|
+
isVisible: slot !== null ? slot.isVisible() : true,
|
|
874
|
+
width: null,
|
|
875
|
+
height: null,
|
|
876
|
+
renderEvent,
|
|
877
|
+
...(slot !== null ? slot.getRenderedSize() : null)
|
|
878
|
+
};
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
const propTypes = {
|
|
882
|
+
position: PropTypes.string.isRequired,
|
|
883
|
+
slot: PropTypes.string,
|
|
884
|
+
path: adPath,
|
|
885
|
+
size: adSize,
|
|
886
|
+
sizeMapping: adSizeMapping,
|
|
887
|
+
targeting: adTargeting,
|
|
888
|
+
refreshInterval: PropTypes.number,
|
|
889
|
+
alwaysRender: PropTypes.bool,
|
|
890
|
+
disabled: PropTypes.bool,
|
|
891
|
+
className: PropTypes.string,
|
|
892
|
+
emptyClassName: PropTypes.string,
|
|
893
|
+
adClassName: PropTypes.string,
|
|
894
|
+
onRender: PropTypes.func
|
|
895
|
+
};
|
|
896
|
+
const defaultProps = {
|
|
897
|
+
path: null,
|
|
898
|
+
slot: 'default',
|
|
899
|
+
size: null,
|
|
900
|
+
sizeMapping: null,
|
|
901
|
+
targeting: null,
|
|
902
|
+
refreshInterval: null,
|
|
903
|
+
alwaysRender: true,
|
|
904
|
+
disabled: false,
|
|
905
|
+
className: null,
|
|
906
|
+
emptyClassName: null,
|
|
907
|
+
adClassName: null,
|
|
908
|
+
onRender: null
|
|
909
|
+
};
|
|
910
|
+
function Ad(_ref) {
|
|
911
|
+
let {
|
|
912
|
+
position: positionName,
|
|
913
|
+
slot: slotName,
|
|
914
|
+
path,
|
|
915
|
+
size,
|
|
916
|
+
sizeMapping,
|
|
917
|
+
targeting,
|
|
918
|
+
refreshInterval,
|
|
919
|
+
alwaysRender,
|
|
920
|
+
disabled,
|
|
921
|
+
className,
|
|
922
|
+
emptyClassName,
|
|
923
|
+
adClassName,
|
|
924
|
+
onRender
|
|
925
|
+
} = _ref;
|
|
926
|
+
const {
|
|
927
|
+
viewports,
|
|
928
|
+
positions,
|
|
929
|
+
slotsPath
|
|
930
|
+
} = useAdsContext();
|
|
931
|
+
const position = positionName !== null ? positions[positionName] || null : null;
|
|
932
|
+
const finalPath = path || (slotName !== null ? slotsPath[slotName] : null) || (positionName !== null ? slotsPath[positionName] : null);
|
|
933
|
+
const finalSize = size !== null ? size : position.size;
|
|
934
|
+
|
|
935
|
+
// Targeting
|
|
936
|
+
const contextTargeting = useAdsTargeting();
|
|
937
|
+
const finalSizeMapping = useMemo(() => sizeMapping !== null ? sizeMapping : getSizeMappingFromPosition(position, viewports), [sizeMapping, position, viewports]);
|
|
938
|
+
const allTargeting = useMemo(() => contextTargeting !== null || targeting !== null || positionName !== null ? {
|
|
939
|
+
position: positionName,
|
|
940
|
+
...contextTargeting,
|
|
941
|
+
...targeting
|
|
942
|
+
} : null, [contextTargeting, targeting, positionName]);
|
|
943
|
+
const finalAdTargeting = useMemo(() => {
|
|
944
|
+
const {
|
|
945
|
+
refreshAds = null,
|
|
946
|
+
...otherProps
|
|
947
|
+
} = allTargeting || {};
|
|
948
|
+
return {
|
|
949
|
+
refreshInterval: refreshAds !== null && refreshAds === 'inactive' ? null : refreshInterval,
|
|
950
|
+
targeting: otherProps || {}
|
|
951
|
+
};
|
|
952
|
+
}, [allTargeting, refreshInterval]);
|
|
953
|
+
|
|
954
|
+
// Create ad
|
|
955
|
+
const {
|
|
956
|
+
disabled: adsDisabled,
|
|
957
|
+
id,
|
|
958
|
+
width,
|
|
959
|
+
height,
|
|
960
|
+
isEmpty,
|
|
961
|
+
isRendered,
|
|
962
|
+
refObserver
|
|
963
|
+
} = useAd(finalPath, finalSize, {
|
|
964
|
+
sizeMapping: finalSizeMapping,
|
|
965
|
+
targeting: finalAdTargeting.targeting,
|
|
966
|
+
refreshInterval: finalAdTargeting.refreshInterval,
|
|
967
|
+
alwaysRender,
|
|
968
|
+
onRender,
|
|
969
|
+
disabled
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
// Get size
|
|
973
|
+
const lastRenderedSize = useRef(null);
|
|
974
|
+
const wasDisabled = useRef(disabled);
|
|
975
|
+
const waitingNextRender = useMemo(() => {
|
|
976
|
+
if (disabled) {
|
|
977
|
+
wasDisabled.current = true;
|
|
978
|
+
} else if (!disabled && isRendered) {
|
|
979
|
+
wasDisabled.current = false;
|
|
980
|
+
}
|
|
981
|
+
return wasDisabled.current && !isRendered;
|
|
982
|
+
}, [isRendered]);
|
|
983
|
+
const sizeStyle = useMemo(() => {
|
|
984
|
+
if (disabled || waitingNextRender) {
|
|
985
|
+
return lastRenderedSize.current;
|
|
986
|
+
}
|
|
987
|
+
const {
|
|
988
|
+
width: minimumWidth,
|
|
989
|
+
height: minimumHeight
|
|
990
|
+
} = getMinimumAdSize(finalSizeMapping !== null ? finalSizeMapping.reduce((allSizes, sizeMap) => [...allSizes, sizeMap[1]], [finalSize]) : finalSize);
|
|
991
|
+
if (isRendered) {
|
|
992
|
+
lastRenderedSize.current = !isEmpty ? {
|
|
993
|
+
width,
|
|
994
|
+
height
|
|
995
|
+
} : null;
|
|
996
|
+
}
|
|
997
|
+
return {
|
|
998
|
+
width: isRendered ? width : minimumWidth,
|
|
999
|
+
height: isRendered ? height : minimumHeight
|
|
1000
|
+
};
|
|
1001
|
+
}, [id, disabled, finalSize, finalSizeMapping, width, height, isRendered, isEmpty]);
|
|
1002
|
+
const keepSize = (disabled || waitingNextRender) && lastRenderedSize.current !== null;
|
|
1003
|
+
if (id === null && !keepSize) {
|
|
1004
|
+
return null;
|
|
1005
|
+
}
|
|
1006
|
+
return /*#__PURE__*/jsx("div", {
|
|
1007
|
+
id: id !== null ? `${id}-container` : null,
|
|
1008
|
+
className: classNames([className, {
|
|
1009
|
+
[emptyClassName]: emptyClassName !== null && isEmpty && !keepSize
|
|
1010
|
+
}]),
|
|
1011
|
+
ref: refObserver,
|
|
1012
|
+
style: isEmpty && !keepSize ? {
|
|
1013
|
+
height: 0,
|
|
1014
|
+
paddingBottom: 0,
|
|
1015
|
+
overflow: 'hidden',
|
|
1016
|
+
opacity: 0
|
|
1017
|
+
} : null,
|
|
1018
|
+
children: /*#__PURE__*/jsx("div", {
|
|
1019
|
+
className: adClassName,
|
|
1020
|
+
style: {
|
|
1021
|
+
...sizeStyle,
|
|
1022
|
+
margin: 'auto'
|
|
1023
|
+
},
|
|
1024
|
+
children: /*#__PURE__*/jsx("div", {
|
|
1025
|
+
id: id
|
|
1026
|
+
})
|
|
1027
|
+
})
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
Ad.propTypes = propTypes;
|
|
1031
|
+
Ad.defaultProps = defaultProps;
|
|
644
1032
|
|
|
645
|
-
export { AdSlot, AdsManager, AdsProvider, useAdsContext };
|
|
1033
|
+
export { Ad, AdSlot, AdsManager, AdsProvider, AdsTargetingProvider, propTypes$3 as PropTypes, buildSizeMappingFromSizes, buildSizeMappingFromViewports, getAdSizes, getMinimumAdSize, getSizeMappingFromPosition, getSortedViewports, positions, sizeFitsInViewport, useAd, useAdsContext, useAdsTargeting, useTrackAd as useAdsTracking, viewports };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@folklore/ads",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Ads library",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"javascript",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"publishConfig": {
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "cbdee31b7e205f95c4ab462380feee74c076daa1",
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@folklore/hooks": "^0.0.41",
|
|
56
56
|
"@folklore/tracking": "^0.0.16",
|