Bless friday deals
if you want to build your spin wheel website or pickerwheel website get Hosting from here on discount Click Here and for website code is here just copy this code and apply in wordpress website in html to get your website ready. Thank you
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Picker Wheel — Spin Tool</title>
<!-- Tailwind Play CDN (utility classes) -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Heroicons (we'll inline a few svgs as needed) -->
<style>
/* small helpers for wheel rendering container */
.wheel-wrap { max-width: 500px; aspect-ratio: 1 / 1; margin: 0 auto; position: relative; }
.wheel-canvas { width: 100%; height: 100%; display:block; transform-origin: 50% 50%; transition: transform var(--spin-duration, 4s) cubic-bezier(.08,.64,.08,1); }
.pointer-triangle {
width: 0; height: 0;
border-left: 18px solid transparent;
border-right: 18px solid transparent;
border-bottom: 26px solid #111827;
position: absolute; top: -12px; left: 50%; transform: translateX(-50%); z-index: 30;
filter: drop-shadow(0 2px 4px rgba(0,0,0,0.2));
}
/* small ring shadow */
.wheel-border { position:absolute; inset:0; border-radius:9999px; pointer-events:none; box-shadow: 0 8px 24px rgba(0,0,0,0.08), inset 0 0 0 8px rgba(17,24,39,0.06); }
.grab { cursor: grab; }
.grabbing { cursor: grabbing; }
</style>
</head>
<body class="bg-slate-50 text-slate-900">
<!-- Header -->
<header class="h-16 bg-white border-b sticky top-0 z-40">
<div class="max-w-7xl mx-auto h-full px-4 md:px-6 lg:px-8 flex items-center justify-between">
<div class="flex items-center gap-4">
<div class="text-2xl font-bold tracking-wide">🔮 PickerSpin</div>
<div class="hidden md:flex items-center gap-2 text-sm text-slate-600">
<button class="px-3 py-2 rounded-lg hover:bg-slate-100">Switch Wheel</button>
<button class="px-3 py-2 rounded-lg hover:bg-slate-100">File</button>
<button class="px-3 py-2 rounded-lg hover:bg-slate-100">Settings</button>
<button class="px-3 py-2 rounded-lg hover:bg-slate-100">Share</button>
</div>
</div>
<div class="flex items-center gap-3">
<button id="importBtn" class="p-2 rounded-lg hover:bg-slate-100" title="Import">📁</button>
<button id="saveBtn" class="p-2 rounded-lg hover:bg-slate-100" title="Save">💾</button>
<div class="w-10 h-10 rounded-full bg-gradient-to-br from-indigo-500 to-pink-500 text-white flex items-center justify-center">B</div>
</div>
</div>
</header>
<!-- Main -->
<main class="max-w-7xl mx-auto px-4 md:px-6 lg:px-8 py-6">
<div class="grid gap-6 lg:grid-cols-[380px_1fr]">
<!-- Left Panel - Inputs -->
<aside id="inputsPanel" class="bg-white border rounded-xl p-6 sticky top-[88px] h-[calc(100vh-112px)] overflow-hidden">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold">INPUTS</h2>
<div class="flex gap-2">
<button id="hidePanelBtn" class="w-10 h-10 rounded-lg flex items-center justify-center hover:bg-slate-100" title="Hide panel">👁️</button>
<button id="shuffleBtn" class="w-10 h-10 rounded-lg flex items-center justify-center hover:bg-slate-100" title="Shuffle">🔀</button>
<button id="importList" class="w-10 h-10 rounded-lg flex items-center justify-center hover:bg-slate-100" title="Import">📂</button>
<div class="relative">
<button id="moreBtn" class="w-10 h-10 rounded-lg flex items-center justify-center hover:bg-slate-100" title="More">⋯</button>
</div>
</div>
</div>
<!-- Add Entry (sticky top of list area) -->
<div class="mt-4">
<label class="text-sm font-medium">Add Entry</label>
<div class="mt-2 flex gap-2">
<input id="newEntryInput" class="h-10 px-3 border rounded-md flex-1 focus:ring-2 focus:ring-indigo-300" placeholder="Type and press Enter" aria-label="Add entry" />
<button id="addEntryBtn" class="px-4 py-2 rounded-lg bg-indigo-600 text-white text-sm font-medium hover:brightness-105">+</button>
</div>
<p class="text-sm text-slate-500 mt-2">Enter text items. Max 20 visible segments recommended.</p>
</div>
<!-- Entry List -->
<div id="entriesContainer" class="mt-4 border rounded-xl p-3 bg-slate-50 overflow-auto max-h-[60vh] space-y-3">
<!-- JS will populate entries here -->
</div>
<!-- Footer: small controls -->
<div class="mt-4 border-t pt-4 flex items-center justify-between">
<div class="text-sm text-slate-600">Entries: <span id="entriesCount">0</span></div>
<div class="flex gap-2">
<button id="clearBtn" class="px-3 py-1 rounded-lg text-sm hover:bg-slate-100">Clear</button>
<button id="resetBtn" class="px-3 py-1 rounded-lg text-sm hover:bg-slate-100">Reset</button>
</div>
</div>
</aside>
<!-- Right Panel - Wheel & Controls -->
<section class="bg-white border rounded-xl p-6 flex flex-col items-center">
<div class="w-full max-w-2xl">
<div class="flex items-center justify-between">
<h1 class="text-2xl md:text-3xl font-bold">Spin Wheel</h1>
<div class="text-sm text-slate-500">Material 3 inspired • Accessible</div>
</div>
<!-- Wheel area -->
<div class="mt-6 flex flex-col items-center">
<div class="wheel-wrap relative">
<div class="pointer-triangle" aria-hidden="true"></div>
<canvas id="wheelCanvas" class="wheel-canvas rounded-full" width="800" height="800" role="img" aria-label="Spin wheel"></canvas>
<div class="wheel-border rounded-full" aria-hidden="true"></div>
</div>
<!-- Spin button -->
<div class="mt-6">
<button id="spinBtn" class="px-8 py-4 rounded-full text-lg font-semibold shadow-2xl bg-gradient-to-r from-indigo-600 to-pink-500 text-white transform-gpu active:scale-95 focus:outline-none focus:ring-4 focus:ring-indigo-200">
Spin
</button>
</div>
<!-- Result Card -->
<div id="resultCard" class="mt-6 hidden rounded-lg p-6 border bg-white w-full max-w-md shadow">
<div class="text-sm text-slate-500">Result</div>
<div id="resultText" class="text-xl font-semibold mt-2">—</div>
<div id="resultControls" class="mt-4 flex gap-2">
<button id="repeatBtn" class="px-3 py-2 rounded-lg bg-slate-100 text-sm">Spin Again</button>
<button id="removeResultBtn" class="px-3 py-2 rounded-lg bg-slate-100 text-sm">Remove Winner</button>
</div>
</div>
</div>
<!-- Settings / Accordion -->
<div class="mt-8 w-full max-w-2xl">
<div class="border rounded-xl">
<button id="settingsToggle" class="w-full flex items-center justify-between p-4 text-left">
<span class="font-medium">Settings</span>
<svg id="chev" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-slate-500" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06-.02L10 10.88l3.71-3.69a.75.75 0 011.06 1.06l-4.24 4.22a.75.75 0 01-1.06 0L5.25 8.25a.75.75 0 01-.02-1.06z" clip-rule="evenodd" /></svg>
</button>
<div id="settingsPanel" class="px-4 pb-4 hidden">
<div class="py-4 border-b">
<label class="flex items-center justify-between">
<div>
<div class="text-sm font-medium">Spin Duration (seconds)</div>
<div class="text-sm text-slate-500">Longer spins feel dramatic</div>
</div>
<div class="w-40">
<input id="durationRange" type="range" min="3" max="7" value="4" class="w-full" />
<div class="text-xs text-right" id="durationValue">4s</div>
</div>
</label>
</div>
<div class="py-4 border-b">
<label class="flex items-center justify-between">
<div>
<div class="text-sm font-medium">Confetti on Win</div>
<div class="text-sm text-slate-500">Toggle celebratory confetti</div>
</div>
<div>
<input id="confettiToggle" type="checkbox" class="h-5 w-9" checked />
</div>
</label>
</div>
<div class="py-4">
<div class="text-sm font-medium mb-2">Color swatches</div>
<div id="swatches" class="grid grid-cols-6 gap-2">
<!-- preset swatches -->
</div>
</div>
</div>
</div>
</div>
<!-- Hidden live region for screen readers -->
<div class="sr-only" aria-live="polite" id="srLive"></div>
</div>
</section>
</div>
</main>
<!-- Confetti canvas overlay -->
<canvas id="confettiCanvas" class="pointer-events-none fixed inset-0 z-50"></canvas>
<script>
/* -----------------------------
Core app JS
------------------------------*/
(() => {
// Helpers
const $ = (sel, ctx=document) => ctx.querySelector(sel);
const $$ = (sel, ctx=document) => Array.from(ctx.querySelectorAll(sel));
// DOM refs
const entriesContainer = $('#entriesContainer');
const newEntryInput = $('#newEntryInput');
const addEntryBtn = $('#addEntryBtn');
const entriesCount = $('#entriesCount');
const wheelCanvas = $('#wheelCanvas');
const spinBtn = $('#spinBtn');
const resultCard = $('#resultCard');
const resultText = $('#resultText');
const repeatBtn = $('#repeatBtn');
const removeResultBtn = $('#removeResultBtn');
const durationRange = $('#durationRange');
const durationValue = $('#durationValue');
const confettiToggle = $('#confettiToggle');
const settingsToggle = $('#settingsToggle');
const settingsPanel = $('#settingsPanel');
const swatchesGrid = $('#swatches');
const srLive = $('#srLive');
const confettiCanvas = $('#confettiCanvas');
// State
let entries = []; // {id,text,hidden}
let colors = [
'#f97316','#f43f5e','#ef4444','#fb7185',
'#f59e0b','#84cc16','#10b981','#06b6d4',
'#3b82f6','#7c3aed','#a78bfa','#f43f5e'
];
let isSpinning = false;
let spinStartTime = 0;
let spinDuration = parseInt(durationRange.value) * 1000;
let lastSpinAngle = 0;
/* ---------- load/save ---------- */
const STORAGE_KEY = 'pickerspin:v1';
function loadState() {
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (raw) {
const parsed = JSON.parse(raw);
entries = parsed.entries || defaultEntries();
if (parsed.colors) colors = parsed.colors;
} else {
entries = defaultEntries();
}
} catch(e) {
entries = defaultEntries();
}
}
function saveState() {
const payload = { entries, colors };
localStorage.setItem(STORAGE_KEY, JSON.stringify(payload));
}
function defaultEntries() {
return [
{id:uid(), text:'Yes', hidden:false},
{id:uid(), text:'No', hidden:false},
{id:uid(), text:'Maybe', hidden:false},
{id:uid(), text:'Try Again', hidden:false}
];
}
/* ---------- utilities ---------- */
function uid() { return Math.random().toString(36).slice(2,9); }
function clamp(v,a,b){ return Math.max(a, Math.min(b, v)); }
/* ---------- render swatches ---------- */
function renderSwatches() {
swatchesGrid.innerHTML = '';
colors.slice(0,12).forEach((c,i) => {
const btn = document.createElement('button');
btn.className = 'w-12 h-12 rounded-full border';
btn.style.background = c;
btn.title = c;
btn.addEventListener('click', () => {
// rotate color array to start at this
colors.unshift(colors.splice(i,1)[0]);
drawWheel();
saveState();
});
swatchesGrid.appendChild(btn);
});
}
/* ---------- entries list (drag/drop) ---------- */
function renderEntries() {
entriesContainer.innerHTML = '';
entries.forEach((e, idx) => {
const item = document.createElement('div');
item.className = 'bg-white border rounded-lg p-3 flex items-center gap-3 grab';
item.setAttribute('draggable', 'true');
item.dataset.id = e.id;
// drag handle
const handle = document.createElement('div');
handle.className = 'w-8 h-8 flex items-center justify-center text-slate-500';
handle.innerHTML = '↕';
handle.style.cursor = 'grab';
item.appendChild(handle);
// content
const content = document.createElement('div');
content.className = 'flex-1';
const label = document.createElement('div');
label.className = 'font-medium text-sm';
label.textContent = e.text;
content.appendChild(label);
// actions
const actions = document.createElement('div');
actions.className = 'flex items-center gap-2';
const dup = iconButton('⎘','Duplicate');
dup.addEventListener('click', () => {
entries.splice(idx+1, 0, {id:uid(), text: e.text + ' (copy)', hidden: e.hidden});
saveState(); renderEntries(); drawWheel();
});
const hideBtn = iconButton(e.hidden ? '👁️🗨️' : '👁️','Hide/Show');
hideBtn.addEventListener('click', () => {
e.hidden = !e.hidden;
saveState(); renderEntries(); drawWheel();
});
const del = iconButton('🗑️','Delete');
del.addEventListener('click', () => {
entries.splice(idx,1);
saveState(); renderEntries(); drawWheel();
});
actions.appendChild(dup); actions.appendChild(hideBtn); actions.appendChild(del);
item.appendChild(content);
item.appendChild(actions);
// drag events
item.addEventListener('dragstart', (ev) => {
ev.dataTransfer.setData('text/plain', e.id);
item.classList.add('grabbing','opacity-70');
});
item.addEventListener('dragend', () => {
item.classList.remove('grabbing','opacity-70');
});
item.addEventListener('dragover', (ev) => {
ev.preventDefault();
});
item.addEventListener('drop', (ev) => {
ev.preventDefault();
const draggedId = ev.dataTransfer.getData('text/plain');
if(!draggedId) return;
const fromIdx = entries.findIndex(x => x.id === draggedId);
const toIdx = entries.findIndex(x => x.id === e.id);
if (fromIdx >=0 && toIdx >=0 && fromIdx !== toIdx) {
const [m] = entries.splice(fromIdx,1);
entries.splice(toIdx, 0, m);
saveState(); renderEntries(); drawWheel();
}
});
entriesContainer.appendChild(item);
});
entriesCount.textContent = entries.filter(e=>!e.hidden).length;
}
function iconButton(icon, title) {
const b = document.createElement('button');
b.className = 'w-8 h-8 rounded-lg flex items-center justify-center hover:bg-slate-100 text-sm';
b.title = title;
b.innerHTML = icon;
return b;
}
/* ---------- wheel drawing (canvas) ---------- */
const ctx = wheelCanvas.getContext('2d');
const DPR = window.devicePixelRatio || 1;
function resizeCanvas() {
const rect = wheelCanvas.getBoundingClientRect();
wheelCanvas.width = Math.floor(rect.width * DPR);
wheelCanvas.height = Math.floor(rect.height * DPR);
wheelCanvas.style.setProperty('--spin-duration', spinDuration + 'ms');
ctx.setTransform(DPR,0,0,DPR,0,0);
drawWheel();
}
window.addEventListener('resize', () => {
resizeCanvas();
});
function drawWheel() {
const visible = entries.filter(e=>!e.hidden);
const n = visible.length || 1;
const w = wheelCanvas.clientWidth;
const h = wheelCanvas.clientHeight;
const cx = w/2;
const cy = h/2;
const radius = Math.min(cx, cy) - 6;
ctx.clearRect(0,0,w,h);
// background
ctx.beginPath();
ctx.arc(cx,cy,radius+2,0,Math.PI*2);
ctx.fillStyle = '#ffffff';
ctx.fill();
const sliceAngle = (Math.PI*2) / n;
for (let i=0;i<n;i++){
const item = visible[i];
const start = -Math.PI/2 + i*sliceAngle;
const end = start + sliceAngle;
// color
ctx.beginPath();
ctx.moveTo(cx,cy);
ctx.arc(cx,cy,radius,start,end);
ctx.closePath();
ctx.fillStyle = colors[i % colors.length];
ctx.fill();
// border
ctx.strokeStyle = 'rgba(255,255,255,0.9)';
ctx.lineWidth = 1.5;
ctx.stroke();
// label
const middle = start + sliceAngle/2;
ctx.save();
ctx.translate(cx + Math.cos(middle)*(radius*0.58), cy + Math.sin(middle)*(radius*0.58));
ctx.rotate(middle + Math.PI/2);
ctx.fillStyle = '#0f172a';
ctx.font = 'bold 16px Inter, sans-serif';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// wrap if long
const txt = item.text;
drawWrappedText(ctx, txt, 120);
ctx.restore();
}
// inner circle
ctx.beginPath();
ctx.arc(cx,cy,radius*0.18,0,Math.PI*2);
ctx.fillStyle = '#111827';
ctx.fill();
ctx.fillStyle = '#fff';
ctx.font = '600 16px Inter, sans-serif';
ctx.textAlign = 'center';
ctx.fillText('SPIN', cx, cy+6);
}
function drawWrappedText(ctx, text, maxWidth) {
const words = text.split(' ');
let line = '', y = 0, lineHeight = 18;
const lines = [];
for (let n=0;n<words.length;n++){
const testLine = line + words[n] + ' ';
const metrics = ctx.measureText(testLine);
if (metrics.width > maxWidth && n > 0) {
lines.push(line.trim());
line = words[n] + ' ';
} else { line = testLine; }
}
lines.push(line.trim());
// center lines vertically
const offset = -((lines.length-1) * lineHeight)/2;
for (let i=0;i<lines.length;i++){
ctx.fillText(lines[i], 0, offset + i*lineHeight);
}
}
/* ---------- spin logic ---------- */
function getVisibleEntries() {
return entries.filter(e=>!e.hidden);
}
function computeSelectedIndex(finalAngleDeg) {
// finalAngleDeg is wheel rotation mod 360 (0 at original), with 0 = top
// We rotated the wheel by angle; pointer at top corresponds to angle 0.
const visible = getVisibleEntries();
const n = visible.length || 1;
// convert to [0,360)
let a = finalAngleDeg % 360;
if (a < 0) a += 360;
// pointer at 0deg means sector that occupies -slice/2 .. +slice/2; easier to compute offset
const sliceDeg = 360 / n;
// index is floor((360 - a + sliceDeg/2) / sliceDeg) % n
const idx = Math.floor((360 - a + sliceDeg/2) / sliceDeg) % n;
return idx;
}
function spinWheel() {
if (isSpinning) return;
const visible = getVisibleEntries();
if (visible.length === 0) {
alert('No visible entries to spin.');
return;
}
isSpinning = true;
resultCard.classList.add('hidden');
// generate a random end rotation in degrees (several full rotations + random)
const baseRot = 3600; // 10 turns
const rand = Math.floor(Math.random() * 360);
const total = baseRot + rand;
lastSpinAngle = total;
// apply CSS transform
wheelCanvas.style.transition = `transform ${spinDuration}ms cubic-bezier(.08,.64,.08,1)`;
wheelCanvas.style.transform = `rotate(${total}deg)`;
spinStartTime = performance.now();
// after spinDuration + tiny buffer
setTimeout(() => {
// compute final angle relative to 0..360
const finalDeg = total % 360;
const selIdx = computeSelectedIndex(finalDeg);
const selected = visible[selIdx];
announceResult(selected.text);
showResult(selected, selIdx);
isSpinning = false;
}, spinDuration + 60);
}
function announceResult(text) {
srLive.textContent = 'Result: ' + text;
}
function showResult(selected, idx) {
resultText.textContent = selected.text;
resultCard.classList.remove('hidden');
if (confettiToggle.checked) {
runConfetti();
}
}
/* ---------- confetti (simple particle system) ---------- */
const confettiCtx = confettiCanvas.getContext('2d');
let confettiParticles = [];
function resizeConfettiCanvas() {
confettiCanvas.width = innerWidth * DPR;
confettiCanvas.height = innerHeight * DPR;
confettiCanvas.style.width = innerWidth + 'px';
confettiCanvas.style.height = innerHeight + 'px';
confettiCtx.setTransform(DPR,0,0,DPR,0,0);
}
window.addEventListener('resize', resizeConfettiCanvas);
function runConfetti() {
resizeConfettiCanvas();
confettiParticles = [];
const count = 120;
for (let i=0;i<count;i++){
confettiParticles.push({
x: Math.random()*innerWidth,
y: -20 - Math.random()*200,
vx: (Math.random()-0.5)*6,
vy: 2 + Math.random()*4,
size: 6 + Math.random()*8,
color: colors[Math.floor(Math.random()*colors.length)]
});
}
let t0 = performance.now();
function step(t) {
const dt = (t - t0)/1000;
t0 = t;
confettiCtx.clearRect(0,0,innerWidth,innerHeight);
confettiParticles.forEach(p => {
p.x += p.vx;
p.y += p.vy;
p.vy += 0.08;
confettiCtx.fillStyle = p.color;
confettiCtx.fillRect(p.x, p.y, p.size, p.size*0.6);
});
// stop when offscreen
confettiParticles = confettiParticles.filter(p => p.y < innerHeight + 40);
if (confettiParticles.length > 0) requestAnimationFrame(step);
else confettiCtx.clearRect(0,0,innerWidth,innerHeight);
}
requestAnimationFrame(step);
}
/* ---------- UI wiring ---------- */
addEntryBtn.addEventListener('click', () => {
const v = newEntryInput.value.trim();
if (!v) return;
entries.push({id:uid(), text:v, hidden:false});
newEntryInput.value = '';
saveState(); renderEntries(); drawWheel();
});
newEntryInput.addEventListener('keydown', (ev) => {
if (ev.key === 'Enter') { ev.preventDefault(); addEntryBtn.click(); }
});
$('#shuffleBtn').addEventListener('click', () => {
entries = entries.sort(()=>Math.random()-0.5);
saveState(); renderEntries(); drawWheel();
});
$('#clearBtn').addEventListener('click', () => {
if (!confirm('Clear all entries?')) return;
entries = [];
saveState(); renderEntries(); drawWheel();
});
$('#resetBtn').addEventListener('click', () => {
if (!confirm('Reset to defaults?')) return;
entries = defaultEntries();
saveState(); renderEntries(); drawWheel();
});
$('#hidePanelBtn').addEventListener('click', () => {
const panel = $('#inputsPanel');
panel.classList.toggle('hidden');
});
$('#importList').addEventListener('click', () => {
const csv = prompt('Paste newline-separated list of entries:');
if (!csv) return;
const lines = csv.split(/[\r\n]+/).map(s=>s.trim()).filter(Boolean).slice(0,50);
lines.forEach(l => entries.push({id:uid(), text:l, hidden:false}));
saveState(); renderEntries(); drawWheel();
});
$('#saveBtn').addEventListener('click', () => {
saveState();
alert('Saved!');
});
// spin button
spinBtn.addEventListener('click', () => {
spinWheel();
});
repeatBtn.addEventListener('click', () => {
spinWheel();
});
removeResultBtn.addEventListener('click', () => {
const text = resultText.textContent;
const idx = entries.findIndex(e => e.text === text && !e.hidden);
if (idx >= 0) {
entries.splice(idx,1);
saveState(); renderEntries(); drawWheel();
resultCard.classList.add('hidden');
}
});
durationRange.addEventListener('input', (ev) => {
const s = ev.target.value;
durationValue.textContent = s + 's';
spinDuration = parseInt(s) * 1000;
wheelCanvas.style.setProperty('--spin-duration', spinDuration + 'ms');
});
settingsToggle.addEventListener('click', () => {
settingsPanel.classList.toggle('hidden');
$('#chev').classList.toggle('rotate-180');
});
// file import / export (basic)
$('#importBtn').addEventListener('click', () => {
const txt = prompt('Paste list (one per line):');
if (!txt) return;
entries = txt.split(/[\r\n]+/).map(s=> ({id:uid(), text:s.trim(), hidden:false})).filter(e=>e.text);
saveState(); renderEntries(); drawWheel();
});
// initial load
loadState();
renderSwatches();
renderEntries();
resizeCanvas();
resizeConfettiCanvas();
// initial draw
drawWheel();
// restore last rotation transform if desired
wheelCanvas.style.transform = `rotate(${lastSpinAngle}deg)`;
// accessibility: keyboard control
window.addEventListener('keydown', (ev) => {
if (ev.key === ' ' || ev.key === 'Enter') {
const active = document.activeElement;
// guard against pressing while typing in input
if (active === newEntryInput) return;
ev.preventDefault();
spinWheel();
}
});
// expose for debug
window.__pickerspin = {
getState: () => ({entries, colors}),
spin: spinWheel,
};
})();
</script>
</body>
</html>
🔮 PickerSpin
📁
💾
Copy Code
👁️
🔀


Comments
Post a Comment