@pcampus/reward-widget 0.1.0 → 0.2.0
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/README.md +27 -4
- package/dist/index.d.ts +5 -1
- package/dist/index.js +1 -1
- package/dist/theme.d.ts +5 -0
- package/dist/theme.js +24 -0
- package/dist/widgets/chrome.d.ts +13 -0
- package/dist/widgets/chrome.js +25 -0
- package/dist/widgets/coupon-success.d.ts +13 -0
- package/dist/widgets/coupon-success.js +256 -0
- package/dist/widgets/index.d.ts +1 -0
- package/dist/widgets/index.js +5 -4
- package/dist/widgets/mystery-box.js +310 -16
- package/dist/widgets/pick-card.d.ts +3 -0
- package/dist/widgets/pick-card.js +195 -33
- package/dist/widgets/quiz.d.ts +13 -3
- package/dist/widgets/quiz.js +396 -47
- package/dist/widgets/scratch.d.ts +3 -0
- package/dist/widgets/scratch.js +347 -47
- package/dist/widgets/spin.d.ts +12 -1
- package/dist/widgets/spin.js +278 -53
- package/dist/widgets/types.d.ts +19 -0
- package/package.json +12 -3
package/dist/widgets/scratch.js
CHANGED
|
@@ -1,78 +1,375 @@
|
|
|
1
|
+
import { parseHexRgb, resolveWidgetChrome, scaleRgb } from "./chrome.js";
|
|
2
|
+
import { showCouponSuccess } from "./coupon-success.js";
|
|
1
3
|
import { textEscape } from "./types.js";
|
|
4
|
+
const DEFAULT_SCRATCH_TEXT = "#f0efed";
|
|
5
|
+
/** Visible scratch face: Ticket color, or Foil color when ticket is unset. */
|
|
6
|
+
export function resolveScratchFoilTint(theme) {
|
|
7
|
+
const { primary } = resolveWidgetChrome(theme);
|
|
8
|
+
return theme?.hubBackgroundColor?.trim() || primary;
|
|
9
|
+
}
|
|
10
|
+
export function resolveScratchTextColor(theme) {
|
|
11
|
+
return theme?.textColor?.trim() || DEFAULT_SCRATCH_TEXT;
|
|
12
|
+
}
|
|
2
13
|
export function renderScratchCardMarkup(rewards = [], theme) {
|
|
3
|
-
const topReward = rewards[0]?.name || "
|
|
4
|
-
const primary = theme
|
|
14
|
+
const topReward = rewards[0]?.name || "ส่วนลด 100 บาท";
|
|
15
|
+
const { primary, surface, border } = resolveWidgetChrome(theme);
|
|
16
|
+
const ticket = theme?.hubBackgroundColor?.trim() || surface;
|
|
17
|
+
const ink = resolveScratchTextColor(theme);
|
|
5
18
|
return `
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
19
|
+
<style>
|
|
20
|
+
.pcampus-scratch-container {
|
|
21
|
+
position: relative;
|
|
22
|
+
width: 100%;
|
|
23
|
+
max-width: min(92vw, 34rem);
|
|
24
|
+
height: clamp(14rem, 42vw, 17rem);
|
|
25
|
+
background: ${ticket};
|
|
26
|
+
background-clip: padding-box;
|
|
27
|
+
border: 2px solid ${border};
|
|
28
|
+
border-radius: 18px;
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
|
|
31
|
+
display: flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
justify-content: center;
|
|
34
|
+
user-select: none;
|
|
35
|
+
box-sizing: border-box;
|
|
36
|
+
}
|
|
37
|
+
.pcampus-scratch-edge-left, .pcampus-scratch-edge-right {
|
|
38
|
+
position: absolute;
|
|
39
|
+
top: 0;
|
|
40
|
+
bottom: 0;
|
|
41
|
+
width: 14px;
|
|
42
|
+
background-image: radial-gradient(circle, #141413 6px, transparent 7px);
|
|
43
|
+
background-size: 16px 18px;
|
|
44
|
+
z-index: 10;
|
|
45
|
+
pointer-events: none;
|
|
46
|
+
}
|
|
47
|
+
.pcampus-scratch-edge-left { left: -7px; }
|
|
48
|
+
.pcampus-scratch-edge-right { right: -7px; }
|
|
49
|
+
.pcampus-scratch-under {
|
|
50
|
+
display: flex;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
align-items: center;
|
|
53
|
+
width: 100%;
|
|
54
|
+
height: 100%;
|
|
55
|
+
padding: 0.75rem;
|
|
56
|
+
box-sizing: border-box;
|
|
57
|
+
}
|
|
58
|
+
.pcampus-scratch-inner-frame {
|
|
59
|
+
width: 100%;
|
|
60
|
+
height: 100%;
|
|
61
|
+
border: 1.5px dashed rgba(240, 239, 237, 0.18);
|
|
62
|
+
border-radius: 12px;
|
|
63
|
+
display: flex;
|
|
64
|
+
flex-direction: column;
|
|
65
|
+
justify-content: space-between;
|
|
66
|
+
align-items: center;
|
|
67
|
+
padding: 1rem 1.25rem;
|
|
68
|
+
box-sizing: border-box;
|
|
69
|
+
text-align: center;
|
|
70
|
+
position: relative;
|
|
71
|
+
}
|
|
72
|
+
.pcampus-scratch-header-row {
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
justify-content: space-between;
|
|
76
|
+
width: 100%;
|
|
77
|
+
}
|
|
78
|
+
.pcampus-scratch-brand-badge {
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: 0.4rem;
|
|
82
|
+
font-size: clamp(0.65rem, 1.8vw, 0.75rem);
|
|
83
|
+
font-weight: 800;
|
|
84
|
+
color: ${ink};
|
|
85
|
+
letter-spacing: 0.06em;
|
|
86
|
+
text-transform: uppercase;
|
|
87
|
+
}
|
|
88
|
+
.pcampus-scratch-serial {
|
|
89
|
+
font-family: monospace;
|
|
90
|
+
font-size: clamp(0.62rem, 1.6vw, 0.72rem);
|
|
91
|
+
color: ${ink};
|
|
92
|
+
opacity: 0.72;
|
|
93
|
+
letter-spacing: 0.12em;
|
|
94
|
+
text-transform: uppercase;
|
|
95
|
+
}
|
|
96
|
+
.pcampus-scratch-prize-label {
|
|
97
|
+
font-size: clamp(0.72rem, 1.9vw, 0.82rem);
|
|
98
|
+
font-weight: 800;
|
|
99
|
+
color: ${ink};
|
|
100
|
+
text-transform: uppercase;
|
|
101
|
+
letter-spacing: 0.15em;
|
|
102
|
+
border-bottom: 2px dashed ${ink};
|
|
103
|
+
padding-bottom: 0.2rem;
|
|
104
|
+
}
|
|
105
|
+
.pcampus-scratch-prize-name {
|
|
106
|
+
font-size: clamp(1.35rem, 4.2vw, 1.95rem);
|
|
107
|
+
font-weight: 900;
|
|
108
|
+
color: ${ink};
|
|
109
|
+
line-height: 1.2;
|
|
110
|
+
letter-spacing: -0.02em;
|
|
111
|
+
z-index: 2;
|
|
112
|
+
}
|
|
113
|
+
.pcampus-scratch-watermark {
|
|
114
|
+
position: absolute;
|
|
115
|
+
top: 50%;
|
|
116
|
+
left: 50%;
|
|
117
|
+
transform: translate(-50%, -50%);
|
|
118
|
+
opacity: 0.12;
|
|
119
|
+
pointer-events: none;
|
|
120
|
+
max-width: 140px;
|
|
121
|
+
max-height: 90px;
|
|
122
|
+
display: flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
justify-content: center;
|
|
125
|
+
z-index: 1;
|
|
126
|
+
}
|
|
127
|
+
.pcampus-scratch-barcode {
|
|
128
|
+
font-family: monospace;
|
|
129
|
+
font-size: clamp(0.85rem, 2.3vw, 1.1rem);
|
|
130
|
+
color: ${ink};
|
|
131
|
+
opacity: 0.4;
|
|
132
|
+
letter-spacing: 4px;
|
|
133
|
+
user-select: none;
|
|
134
|
+
}
|
|
135
|
+
.pcampus-scratch-canvas {
|
|
136
|
+
position: absolute;
|
|
137
|
+
inset: 0;
|
|
138
|
+
width: 100%;
|
|
139
|
+
height: 100%;
|
|
140
|
+
cursor: crosshair;
|
|
141
|
+
touch-action: none;
|
|
142
|
+
z-index: 5;
|
|
143
|
+
}
|
|
144
|
+
.pcampus-scratch-guide-hint {
|
|
145
|
+
position: absolute;
|
|
146
|
+
inset: 0;
|
|
147
|
+
z-index: 6;
|
|
148
|
+
pointer-events: none;
|
|
149
|
+
display: flex;
|
|
150
|
+
flex-direction: column;
|
|
151
|
+
align-items: center;
|
|
152
|
+
justify-content: center;
|
|
153
|
+
gap: 0.45rem;
|
|
154
|
+
transition: opacity 250ms ease;
|
|
155
|
+
}
|
|
156
|
+
.pcampus-scratch-center-emblem {
|
|
157
|
+
height: 38px;
|
|
158
|
+
max-width: 120px;
|
|
159
|
+
display: flex;
|
|
160
|
+
align-items: center;
|
|
161
|
+
justify-content: center;
|
|
162
|
+
filter: drop-shadow(0 3px 8px rgba(0,0,0,0.7));
|
|
163
|
+
margin-bottom: 2px;
|
|
164
|
+
}
|
|
165
|
+
</style>
|
|
166
|
+
|
|
167
|
+
<div class="pcampus-scratch-widget-wrap" style="position:relative;display:flex;flex-direction:column;align-items:center;width:100%;box-sizing:border-box;">
|
|
168
|
+
<div class="pcampus-scratch-container">
|
|
169
|
+
<div class="pcampus-scratch-edge-left"></div>
|
|
170
|
+
<div class="pcampus-scratch-edge-right"></div>
|
|
171
|
+
|
|
172
|
+
<div class="pcampus-scratch-under">
|
|
173
|
+
<div class="pcampus-scratch-inner-frame">
|
|
174
|
+
<div class="pcampus-scratch-header-row">
|
|
175
|
+
<div class="pcampus-scratch-brand-badge">
|
|
176
|
+
<span style="color:${ink};"><i class="fa-solid fa-ticket"></i></span>
|
|
177
|
+
<span>${textEscape(theme?.brandName || "OFFICIAL REWARD TICKET")}</span>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="pcampus-scratch-serial">NO. #77291</div>
|
|
180
|
+
</div>
|
|
181
|
+
|
|
182
|
+
<!-- Center Stamped Brand Logo & Prize Section -->
|
|
183
|
+
<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:2;">
|
|
184
|
+
${theme?.brandLogoUrl ? `
|
|
185
|
+
<div style="height:26px;max-width:100px;display:flex;align-items:center;justify-content:center;margin-bottom:0.35rem;filter:drop-shadow(0 2px 5px rgba(0,0,0,0.5));">
|
|
186
|
+
<img src="${textEscape(theme.brandLogoUrl)}" alt="Brand Logo" style="height:100%;max-width:100%;object-fit:contain;" />
|
|
187
|
+
</div>
|
|
188
|
+
` : `
|
|
189
|
+
<div class="pcampus-scratch-prize-label">WINNER PRIZE</div>
|
|
190
|
+
`}
|
|
191
|
+
<div class="pcampus-scratch-prize-name">${textEscape(topReward)}</div>
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
${theme?.brandLogoUrl ? `
|
|
195
|
+
<div class="pcampus-scratch-watermark">
|
|
196
|
+
<img src="${textEscape(theme.brandLogoUrl)}" alt="Watermark" style="max-width:100%;max-height:100%;object-fit:contain;" />
|
|
197
|
+
</div>
|
|
198
|
+
` : ''}
|
|
199
|
+
|
|
200
|
+
<div class="pcampus-scratch-barcode">||| | |||| | || | |||| ||</div>
|
|
201
|
+
</div>
|
|
11
202
|
</div>
|
|
12
203
|
|
|
13
|
-
<canvas class="pcampus-scratch-canvas" width="
|
|
204
|
+
<canvas class="pcampus-scratch-canvas" width="480" height="240"></canvas>
|
|
14
205
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
206
|
+
<!-- Center Foil Overlay Guide with Prominent Brand Logo -->
|
|
207
|
+
<div class="pcampus-scratch-guide-hint">
|
|
208
|
+
${theme?.brandLogoUrl ? `
|
|
209
|
+
<div class="pcampus-scratch-center-emblem">
|
|
210
|
+
<img src="${textEscape(theme.brandLogoUrl)}" alt="Brand Logo" style="height:100%;max-width:100%;object-fit:contain;" />
|
|
211
|
+
</div>
|
|
212
|
+
` : `
|
|
213
|
+
<div style="width:38px;height:38px;border-radius:50%;background:${primary};display:flex;align-items:center;justify-content:center;color:#141413;box-shadow:0 4px 12px rgba(0,0,0,0.5);">
|
|
214
|
+
<i class="fa-solid fa-coins" style="font-size:1.1rem;"></i>
|
|
215
|
+
</div>
|
|
216
|
+
`}
|
|
217
|
+
<span style="font-size:0.78rem;font-weight:800;letter-spacing:0.08em;color:${ink};text-transform:uppercase;background:rgba(20,20,19,0.9);padding:3px 14px;border-radius:9999px;border:1px solid rgba(240,239,237,0.18);box-shadow:0 2px 8px rgba(0,0,0,0.4);">SCRATCH HERE</span>
|
|
22
218
|
</div>
|
|
23
219
|
</div>
|
|
24
|
-
|
|
220
|
+
|
|
221
|
+
<div style="margin-top:1rem;font-size:0.82rem;font-weight:600;color:${ink};opacity:0.78;display:flex;align-items:center;gap:0.4rem;">
|
|
222
|
+
<span><i class="fa-solid fa-hand-pointer" style="color:${primary};"></i></span>
|
|
223
|
+
<span>ใช้นิ้วหรือเมาส์ขูดฟอยล์สีเงินเพื่อเปิดดูรางวัล</span>
|
|
224
|
+
</div>
|
|
25
225
|
</div>
|
|
26
226
|
`;
|
|
27
227
|
}
|
|
228
|
+
function ensureFontAwesomeLoaded() {
|
|
229
|
+
if (typeof document === "undefined")
|
|
230
|
+
return;
|
|
231
|
+
const id = "pcampus-fa-cdn";
|
|
232
|
+
if (!document.getElementById(id)) {
|
|
233
|
+
const link = document.createElement("link");
|
|
234
|
+
link.id = id;
|
|
235
|
+
link.rel = "stylesheet";
|
|
236
|
+
link.href = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css";
|
|
237
|
+
document.head.appendChild(link);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
28
240
|
export function mountScratchCard(target, rewards = [], theme, onAction) {
|
|
241
|
+
ensureFontAwesomeLoaded();
|
|
29
242
|
target.innerHTML = renderScratchCardMarkup(rewards, theme);
|
|
30
243
|
const canvas = target.querySelector(".pcampus-scratch-canvas");
|
|
31
|
-
const hint = target.querySelector(".pcampus-scratch-
|
|
244
|
+
const hint = target.querySelector(".pcampus-scratch-guide-hint");
|
|
32
245
|
if (!canvas)
|
|
33
246
|
return;
|
|
34
|
-
const ctx = canvas.getContext("2d");
|
|
247
|
+
const ctx = canvas.getContext("2d", { willReadFrequently: true });
|
|
35
248
|
if (!ctx)
|
|
36
249
|
return;
|
|
37
|
-
//
|
|
38
|
-
|
|
250
|
+
// Initialize Canvas Resolution to match actual client display bounds
|
|
251
|
+
const rect = canvas.getBoundingClientRect();
|
|
252
|
+
if (rect.width > 0 && rect.height > 0) {
|
|
253
|
+
canvas.width = Math.round(rect.width * window.devicePixelRatio || rect.width);
|
|
254
|
+
canvas.height = Math.round(rect.height * window.devicePixelRatio || rect.height);
|
|
255
|
+
}
|
|
256
|
+
// Draw foil from Ticket color (hub), falling back to Foil color (primary)
|
|
257
|
+
const foilRgb = parseHexRgb(resolveScratchFoilTint(theme));
|
|
258
|
+
const grad = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
|
|
259
|
+
if (foilRgb) {
|
|
260
|
+
grad.addColorStop(0, scaleRgb(foilRgb, 0.72));
|
|
261
|
+
grad.addColorStop(0.35, scaleRgb(foilRgb, 1));
|
|
262
|
+
grad.addColorStop(0.7, scaleRgb(foilRgb, 0.78));
|
|
263
|
+
grad.addColorStop(1, scaleRgb(foilRgb, 0.55));
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
grad.addColorStop(0, "#42423f");
|
|
267
|
+
grad.addColorStop(0.35, "#686862");
|
|
268
|
+
grad.addColorStop(0.7, "#42423f");
|
|
269
|
+
grad.addColorStop(1, "#333330");
|
|
270
|
+
}
|
|
271
|
+
ctx.fillStyle = grad;
|
|
39
272
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
|
273
|
+
// Subtle Pattern Grid
|
|
274
|
+
ctx.fillStyle = "rgba(255, 255, 255, 0.08)";
|
|
275
|
+
for (let x = 12; x < canvas.width; x += 22) {
|
|
276
|
+
for (let y = 12; y < canvas.height; y += 22) {
|
|
277
|
+
ctx.beginPath();
|
|
278
|
+
ctx.arc(x, y, 2, 0, Math.PI * 2);
|
|
279
|
+
ctx.fill();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
40
282
|
let isDrawing = false;
|
|
41
|
-
let
|
|
42
|
-
|
|
283
|
+
let revealed = false;
|
|
284
|
+
let lastCheck = 0;
|
|
285
|
+
let lastX = 0;
|
|
286
|
+
let lastY = 0;
|
|
287
|
+
function checkPercent() {
|
|
288
|
+
if (revealed || !ctx || !canvas)
|
|
289
|
+
return;
|
|
290
|
+
const now = Date.now();
|
|
291
|
+
if (now - lastCheck < 160)
|
|
292
|
+
return;
|
|
293
|
+
lastCheck = now;
|
|
294
|
+
try {
|
|
295
|
+
const imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
296
|
+
const data = imgData.data;
|
|
297
|
+
let clear = 0;
|
|
298
|
+
const total = data.length / 4;
|
|
299
|
+
const step = 8;
|
|
300
|
+
for (let i = 3; i < data.length; i += 4 * step) {
|
|
301
|
+
if (data[i] === 0)
|
|
302
|
+
clear += step;
|
|
303
|
+
}
|
|
304
|
+
if (clear / total >= 0.4) {
|
|
305
|
+
revealed = true;
|
|
306
|
+
canvas.style.transition = "opacity 400ms ease";
|
|
307
|
+
canvas.style.opacity = "0";
|
|
308
|
+
if (hint)
|
|
309
|
+
hint.style.opacity = "0";
|
|
310
|
+
setTimeout(() => {
|
|
311
|
+
canvas.remove();
|
|
312
|
+
if (rewards[0]) {
|
|
313
|
+
showCouponSuccess({
|
|
314
|
+
rewardName: rewards[0].name,
|
|
315
|
+
couponCode: rewards[0].couponCode,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
if (onAction)
|
|
319
|
+
onAction(rewards[0]);
|
|
320
|
+
}, 420);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
catch { }
|
|
324
|
+
}
|
|
325
|
+
const scratch = (x, y, isMove = false) => {
|
|
326
|
+
if (revealed || !ctx)
|
|
327
|
+
return;
|
|
328
|
+
// Set 100% solid opacity eraser (fixes 6% opacity bug)
|
|
43
329
|
ctx.globalCompositeOperation = "destination-out";
|
|
330
|
+
ctx.fillStyle = "rgba(0, 0, 0, 1)";
|
|
331
|
+
ctx.strokeStyle = "rgba(0, 0, 0, 1)";
|
|
332
|
+
ctx.lineWidth = Math.max(34, canvas.width * 0.09);
|
|
333
|
+
ctx.lineCap = "round";
|
|
334
|
+
ctx.lineJoin = "round";
|
|
44
335
|
ctx.beginPath();
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
hint.style.transition = "opacity 200ms ease";
|
|
336
|
+
if (isMove) {
|
|
337
|
+
ctx.moveTo(lastX, lastY);
|
|
338
|
+
ctx.lineTo(x, y);
|
|
339
|
+
ctx.stroke();
|
|
50
340
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
onAction(rewards[0]);
|
|
341
|
+
else {
|
|
342
|
+
ctx.arc(x, y, Math.max(18, canvas.width * 0.045), 0, Math.PI * 2);
|
|
343
|
+
ctx.fill();
|
|
55
344
|
}
|
|
345
|
+
lastX = x;
|
|
346
|
+
lastY = y;
|
|
347
|
+
if (hint && hint.style.opacity !== "0") {
|
|
348
|
+
hint.style.opacity = "0";
|
|
349
|
+
}
|
|
350
|
+
checkPercent();
|
|
56
351
|
};
|
|
57
|
-
const getPos = (
|
|
58
|
-
const
|
|
59
|
-
const scaleX = canvas.width /
|
|
60
|
-
const scaleY = canvas.height /
|
|
352
|
+
const getPos = (clientX, clientY) => {
|
|
353
|
+
const cRect = canvas.getBoundingClientRect();
|
|
354
|
+
const scaleX = canvas.width / cRect.width;
|
|
355
|
+
const scaleY = canvas.height / cRect.height;
|
|
61
356
|
return {
|
|
62
|
-
x: (
|
|
63
|
-
y: (
|
|
357
|
+
x: (clientX - cRect.left) * scaleX,
|
|
358
|
+
y: (clientY - cRect.top) * scaleY,
|
|
64
359
|
};
|
|
65
360
|
};
|
|
66
361
|
canvas.addEventListener("mousedown", (e) => {
|
|
67
362
|
isDrawing = true;
|
|
68
|
-
const pos = getPos(e);
|
|
69
|
-
|
|
363
|
+
const pos = getPos(e.clientX, e.clientY);
|
|
364
|
+
lastX = pos.x;
|
|
365
|
+
lastY = pos.y;
|
|
366
|
+
scratch(pos.x, pos.y, false);
|
|
70
367
|
});
|
|
71
368
|
window.addEventListener("mousemove", (e) => {
|
|
72
369
|
if (!isDrawing)
|
|
73
370
|
return;
|
|
74
|
-
const pos = getPos(e);
|
|
75
|
-
scratch(pos.x, pos.y);
|
|
371
|
+
const pos = getPos(e.clientX, e.clientY);
|
|
372
|
+
scratch(pos.x, pos.y, true);
|
|
76
373
|
});
|
|
77
374
|
window.addEventListener("mouseup", () => {
|
|
78
375
|
isDrawing = false;
|
|
@@ -80,16 +377,19 @@ export function mountScratchCard(target, rewards = [], theme, onAction) {
|
|
|
80
377
|
canvas.addEventListener("touchstart", (e) => {
|
|
81
378
|
if (e.touches[0]) {
|
|
82
379
|
isDrawing = true;
|
|
83
|
-
const pos = getPos(e.touches[0]);
|
|
84
|
-
|
|
380
|
+
const pos = getPos(e.touches[0].clientX, e.touches[0].clientY);
|
|
381
|
+
lastX = pos.x;
|
|
382
|
+
lastY = pos.y;
|
|
383
|
+
scratch(pos.x, pos.y, false);
|
|
85
384
|
}
|
|
86
|
-
});
|
|
385
|
+
}, { passive: false });
|
|
87
386
|
canvas.addEventListener("touchmove", (e) => {
|
|
88
387
|
if (!isDrawing || !e.touches[0])
|
|
89
388
|
return;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
389
|
+
e.preventDefault();
|
|
390
|
+
const pos = getPos(e.touches[0].clientX, e.touches[0].clientY);
|
|
391
|
+
scratch(pos.x, pos.y, true);
|
|
392
|
+
}, { passive: false });
|
|
93
393
|
canvas.addEventListener("touchend", () => {
|
|
94
394
|
isDrawing = false;
|
|
95
395
|
});
|
package/dist/widgets/spin.d.ts
CHANGED
|
@@ -4,7 +4,13 @@ export declare const MIN_WHEEL_SLICES = 6;
|
|
|
4
4
|
export declare const WHEEL_CX = 160;
|
|
5
5
|
export declare const WHEEL_CY = 160;
|
|
6
6
|
export declare const WHEEL_R = 160;
|
|
7
|
-
export declare const
|
|
7
|
+
export declare const PCAMPUS_SURFACE_CARD = "#1c1c1b";
|
|
8
|
+
export declare const PCAMPUS_SURFACE_SLATE = "#262624";
|
|
9
|
+
export declare const PCAMPUS_SURFACE_ONYX = "#181817";
|
|
10
|
+
export declare const PCAMPUS_ACCENT_BLUE = "#4b7fd4";
|
|
11
|
+
export declare const PCAMPUS_ACCENT_GOLD = "#e8a96a";
|
|
12
|
+
export declare const PCAMPUS_BORDER_SUBTLE = "rgba(240, 239, 237, 0.12)";
|
|
13
|
+
export declare const DEFAULT_PCAMPUS_SLICE_COLORS: readonly ["#1c1c1b", "#262624", "#181817"];
|
|
8
14
|
export interface WheelSlice {
|
|
9
15
|
id?: string;
|
|
10
16
|
name: string;
|
|
@@ -18,5 +24,10 @@ export declare function polar(cx: number, cy: number, r: number, deg: number): [
|
|
|
18
24
|
export declare function slicePath(cx: number, cy: number, r: number, startDeg: number, endDeg: number): string;
|
|
19
25
|
export declare function visualSliceCounts(rewardCount: number): number[];
|
|
20
26
|
export declare function wheelSlices(rewards: WidgetRewardItem[]): WheelSlice[];
|
|
27
|
+
export declare function sliceFaIcon(name: string): {
|
|
28
|
+
style: "regular" | "solid";
|
|
29
|
+
icon: string;
|
|
30
|
+
};
|
|
31
|
+
export declare function sliceLabelLines(name: string): string[];
|
|
21
32
|
export declare function renderSpinWheelMarkup(rewards?: WidgetRewardItem[], theme?: RewardWidgetTheme): string;
|
|
22
33
|
export declare function mountSpinWheel(target: Element, rewards?: WidgetRewardItem[], theme?: RewardWidgetTheme, onAction?: (reward?: WidgetRewardItem) => void): void;
|