@zencemarketing/spin-scratch-sdk 0.1.0-alpha.1 → 0.1.0-alpha.2
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/react.cjs.js +79 -17
- package/dist/react.cjs.js.map +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.esm.mjs +79 -17
- package/dist/react.esm.mjs.map +1 -1
- package/dist/spin-wheel-sdk.cjs.js +79 -17
- package/dist/spin-wheel-sdk.cjs.js.map +1 -1
- package/dist/spin-wheel-sdk.d.ts +1 -1
- package/dist/spin-wheel-sdk.esm.mjs +79 -17
- package/dist/spin-wheel-sdk.esm.mjs.map +1 -1
- package/dist/spin-wheel-sdk.umd.js +77 -18
- package/dist/spin-wheel-sdk.umd.js.map +1 -1
- package/dist/spin-wheel-sdk.umd.min.js +1 -1
- package/dist/spin-wheel-sdk.umd.min.js.map +1 -1
- package/package.json +1 -1
package/dist/react.d.ts
CHANGED
package/dist/react.esm.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* SpinWheel SDK v0.1.0-alpha.
|
|
2
|
+
* SpinWheel SDK v0.1.0-alpha.2
|
|
3
3
|
* (c) 2026 – MIT License
|
|
4
4
|
* A dynamic, configurable Spin & Win wheel and Scratch Card SDK for Vanilla JS & React.
|
|
5
5
|
*/
|
|
@@ -28,6 +28,63 @@ import React from 'react';
|
|
|
28
28
|
*/
|
|
29
29
|
function buildCSS(config, hexToRGBA) {
|
|
30
30
|
const t = config.theme || {};
|
|
31
|
+
const isHexColor = value => typeof value === 'string' && /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(value.trim());
|
|
32
|
+
const parseRgbLike = value => {
|
|
33
|
+
if (typeof value !== 'string') return null;
|
|
34
|
+
const m = value.trim().match(/^rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})(?:\s*,\s*(\d*\.?\d+)\s*)?\)$/i);
|
|
35
|
+
if (!m) return null;
|
|
36
|
+
const r = Math.min(255, Math.max(0, Number(m[1])));
|
|
37
|
+
const g = Math.min(255, Math.max(0, Number(m[2])));
|
|
38
|
+
const b = Math.min(255, Math.max(0, Number(m[3])));
|
|
39
|
+
if ([r, g, b].some(n => Number.isNaN(n))) return null;
|
|
40
|
+
return {
|
|
41
|
+
r,
|
|
42
|
+
g,
|
|
43
|
+
b
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
const parseHex = value => {
|
|
47
|
+
if (!isHexColor(value)) return null;
|
|
48
|
+
const hex = value.trim().slice(1);
|
|
49
|
+
if (hex.length === 3) {
|
|
50
|
+
const r = parseInt(hex[0] + hex[0], 16);
|
|
51
|
+
const g = parseInt(hex[1] + hex[1], 16);
|
|
52
|
+
const b = parseInt(hex[2] + hex[2], 16);
|
|
53
|
+
return {
|
|
54
|
+
r,
|
|
55
|
+
g,
|
|
56
|
+
b
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
60
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
61
|
+
const b = parseInt(hex.slice(4, 6), 16);
|
|
62
|
+
return {
|
|
63
|
+
r,
|
|
64
|
+
g,
|
|
65
|
+
b
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
const toRGBA = (value, alpha) => {
|
|
69
|
+
const rgb = parseHex(value) || parseRgbLike(value);
|
|
70
|
+
if (!rgb) return `rgba(0,0,0,${alpha})`;
|
|
71
|
+
return `rgba(${rgb.r},${rgb.g},${rgb.b},${alpha})`;
|
|
72
|
+
};
|
|
73
|
+
const darkenColor = (value, amount = 0.22) => {
|
|
74
|
+
const rgb = parseHex(value) || parseRgbLike(value);
|
|
75
|
+
if (!rgb) return null;
|
|
76
|
+
const factor = 1 - Math.min(0.9, Math.max(0, amount));
|
|
77
|
+
const r = Math.round(rgb.r * factor);
|
|
78
|
+
const g = Math.round(rgb.g * factor);
|
|
79
|
+
const b = Math.round(rgb.b * factor);
|
|
80
|
+
return `rgb(${r},${g},${b})`;
|
|
81
|
+
};
|
|
82
|
+
const readableTextOn = bg => {
|
|
83
|
+
const rgb = parseHex(bg) || parseRgbLike(bg);
|
|
84
|
+
if (!rgb) return '#1a1a1f';
|
|
85
|
+
const luma = (0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b) / 255;
|
|
86
|
+
return luma < 0.55 ? '#ffffff' : '#1a1a1f';
|
|
87
|
+
};
|
|
31
88
|
|
|
32
89
|
// Extract theme colors with fallbacks
|
|
33
90
|
const gold = t.gold || '#e8c547';
|
|
@@ -37,11 +94,16 @@ function buildCSS(config, hexToRGBA) {
|
|
|
37
94
|
const textMuted = t.textMuted || '#9ca3af';
|
|
38
95
|
|
|
39
96
|
// Configurable colors
|
|
40
|
-
const
|
|
97
|
+
const hasCustomTitleColor = config.titleColor !== null && config.titleColor !== undefined;
|
|
98
|
+
const titleSpinColor = hasCustomTitleColor ? config.titleColor : goldLight;
|
|
99
|
+
const titleWinColor = hasCustomTitleColor ? config.titleColor : goldDark;
|
|
41
100
|
const subtitleColor = config.subtitleColor || textMuted;
|
|
42
101
|
const ringColor = config.ringColor || gold;
|
|
43
102
|
const pointerColor = config.pointerColor || gold;
|
|
44
|
-
const
|
|
103
|
+
const hasCustomButtonColor = config.buttonColor !== null && config.buttonColor !== undefined;
|
|
104
|
+
const buttonBaseColor = hasCustomButtonColor ? config.buttonColor : gold;
|
|
105
|
+
const buttonTextColor = hasCustomButtonColor ? readableTextOn(buttonBaseColor) : '#1a1a1f';
|
|
106
|
+
const buttonEdgeColor = hasCustomButtonColor ? darkenColor(buttonBaseColor) || 'rgba(0,0,0,0.25)' : goldDark;
|
|
45
107
|
const redeemBtnTop = config.winCardRedeemButtonColorTop || '#15803d';
|
|
46
108
|
const redeemBtnBottom = config.winCardRedeemButtonColorBottom || '#166534';
|
|
47
109
|
const redeemBtnText = config.winCardRedeemButtonTextColor || '#ffffff';
|
|
@@ -55,7 +117,7 @@ function buildCSS(config, hexToRGBA) {
|
|
|
55
117
|
// Computed values
|
|
56
118
|
hexToRGBA(gold, 0.4);
|
|
57
119
|
const ringGlow = hexToRGBA(ringColor, 0.4);
|
|
58
|
-
const buttonGlow =
|
|
120
|
+
const buttonGlow = toRGBA(buttonBaseColor, 0.4);
|
|
59
121
|
|
|
60
122
|
// Background styles
|
|
61
123
|
const bgStyle = config.backgroundColor ? `background-color:${config.backgroundColor};` : '';
|
|
@@ -66,9 +128,10 @@ function buildCSS(config, hexToRGBA) {
|
|
|
66
128
|
const ringAnimationCSS = ringAnimation ? `animation:sw-ring-pulse 3s ease-in-out infinite;` : '';
|
|
67
129
|
|
|
68
130
|
// Button shadow and animation
|
|
69
|
-
const buttonBoxShadow = buttonShadow ? `box-shadow:0 4px 0 ${
|
|
70
|
-
const buttonHoverStyle = buttonAnimation ? `.sw-spin-btn:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 6px 0 ${
|
|
71
|
-
const buttonActiveStyle = buttonAnimation ? `.sw-spin-btn:active:not(:disabled){transform:translateY(2px);box-shadow:0 2px 0 ${
|
|
131
|
+
const buttonBoxShadow = buttonShadow ? `box-shadow:0 4px 0 ${buttonEdgeColor}, 0 6px 20px ${buttonGlow}, inset 0 1px 0 rgba(255,255,255,.3);` : `box-shadow:inset 0 1px 0 rgba(255,255,255,.25);`;
|
|
132
|
+
const buttonHoverStyle = buttonAnimation ? buttonShadow ? `.sw-spin-btn:hover:not(:disabled){transform:translateY(-2px);box-shadow:0 6px 0 ${buttonEdgeColor},0 8px 28px ${buttonGlow},inset 0 1px 0 rgba(255,255,255,.3)}` : `.sw-spin-btn:hover:not(:disabled){transform:translateY(-2px);filter:brightness(1.05)}` : `.sw-spin-btn:hover:not(:disabled){filter:brightness(1.05)}`;
|
|
133
|
+
const buttonActiveStyle = buttonAnimation ? buttonShadow ? `.sw-spin-btn:active:not(:disabled){transform:translateY(2px);box-shadow:0 2px 0 ${buttonEdgeColor},0 4px 15px ${buttonGlow},inset 0 1px 0 rgba(255,255,255,.2)}` : `.sw-spin-btn:active:not(:disabled){transform:translateY(1px);filter:brightness(0.98)}` : `.sw-spin-btn:active:not(:disabled){transform:translateY(1px)}`;
|
|
134
|
+
const buttonBackground = hasCustomButtonColor ? `background:${buttonBaseColor};` : `background:linear-gradient(180deg,${goldLight},${goldDark});`;
|
|
72
135
|
return `
|
|
73
136
|
/* === SpinWheel SDK v2.1 === */
|
|
74
137
|
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700;800&family=Outfit:wght@300;500;600;700&display=swap');
|
|
@@ -89,10 +152,10 @@ function buildCSS(config, hexToRGBA) {
|
|
|
89
152
|
font-size:clamp(2rem,6vw,3.5rem); font-weight:800; letter-spacing:.02em;
|
|
90
153
|
}
|
|
91
154
|
.sw-title .sw-spin-text {
|
|
92
|
-
color:${
|
|
93
|
-
text-shadow:0 0 30px ${
|
|
155
|
+
color:${titleSpinColor};
|
|
156
|
+
text-shadow:0 0 30px ${toRGBA(titleSpinColor, 0.4)}, 0 0 60px ${toRGBA(titleSpinColor, 0.2)};
|
|
94
157
|
}
|
|
95
|
-
.sw-title .sw-win-text { color:${
|
|
158
|
+
.sw-title .sw-win-text { color:${titleWinColor}; }
|
|
96
159
|
.sw-subtitle { margin-top:.5rem; color:${subtitleColor}; font-size:1rem; font-weight:300; }
|
|
97
160
|
|
|
98
161
|
/* ── wheel ── */
|
|
@@ -174,7 +237,7 @@ ${ringAnimation ? `
|
|
|
174
237
|
.sw-spin-btn {
|
|
175
238
|
font-family:'Outfit',sans-serif; font-size:1.25rem; font-weight:700;
|
|
176
239
|
letter-spacing:.15em; padding:1rem 3rem; border:none; border-radius:12px;
|
|
177
|
-
|
|
240
|
+
${buttonBackground} color:${buttonTextColor};
|
|
178
241
|
cursor:pointer;
|
|
179
242
|
${buttonBoxShadow}
|
|
180
243
|
transition:transform .15s ease, box-shadow .2s ease, filter .2s ease;
|
|
@@ -1426,7 +1489,7 @@ class SpinWheel {
|
|
|
1426
1489
|
static Instance = SpinWheelInstance;
|
|
1427
1490
|
|
|
1428
1491
|
/** Current SDK version – kept in sync with package.json via build banner */
|
|
1429
|
-
static VERSION = '0.1.0-alpha.
|
|
1492
|
+
static VERSION = '0.1.0-alpha.2';
|
|
1430
1493
|
|
|
1431
1494
|
/** Export defaults for reference */
|
|
1432
1495
|
static DEFAULTS = DEFAULTS$1;
|
|
@@ -1655,7 +1718,8 @@ function buildScratchCSS(config, hexToRGBA) {
|
|
|
1655
1718
|
|
|
1656
1719
|
// Background configs
|
|
1657
1720
|
const cardBg = config.cardBackground || `linear-gradient(180deg, #faf8fc 0%, #f0ebf5 100%)`;
|
|
1658
|
-
const
|
|
1721
|
+
const hasCustomScratchZoneBg = config.scratchZoneBackground !== null && config.scratchZoneBackground !== undefined;
|
|
1722
|
+
const scratchZoneBg = hasCustomScratchZoneBg ? config.scratchZoneBackground : `linear-gradient(145deg, ${purpleDark} 0%, ${purpleMid} 50%, #5a3a7a 100%)`;
|
|
1659
1723
|
const modalBtnBg = config.modalButtonColor || `linear-gradient(145deg, ${purpleMid} 0%, ${purpleDark} 100%)`;
|
|
1660
1724
|
|
|
1661
1725
|
// Computed values
|
|
@@ -1765,9 +1829,7 @@ function buildScratchCSS(config, hexToRGBA) {
|
|
|
1765
1829
|
align-items:center;
|
|
1766
1830
|
justify-content:center;
|
|
1767
1831
|
padding:20px;
|
|
1768
|
-
background:
|
|
1769
|
-
radial-gradient(circle at 30% 30%, rgba(255,255,255,0.08) 0%, transparent 45%),
|
|
1770
|
-
linear-gradient(145deg, ${purpleDark} 0%, ${purpleMid} 100%);
|
|
1832
|
+
background:${hasCustomScratchZoneBg ? scratchZoneBg : `radial-gradient(circle at 30% 30%, rgba(255,255,255,0.08) 0%, transparent 45%), linear-gradient(145deg, ${purpleDark} 0%, ${purpleMid} 100%)`};
|
|
1771
1833
|
}
|
|
1772
1834
|
|
|
1773
1835
|
.sc-prize-content::before {
|
|
@@ -3392,7 +3454,7 @@ const ScratchCard = {
|
|
|
3392
3454
|
/** The underlying class – useful for `instanceof` checks or subclassing. */
|
|
3393
3455
|
Instance: ScratchCardInstance,
|
|
3394
3456
|
/** Current SDK version */
|
|
3395
|
-
VERSION: '0.1.0-alpha.
|
|
3457
|
+
VERSION: '0.1.0-alpha.2',
|
|
3396
3458
|
/** Export defaults for reference */
|
|
3397
3459
|
DEFAULTS: DEFAULTS
|
|
3398
3460
|
};
|