@playcraft/adsdk 1.0.16 → 1.0.18-beta.1
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/LICENSE +21 -21
- package/defines.d.ts +130 -130
- package/dist/esm/index.js +146 -80
- package/dist/iife/index.js +146 -80
- package/dist/index.d.mts +69 -31
- package/dist/index.d.ts +69 -31
- package/dist/index.js +146 -80
- package/package.json +56 -56
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025-present Smoud
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present Smoud
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/defines.d.ts
CHANGED
|
@@ -1,130 +1,130 @@
|
|
|
1
|
-
declare const mraid: {
|
|
2
|
-
getVersion: () => string; // MRAID 规范必需:返回 MRAID 版本(如 "3.0")
|
|
3
|
-
isReady: () => boolean;
|
|
4
|
-
isViewable: () => boolean;
|
|
5
|
-
getState: () => string;
|
|
6
|
-
addEventListener: (
|
|
7
|
-
event: 'viewableChange' | 'sizeChange' | 'ready' | 'audioVolumeChange' | 'stateChange' | 'error' | 'orientationChange' | 'resize',
|
|
8
|
-
callback: (...args: any[]) => void
|
|
9
|
-
) => void;
|
|
10
|
-
removeEventListener: (
|
|
11
|
-
event: 'viewableChange' | 'sizeChange' | 'ready' | 'audioVolumeChange' | 'stateChange' | 'error' | 'orientationChange' | 'resize',
|
|
12
|
-
callback: (...args: any[]) => void
|
|
13
|
-
) => void;
|
|
14
|
-
getMaxSize: () => { width: number; height: number };
|
|
15
|
-
openStoreUrl: () => void;
|
|
16
|
-
open: (url: string) => void;
|
|
17
|
-
close: () => void; // Unity Ads 必需:关闭广告
|
|
18
|
-
getAudioVolume: () => number;
|
|
19
|
-
fireTrackingEvent?: (event: string) => void; // Unity Ads 可选:跟踪事件
|
|
20
|
-
preloadStore?: () => void;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
declare const dapi: {
|
|
24
|
-
addEventListener: (
|
|
25
|
-
event: 'viewableChange' | 'adResized' | 'ready' | 'audioVolumeChange' | 'error',
|
|
26
|
-
callback: (...args: any[]) => void
|
|
27
|
-
) => void;
|
|
28
|
-
removeEventListener: (
|
|
29
|
-
event: 'viewableChange' | 'adResized' | 'ready' | 'audioVolumeChange' | 'error',
|
|
30
|
-
callback: (...args: any[]) => void
|
|
31
|
-
) => void;
|
|
32
|
-
getScreenSize: () => { width: number; height: number };
|
|
33
|
-
openStoreUrl: () => void;
|
|
34
|
-
getAudioVolume: () => number;
|
|
35
|
-
isViewable: () => boolean;
|
|
36
|
-
isReady: () => boolean;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
declare const NUC: {
|
|
40
|
-
trigger: {
|
|
41
|
-
convert: (destinationUrl: string) => void;
|
|
42
|
-
tryAgain: Function;
|
|
43
|
-
};
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
declare const ScPlayableAd: { onCTAClick: () => void };
|
|
47
|
-
|
|
48
|
-
// Adikteev 占位符变量
|
|
49
|
-
declare const AK_CLICK_DESTINATION_URL: string;
|
|
50
|
-
declare const AK_CLICK_PIXEL_URL: string;
|
|
51
|
-
declare const FbPlayableAd: { onCTAClick: () => void };
|
|
52
|
-
declare const smxTracking: { redirect: () => void };
|
|
53
|
-
declare const ExitApi: { exit: () => void };
|
|
54
|
-
|
|
55
|
-
declare const AD_NETWORK:
|
|
56
|
-
| 'preview'
|
|
57
|
-
| 'applovin'
|
|
58
|
-
| 'unity'
|
|
59
|
-
| 'google'
|
|
60
|
-
| 'ironsource'
|
|
61
|
-
| 'facebook'
|
|
62
|
-
| 'moloco'
|
|
63
|
-
| 'mintegral'
|
|
64
|
-
| 'vungle'
|
|
65
|
-
| 'adcolony'
|
|
66
|
-
| 'tapjoy'
|
|
67
|
-
| 'snapchat'
|
|
68
|
-
| 'tiktok'
|
|
69
|
-
| 'appreciate'
|
|
70
|
-
| 'chartboost'
|
|
71
|
-
| 'pangle'
|
|
72
|
-
| 'mytarget'
|
|
73
|
-
| 'liftoff'
|
|
74
|
-
| 'smadex'
|
|
75
|
-
| 'adikteev'
|
|
76
|
-
| 'bigabid'
|
|
77
|
-
| 'inmobi'
|
|
78
|
-
| 'bigoads';
|
|
79
|
-
|
|
80
|
-
declare const AD_PROTOCOL: 'mraid' | 'dapi' | 'nucleo' | 'none';
|
|
81
|
-
declare const GOOGLE_PLAY_URL: string;
|
|
82
|
-
declare const APP_STORE_URL: string;
|
|
83
|
-
declare const BUILD_HASH: string;
|
|
84
|
-
|
|
85
|
-
interface Window {
|
|
86
|
-
PlayableSDK: any;
|
|
87
|
-
ADS_MRAID_CONFIG: {
|
|
88
|
-
landUrl: string;
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// AppLovin Playable Analytics
|
|
92
|
-
// 文档: https://support.axon.ai/en/growth/promoting-your-apps/creatives/playable-analytics-integration
|
|
93
|
-
ALPlayableAnalytics?: {
|
|
94
|
-
trackEvent: (event: string) => void;
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// BigoAds SDK
|
|
98
|
-
// 文档: https://www.bigoads.com/help/detail?id=143&moduleId=7¤tLan=CN
|
|
99
|
-
BGY_MRAID: {
|
|
100
|
-
open: () => void; // 打开应用商店/推广地址
|
|
101
|
-
gameReady: () => void; // 素材准备完毕时调用
|
|
102
|
-
gameEnd: () => void; // 游戏结束时调用
|
|
103
|
-
isViewable: () => boolean;
|
|
104
|
-
addEventListener: (event: string, callback: (...args: any[]) => void) => void;
|
|
105
|
-
removeEventListener: (event: string, callback: (...args: any[]) => void) => void;
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
// Mintegral functions
|
|
109
|
-
gameReady: Function;
|
|
110
|
-
gameEnd: Function;
|
|
111
|
-
gameRetry: Function;
|
|
112
|
-
install: Function;
|
|
113
|
-
mintGameStart: Function;
|
|
114
|
-
mintGameClose: Function;
|
|
115
|
-
|
|
116
|
-
// Tapjoy functions
|
|
117
|
-
TJ_API: {
|
|
118
|
-
objectiveComplete: Function;
|
|
119
|
-
playableFinished: Function;
|
|
120
|
-
gameplayFinished: Function;
|
|
121
|
-
setPlayableBuild: Function;
|
|
122
|
-
setPlayableAPI: Function;
|
|
123
|
-
click: Function;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
BIGABID_BIDTIMEMACROS?: Record<string, string>
|
|
127
|
-
INMOBI_DSPMACROS?: Record<string, string>
|
|
128
|
-
|
|
129
|
-
openAppStore: Function;
|
|
130
|
-
}
|
|
1
|
+
declare const mraid: {
|
|
2
|
+
getVersion: () => string; // MRAID 规范必需:返回 MRAID 版本(如 "3.0")
|
|
3
|
+
isReady: () => boolean;
|
|
4
|
+
isViewable: () => boolean;
|
|
5
|
+
getState: () => string;
|
|
6
|
+
addEventListener: (
|
|
7
|
+
event: 'viewableChange' | 'sizeChange' | 'ready' | 'audioVolumeChange' | 'stateChange' | 'error' | 'orientationChange' | 'resize',
|
|
8
|
+
callback: (...args: any[]) => void
|
|
9
|
+
) => void;
|
|
10
|
+
removeEventListener: (
|
|
11
|
+
event: 'viewableChange' | 'sizeChange' | 'ready' | 'audioVolumeChange' | 'stateChange' | 'error' | 'orientationChange' | 'resize',
|
|
12
|
+
callback: (...args: any[]) => void
|
|
13
|
+
) => void;
|
|
14
|
+
getMaxSize: () => { width: number; height: number };
|
|
15
|
+
openStoreUrl: () => void;
|
|
16
|
+
open: (url: string) => void;
|
|
17
|
+
close: () => void; // Unity Ads 必需:关闭广告
|
|
18
|
+
getAudioVolume: () => number;
|
|
19
|
+
fireTrackingEvent?: (event: string) => void; // Unity Ads 可选:跟踪事件
|
|
20
|
+
preloadStore?: () => void;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
declare const dapi: {
|
|
24
|
+
addEventListener: (
|
|
25
|
+
event: 'viewableChange' | 'adResized' | 'ready' | 'audioVolumeChange' | 'error',
|
|
26
|
+
callback: (...args: any[]) => void
|
|
27
|
+
) => void;
|
|
28
|
+
removeEventListener: (
|
|
29
|
+
event: 'viewableChange' | 'adResized' | 'ready' | 'audioVolumeChange' | 'error',
|
|
30
|
+
callback: (...args: any[]) => void
|
|
31
|
+
) => void;
|
|
32
|
+
getScreenSize: () => { width: number; height: number };
|
|
33
|
+
openStoreUrl: () => void;
|
|
34
|
+
getAudioVolume: () => number;
|
|
35
|
+
isViewable: () => boolean;
|
|
36
|
+
isReady: () => boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
declare const NUC: {
|
|
40
|
+
trigger: {
|
|
41
|
+
convert: (destinationUrl: string) => void;
|
|
42
|
+
tryAgain: Function;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
declare const ScPlayableAd: { onCTAClick: () => void };
|
|
47
|
+
|
|
48
|
+
// Adikteev 占位符变量
|
|
49
|
+
declare const AK_CLICK_DESTINATION_URL: string;
|
|
50
|
+
declare const AK_CLICK_PIXEL_URL: string;
|
|
51
|
+
declare const FbPlayableAd: { onCTAClick: () => void };
|
|
52
|
+
declare const smxTracking: { redirect: () => void };
|
|
53
|
+
declare const ExitApi: { exit: () => void };
|
|
54
|
+
|
|
55
|
+
declare const AD_NETWORK:
|
|
56
|
+
| 'preview'
|
|
57
|
+
| 'applovin'
|
|
58
|
+
| 'unity'
|
|
59
|
+
| 'google'
|
|
60
|
+
| 'ironsource'
|
|
61
|
+
| 'facebook'
|
|
62
|
+
| 'moloco'
|
|
63
|
+
| 'mintegral'
|
|
64
|
+
| 'vungle'
|
|
65
|
+
| 'adcolony'
|
|
66
|
+
| 'tapjoy'
|
|
67
|
+
| 'snapchat'
|
|
68
|
+
| 'tiktok'
|
|
69
|
+
| 'appreciate'
|
|
70
|
+
| 'chartboost'
|
|
71
|
+
| 'pangle'
|
|
72
|
+
| 'mytarget'
|
|
73
|
+
| 'liftoff'
|
|
74
|
+
| 'smadex'
|
|
75
|
+
| 'adikteev'
|
|
76
|
+
| 'bigabid'
|
|
77
|
+
| 'inmobi'
|
|
78
|
+
| 'bigoads';
|
|
79
|
+
|
|
80
|
+
declare const AD_PROTOCOL: 'mraid' | 'dapi' | 'nucleo' | 'none';
|
|
81
|
+
declare const GOOGLE_PLAY_URL: string;
|
|
82
|
+
declare const APP_STORE_URL: string;
|
|
83
|
+
declare const BUILD_HASH: string;
|
|
84
|
+
|
|
85
|
+
interface Window {
|
|
86
|
+
PlayableSDK: any;
|
|
87
|
+
ADS_MRAID_CONFIG: {
|
|
88
|
+
landUrl: string;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// AppLovin Playable Analytics
|
|
92
|
+
// 文档: https://support.axon.ai/en/growth/promoting-your-apps/creatives/playable-analytics-integration
|
|
93
|
+
ALPlayableAnalytics?: {
|
|
94
|
+
trackEvent: (event: string) => void;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// BigoAds SDK
|
|
98
|
+
// 文档: https://www.bigoads.com/help/detail?id=143&moduleId=7¤tLan=CN
|
|
99
|
+
BGY_MRAID: {
|
|
100
|
+
open: () => void; // 打开应用商店/推广地址
|
|
101
|
+
gameReady: () => void; // 素材准备完毕时调用
|
|
102
|
+
gameEnd: () => void; // 游戏结束时调用
|
|
103
|
+
isViewable: () => boolean;
|
|
104
|
+
addEventListener: (event: string, callback: (...args: any[]) => void) => void;
|
|
105
|
+
removeEventListener: (event: string, callback: (...args: any[]) => void) => void;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// Mintegral functions
|
|
109
|
+
gameReady: Function;
|
|
110
|
+
gameEnd: Function;
|
|
111
|
+
gameRetry: Function;
|
|
112
|
+
install: Function;
|
|
113
|
+
mintGameStart: Function;
|
|
114
|
+
mintGameClose: Function;
|
|
115
|
+
|
|
116
|
+
// Tapjoy functions
|
|
117
|
+
TJ_API: {
|
|
118
|
+
objectiveComplete: Function;
|
|
119
|
+
playableFinished: Function;
|
|
120
|
+
gameplayFinished: Function;
|
|
121
|
+
setPlayableBuild: Function;
|
|
122
|
+
setPlayableAPI: Function;
|
|
123
|
+
click: Function;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
BIGABID_BIDTIMEMACROS?: Record<string, string>
|
|
127
|
+
INMOBI_DSPMACROS?: Record<string, string>
|
|
128
|
+
|
|
129
|
+
openAppStore: Function;
|
|
130
|
+
}
|
package/dist/esm/index.js
CHANGED
|
@@ -461,6 +461,38 @@ function extractDefaultsFromSchema(schema) {
|
|
|
461
461
|
}
|
|
462
462
|
return void 0;
|
|
463
463
|
}
|
|
464
|
+
function getLanguageCode() {
|
|
465
|
+
try {
|
|
466
|
+
return (navigator.language || "en").split("-")[0].toLowerCase();
|
|
467
|
+
} catch (e) {
|
|
468
|
+
return "en";
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
function lookupI18nRuntime(runtime, key, langCode) {
|
|
472
|
+
var _a, _b;
|
|
473
|
+
const map = runtime[key];
|
|
474
|
+
if (!map || typeof map !== "object") return void 0;
|
|
475
|
+
return (_b = (_a = map[langCode]) != null ? _a : map["en"]) != null ? _b : Object.values(map)[0];
|
|
476
|
+
}
|
|
477
|
+
function resolveI18nRefs(config, i18nRecord, langCode) {
|
|
478
|
+
var _a;
|
|
479
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) return;
|
|
480
|
+
const runtime = (_a = i18nRecord.runtime) != null ? _a : {};
|
|
481
|
+
for (const key of Object.keys(config)) {
|
|
482
|
+
const value = config[key];
|
|
483
|
+
if (typeof value === "string") {
|
|
484
|
+
if (value.startsWith("i18n.runtime.")) {
|
|
485
|
+
const i18nKey = value.slice("i18n.runtime.".length);
|
|
486
|
+
const resolved = lookupI18nRuntime(runtime, i18nKey, langCode);
|
|
487
|
+
if (resolved !== void 0) {
|
|
488
|
+
config[key] = resolved;
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
} else if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
492
|
+
resolveI18nRefs(value, i18nRecord, langCode);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
}
|
|
464
496
|
function resolveImagePaths(config, assetRecordByPath) {
|
|
465
497
|
if (!assetRecordByPath || !config || typeof config !== "object") return;
|
|
466
498
|
for (const key of Object.keys(config)) {
|
|
@@ -488,7 +520,7 @@ function deepMerge(target, source) {
|
|
|
488
520
|
return target;
|
|
489
521
|
}
|
|
490
522
|
function setConfig(configList, config) {
|
|
491
|
-
const { assetRecordByPath } = config;
|
|
523
|
+
const { assetRecordByPath, i18nRecord } = config;
|
|
492
524
|
const resolvedConfigs = configList.map((item) => {
|
|
493
525
|
var _a;
|
|
494
526
|
if (!item) return {};
|
|
@@ -499,6 +531,10 @@ function setConfig(configList, config) {
|
|
|
499
531
|
for (const data of rest) {
|
|
500
532
|
deepMerge(mergedConfig, data);
|
|
501
533
|
}
|
|
534
|
+
if (i18nRecord) {
|
|
535
|
+
const langCode = getLanguageCode();
|
|
536
|
+
resolveI18nRefs(mergedConfig, i18nRecord, langCode);
|
|
537
|
+
}
|
|
502
538
|
resolveImagePaths(mergedConfig, assetRecordByPath);
|
|
503
539
|
_cachedConfig = mergedConfig;
|
|
504
540
|
}
|
|
@@ -510,6 +546,83 @@ function getConfig() {
|
|
|
510
546
|
return _cachedConfig;
|
|
511
547
|
}
|
|
512
548
|
|
|
549
|
+
// src/cursor.ts
|
|
550
|
+
var cleanup = null;
|
|
551
|
+
function toCursor(src, size) {
|
|
552
|
+
const hotspot = Math.round(size / 8);
|
|
553
|
+
return new Promise((resolve, reject) => {
|
|
554
|
+
const img = new Image();
|
|
555
|
+
img.onload = () => {
|
|
556
|
+
const c = document.createElement("canvas");
|
|
557
|
+
c.width = size;
|
|
558
|
+
c.height = size;
|
|
559
|
+
const ctx = c.getContext("2d");
|
|
560
|
+
if (!ctx) {
|
|
561
|
+
reject(new Error("[PlayableSDK] Failed to get 2d context for cursor"));
|
|
562
|
+
return;
|
|
563
|
+
}
|
|
564
|
+
ctx.drawImage(img, 0, 0, size, size);
|
|
565
|
+
resolve(`url(${c.toDataURL("image/png")}) ${hotspot} ${hotspot}, pointer`);
|
|
566
|
+
};
|
|
567
|
+
img.onerror = () => reject(new Error("[PlayableSDK] Failed to load cursor image"));
|
|
568
|
+
img.src = src;
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
function enableCustomCursor(opts = {}) {
|
|
572
|
+
var _a, _b;
|
|
573
|
+
cleanup == null ? void 0 : cleanup();
|
|
574
|
+
cleanup = null;
|
|
575
|
+
if (typeof document === "undefined") return () => {
|
|
576
|
+
};
|
|
577
|
+
const target = (_a = opts.target) != null ? _a : document.body;
|
|
578
|
+
if (!target) {
|
|
579
|
+
console.warn("[PlayableSDK] enableCustomCursor: target not found");
|
|
580
|
+
return () => {
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
const size = (_b = opts.size) != null ? _b : 64;
|
|
584
|
+
const prevCursor = target.style.cursor;
|
|
585
|
+
let disposed = false;
|
|
586
|
+
let down = null;
|
|
587
|
+
let up = null;
|
|
588
|
+
const dispose = () => {
|
|
589
|
+
if (disposed) return;
|
|
590
|
+
disposed = true;
|
|
591
|
+
target.style.cursor = prevCursor;
|
|
592
|
+
if (down) target.removeEventListener("pointerdown", down);
|
|
593
|
+
if (up) {
|
|
594
|
+
target.removeEventListener("pointerup", up);
|
|
595
|
+
target.removeEventListener("pointercancel", up);
|
|
596
|
+
}
|
|
597
|
+
if (cleanup === dispose) cleanup = null;
|
|
598
|
+
};
|
|
599
|
+
cleanup = dispose;
|
|
600
|
+
Promise.all([
|
|
601
|
+
toCursor(FINGER_HOVERING, size),
|
|
602
|
+
toCursor(FINGER_PRESSING, size)
|
|
603
|
+
]).then(([hover, press]) => {
|
|
604
|
+
if (disposed) return;
|
|
605
|
+
target.style.cursor = hover;
|
|
606
|
+
down = () => {
|
|
607
|
+
target.style.cursor = press;
|
|
608
|
+
};
|
|
609
|
+
up = () => {
|
|
610
|
+
target.style.cursor = hover;
|
|
611
|
+
};
|
|
612
|
+
target.addEventListener("pointerdown", down);
|
|
613
|
+
target.addEventListener("pointerup", up);
|
|
614
|
+
target.addEventListener("pointercancel", up);
|
|
615
|
+
}).catch((err) => {
|
|
616
|
+
console.warn("[PlayableSDK] enableCustomCursor failed:", err);
|
|
617
|
+
dispose();
|
|
618
|
+
});
|
|
619
|
+
return dispose;
|
|
620
|
+
}
|
|
621
|
+
function disableCustomCursor() {
|
|
622
|
+
cleanup == null ? void 0 : cleanup();
|
|
623
|
+
cleanup = null;
|
|
624
|
+
}
|
|
625
|
+
|
|
513
626
|
// src/core.ts
|
|
514
627
|
var destinationUrl = "";
|
|
515
628
|
var isSDKInitialized = false;
|
|
@@ -845,6 +958,7 @@ var _sdk = class _sdk {
|
|
|
845
958
|
* This must be called as earlier as possible.
|
|
846
959
|
*
|
|
847
960
|
* @param callback Optional function called when ad container is ready
|
|
961
|
+
* @param options Optional configuration options
|
|
848
962
|
* @example
|
|
849
963
|
* // Basic initialization
|
|
850
964
|
* sdk.playcraftInit();
|
|
@@ -857,12 +971,15 @@ var _sdk = class _sdk {
|
|
|
857
971
|
* @fires playcraftInit When SDK initialization starts
|
|
858
972
|
* @fires playcraftReady When game instance is created and ready to load resources
|
|
859
973
|
*/
|
|
860
|
-
static playcraftInit(callback) {
|
|
974
|
+
static playcraftInit(callback, options) {
|
|
861
975
|
if (isSDKInitialized) return;
|
|
862
976
|
if (callback) initCallback = callback;
|
|
863
977
|
initTrackingProtocols();
|
|
864
978
|
document.readyState === "loading" ? window.addEventListener("DOMContentLoaded", initSDK) : initSDK();
|
|
865
979
|
isSDKInitialized = true;
|
|
980
|
+
if ((options == null ? void 0 : options.useCustomCursor) !== false) {
|
|
981
|
+
enableCustomCursor();
|
|
982
|
+
}
|
|
866
983
|
}
|
|
867
984
|
/**
|
|
868
985
|
* Starts the playable ad experience.
|
|
@@ -1255,9 +1372,35 @@ var _sdk = class _sdk {
|
|
|
1255
1372
|
static getConfig() {
|
|
1256
1373
|
return getConfig();
|
|
1257
1374
|
}
|
|
1375
|
+
/**
|
|
1376
|
+
* 启用自定义鼠标指针。默认挂载到 `document.body`,作用于整个页面。
|
|
1377
|
+
* 悬浮显示手指图标,按下时切换为按压态图标。
|
|
1378
|
+
* 多次调用会先清理上一次的状态再重新绑定。
|
|
1379
|
+
*
|
|
1380
|
+
* @param opts 可选配置
|
|
1381
|
+
* - opts.target: 目标元素,未传则默认 document.body
|
|
1382
|
+
* - opts.size: 光标尺寸(像素),默认 64,热点固定为 size 的 1/8
|
|
1383
|
+
* @returns 清理函数,调用后会恢复默认光标并解除事件监听
|
|
1384
|
+
*
|
|
1385
|
+
* @example
|
|
1386
|
+
* sdk.enableCustomCursor();
|
|
1387
|
+
* sdk.enableCustomCursor({ size: 96 });
|
|
1388
|
+
*/
|
|
1389
|
+
static enableCustomCursor(opts) {
|
|
1390
|
+
return enableCustomCursor(opts);
|
|
1391
|
+
}
|
|
1392
|
+
/**
|
|
1393
|
+
* 关闭自定义鼠标指针,恢复默认光标。
|
|
1394
|
+
*
|
|
1395
|
+
* @example
|
|
1396
|
+
* sdk.disableCustomCursor();
|
|
1397
|
+
*/
|
|
1398
|
+
static disableCustomCursor() {
|
|
1399
|
+
disableCustomCursor();
|
|
1400
|
+
}
|
|
1258
1401
|
};
|
|
1259
1402
|
/** Current version of the SDK */
|
|
1260
|
-
_sdk.version = "1.0.
|
|
1403
|
+
_sdk.version = "1.0.18-beta.1";
|
|
1261
1404
|
/** Current maximum width of the playable ad container in pixels */
|
|
1262
1405
|
_sdk.maxWidth = Math.floor(window.innerWidth);
|
|
1263
1406
|
/** Current maximum height of the playable ad container in pixels */
|
|
@@ -1283,83 +1426,6 @@ window["console"].log(
|
|
|
1283
1426
|
"background: #e1e4e8; color: #333; font-size: 14px; padding: 4px 8px; border-top-right-radius: 4px; border-bottom-right-radius: 4px;"
|
|
1284
1427
|
);
|
|
1285
1428
|
window.PlayableSDK = sdk;
|
|
1286
|
-
|
|
1287
|
-
// src/cursor.ts
|
|
1288
|
-
var cleanup = null;
|
|
1289
|
-
function toCursor(src, size) {
|
|
1290
|
-
const hotspot = Math.round(size / 8);
|
|
1291
|
-
return new Promise((resolve, reject) => {
|
|
1292
|
-
const img = new Image();
|
|
1293
|
-
img.onload = () => {
|
|
1294
|
-
const c = document.createElement("canvas");
|
|
1295
|
-
c.width = size;
|
|
1296
|
-
c.height = size;
|
|
1297
|
-
const ctx = c.getContext("2d");
|
|
1298
|
-
if (!ctx) {
|
|
1299
|
-
reject(new Error("[PlayableSDK] Failed to get 2d context for cursor"));
|
|
1300
|
-
return;
|
|
1301
|
-
}
|
|
1302
|
-
ctx.drawImage(img, 0, 0, size, size);
|
|
1303
|
-
resolve(`url(${c.toDataURL("image/png")}) ${hotspot} ${hotspot}, pointer`);
|
|
1304
|
-
};
|
|
1305
|
-
img.onerror = () => reject(new Error("[PlayableSDK] Failed to load cursor image"));
|
|
1306
|
-
img.src = src;
|
|
1307
|
-
});
|
|
1308
|
-
}
|
|
1309
|
-
function enableCustomCursor(opts = {}) {
|
|
1310
|
-
var _a, _b;
|
|
1311
|
-
cleanup == null ? void 0 : cleanup();
|
|
1312
|
-
cleanup = null;
|
|
1313
|
-
if (typeof document === "undefined") return () => {
|
|
1314
|
-
};
|
|
1315
|
-
const target = (_a = opts.target) != null ? _a : document.body;
|
|
1316
|
-
if (!target) {
|
|
1317
|
-
console.warn("[PlayableSDK] enableCustomCursor: target not found");
|
|
1318
|
-
return () => {
|
|
1319
|
-
};
|
|
1320
|
-
}
|
|
1321
|
-
const size = (_b = opts.size) != null ? _b : 64;
|
|
1322
|
-
const prevCursor = target.style.cursor;
|
|
1323
|
-
let disposed = false;
|
|
1324
|
-
let down = null;
|
|
1325
|
-
let up = null;
|
|
1326
|
-
const dispose = () => {
|
|
1327
|
-
if (disposed) return;
|
|
1328
|
-
disposed = true;
|
|
1329
|
-
target.style.cursor = prevCursor;
|
|
1330
|
-
if (down) target.removeEventListener("pointerdown", down);
|
|
1331
|
-
if (up) {
|
|
1332
|
-
target.removeEventListener("pointerup", up);
|
|
1333
|
-
target.removeEventListener("pointercancel", up);
|
|
1334
|
-
}
|
|
1335
|
-
if (cleanup === dispose) cleanup = null;
|
|
1336
|
-
};
|
|
1337
|
-
cleanup = dispose;
|
|
1338
|
-
Promise.all([
|
|
1339
|
-
toCursor(FINGER_HOVERING, size),
|
|
1340
|
-
toCursor(FINGER_PRESSING, size)
|
|
1341
|
-
]).then(([hover, press]) => {
|
|
1342
|
-
if (disposed) return;
|
|
1343
|
-
target.style.cursor = hover;
|
|
1344
|
-
down = () => {
|
|
1345
|
-
target.style.cursor = press;
|
|
1346
|
-
};
|
|
1347
|
-
up = () => {
|
|
1348
|
-
target.style.cursor = hover;
|
|
1349
|
-
};
|
|
1350
|
-
target.addEventListener("pointerdown", down);
|
|
1351
|
-
target.addEventListener("pointerup", up);
|
|
1352
|
-
target.addEventListener("pointercancel", up);
|
|
1353
|
-
}).catch((err) => {
|
|
1354
|
-
console.warn("[PlayableSDK] enableCustomCursor failed:", err);
|
|
1355
|
-
dispose();
|
|
1356
|
-
});
|
|
1357
|
-
return dispose;
|
|
1358
|
-
}
|
|
1359
|
-
function disableCustomCursor() {
|
|
1360
|
-
cleanup == null ? void 0 : cleanup();
|
|
1361
|
-
cleanup = null;
|
|
1362
|
-
}
|
|
1363
1429
|
export {
|
|
1364
1430
|
sdk as default,
|
|
1365
1431
|
disableCustomCursor,
|