@papernote/ui 1.10.11 → 1.10.12
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/components/Celebration.d.ts +47 -0
- package/dist/components/Celebration.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/index.d.ts +48 -2
- package/dist/index.esm.js +1087 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1088 -0
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/src/components/Celebration.stories.tsx +175 -0
- package/src/components/Celebration.tsx +256 -0
- package/src/components/index.ts +2 -0
package/dist/index.esm.js
CHANGED
|
@@ -2920,6 +2920,1092 @@ function Separator({ orientation = 'horizontal', className = '', spacing = 'md',
|
|
|
2920
2920
|
`, role: "separator", "aria-orientation": orientation }));
|
|
2921
2921
|
}
|
|
2922
2922
|
|
|
2923
|
+
// canvas-confetti v1.9.4 built on 2025-10-25T05:14:56.640Z
|
|
2924
|
+
var module$1 = {};
|
|
2925
|
+
|
|
2926
|
+
// source content
|
|
2927
|
+
/* globals Map */
|
|
2928
|
+
|
|
2929
|
+
(function main(global, module, isWorker, workerSize) {
|
|
2930
|
+
var canUseWorker = !!(
|
|
2931
|
+
global.Worker &&
|
|
2932
|
+
global.Blob &&
|
|
2933
|
+
global.Promise &&
|
|
2934
|
+
global.OffscreenCanvas &&
|
|
2935
|
+
global.OffscreenCanvasRenderingContext2D &&
|
|
2936
|
+
global.HTMLCanvasElement &&
|
|
2937
|
+
global.HTMLCanvasElement.prototype.transferControlToOffscreen &&
|
|
2938
|
+
global.URL &&
|
|
2939
|
+
global.URL.createObjectURL);
|
|
2940
|
+
|
|
2941
|
+
var canUsePaths = typeof Path2D === 'function' && typeof DOMMatrix === 'function';
|
|
2942
|
+
var canDrawBitmap = (function () {
|
|
2943
|
+
// this mostly supports ssr
|
|
2944
|
+
if (!global.OffscreenCanvas) {
|
|
2945
|
+
return false;
|
|
2946
|
+
}
|
|
2947
|
+
|
|
2948
|
+
try {
|
|
2949
|
+
var canvas = new OffscreenCanvas(1, 1);
|
|
2950
|
+
var ctx = canvas.getContext('2d');
|
|
2951
|
+
ctx.fillRect(0, 0, 1, 1);
|
|
2952
|
+
var bitmap = canvas.transferToImageBitmap();
|
|
2953
|
+
ctx.createPattern(bitmap, 'no-repeat');
|
|
2954
|
+
} catch (e) {
|
|
2955
|
+
return false;
|
|
2956
|
+
}
|
|
2957
|
+
|
|
2958
|
+
return true;
|
|
2959
|
+
})();
|
|
2960
|
+
|
|
2961
|
+
function noop() {}
|
|
2962
|
+
|
|
2963
|
+
// create a promise if it exists, otherwise, just
|
|
2964
|
+
// call the function directly
|
|
2965
|
+
function promise(func) {
|
|
2966
|
+
var ModulePromise = module.exports.Promise;
|
|
2967
|
+
var Prom = ModulePromise !== void 0 ? ModulePromise : global.Promise;
|
|
2968
|
+
|
|
2969
|
+
if (typeof Prom === 'function') {
|
|
2970
|
+
return new Prom(func);
|
|
2971
|
+
}
|
|
2972
|
+
|
|
2973
|
+
func(noop, noop);
|
|
2974
|
+
|
|
2975
|
+
return null;
|
|
2976
|
+
}
|
|
2977
|
+
|
|
2978
|
+
var bitmapMapper = (function (skipTransform, map) {
|
|
2979
|
+
// see https://github.com/catdad/canvas-confetti/issues/209
|
|
2980
|
+
// creating canvases is actually pretty expensive, so we should create a
|
|
2981
|
+
// 1:1 map for bitmap:canvas, so that we can animate the confetti in
|
|
2982
|
+
// a performant manner, but also not store them forever so that we don't
|
|
2983
|
+
// have a memory leak
|
|
2984
|
+
return {
|
|
2985
|
+
transform: function(bitmap) {
|
|
2986
|
+
if (skipTransform) {
|
|
2987
|
+
return bitmap;
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2990
|
+
if (map.has(bitmap)) {
|
|
2991
|
+
return map.get(bitmap);
|
|
2992
|
+
}
|
|
2993
|
+
|
|
2994
|
+
var canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
|
|
2995
|
+
var ctx = canvas.getContext('2d');
|
|
2996
|
+
ctx.drawImage(bitmap, 0, 0);
|
|
2997
|
+
|
|
2998
|
+
map.set(bitmap, canvas);
|
|
2999
|
+
|
|
3000
|
+
return canvas;
|
|
3001
|
+
},
|
|
3002
|
+
clear: function () {
|
|
3003
|
+
map.clear();
|
|
3004
|
+
}
|
|
3005
|
+
};
|
|
3006
|
+
})(canDrawBitmap, new Map());
|
|
3007
|
+
|
|
3008
|
+
var raf = (function () {
|
|
3009
|
+
var TIME = Math.floor(1000 / 60);
|
|
3010
|
+
var frame, cancel;
|
|
3011
|
+
var frames = {};
|
|
3012
|
+
var lastFrameTime = 0;
|
|
3013
|
+
|
|
3014
|
+
if (typeof requestAnimationFrame === 'function' && typeof cancelAnimationFrame === 'function') {
|
|
3015
|
+
frame = function (cb) {
|
|
3016
|
+
var id = Math.random();
|
|
3017
|
+
|
|
3018
|
+
frames[id] = requestAnimationFrame(function onFrame(time) {
|
|
3019
|
+
if (lastFrameTime === time || lastFrameTime + TIME - 1 < time) {
|
|
3020
|
+
lastFrameTime = time;
|
|
3021
|
+
delete frames[id];
|
|
3022
|
+
|
|
3023
|
+
cb();
|
|
3024
|
+
} else {
|
|
3025
|
+
frames[id] = requestAnimationFrame(onFrame);
|
|
3026
|
+
}
|
|
3027
|
+
});
|
|
3028
|
+
|
|
3029
|
+
return id;
|
|
3030
|
+
};
|
|
3031
|
+
cancel = function (id) {
|
|
3032
|
+
if (frames[id]) {
|
|
3033
|
+
cancelAnimationFrame(frames[id]);
|
|
3034
|
+
}
|
|
3035
|
+
};
|
|
3036
|
+
} else {
|
|
3037
|
+
frame = function (cb) {
|
|
3038
|
+
return setTimeout(cb, TIME);
|
|
3039
|
+
};
|
|
3040
|
+
cancel = function (timer) {
|
|
3041
|
+
return clearTimeout(timer);
|
|
3042
|
+
};
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
return { frame: frame, cancel: cancel };
|
|
3046
|
+
}());
|
|
3047
|
+
|
|
3048
|
+
var getWorker = (function () {
|
|
3049
|
+
var worker;
|
|
3050
|
+
var prom;
|
|
3051
|
+
var resolves = {};
|
|
3052
|
+
|
|
3053
|
+
function decorate(worker) {
|
|
3054
|
+
function execute(options, callback) {
|
|
3055
|
+
worker.postMessage({ options: options || {}, callback: callback });
|
|
3056
|
+
}
|
|
3057
|
+
worker.init = function initWorker(canvas) {
|
|
3058
|
+
var offscreen = canvas.transferControlToOffscreen();
|
|
3059
|
+
worker.postMessage({ canvas: offscreen }, [offscreen]);
|
|
3060
|
+
};
|
|
3061
|
+
|
|
3062
|
+
worker.fire = function fireWorker(options, size, done) {
|
|
3063
|
+
if (prom) {
|
|
3064
|
+
execute(options, null);
|
|
3065
|
+
return prom;
|
|
3066
|
+
}
|
|
3067
|
+
|
|
3068
|
+
var id = Math.random().toString(36).slice(2);
|
|
3069
|
+
|
|
3070
|
+
prom = promise(function (resolve) {
|
|
3071
|
+
function workerDone(msg) {
|
|
3072
|
+
if (msg.data.callback !== id) {
|
|
3073
|
+
return;
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
delete resolves[id];
|
|
3077
|
+
worker.removeEventListener('message', workerDone);
|
|
3078
|
+
|
|
3079
|
+
prom = null;
|
|
3080
|
+
|
|
3081
|
+
bitmapMapper.clear();
|
|
3082
|
+
|
|
3083
|
+
done();
|
|
3084
|
+
resolve();
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
worker.addEventListener('message', workerDone);
|
|
3088
|
+
execute(options, id);
|
|
3089
|
+
|
|
3090
|
+
resolves[id] = workerDone.bind(null, { data: { callback: id }});
|
|
3091
|
+
});
|
|
3092
|
+
|
|
3093
|
+
return prom;
|
|
3094
|
+
};
|
|
3095
|
+
|
|
3096
|
+
worker.reset = function resetWorker() {
|
|
3097
|
+
worker.postMessage({ reset: true });
|
|
3098
|
+
|
|
3099
|
+
for (var id in resolves) {
|
|
3100
|
+
resolves[id]();
|
|
3101
|
+
delete resolves[id];
|
|
3102
|
+
}
|
|
3103
|
+
};
|
|
3104
|
+
}
|
|
3105
|
+
|
|
3106
|
+
return function () {
|
|
3107
|
+
if (worker) {
|
|
3108
|
+
return worker;
|
|
3109
|
+
}
|
|
3110
|
+
|
|
3111
|
+
if (!isWorker && canUseWorker) {
|
|
3112
|
+
var code = [
|
|
3113
|
+
'var CONFETTI, SIZE = {}, module = {};',
|
|
3114
|
+
'(' + main.toString() + ')(this, module, true, SIZE);',
|
|
3115
|
+
'onmessage = function(msg) {',
|
|
3116
|
+
' if (msg.data.options) {',
|
|
3117
|
+
' CONFETTI(msg.data.options).then(function () {',
|
|
3118
|
+
' if (msg.data.callback) {',
|
|
3119
|
+
' postMessage({ callback: msg.data.callback });',
|
|
3120
|
+
' }',
|
|
3121
|
+
' });',
|
|
3122
|
+
' } else if (msg.data.reset) {',
|
|
3123
|
+
' CONFETTI && CONFETTI.reset();',
|
|
3124
|
+
' } else if (msg.data.resize) {',
|
|
3125
|
+
' SIZE.width = msg.data.resize.width;',
|
|
3126
|
+
' SIZE.height = msg.data.resize.height;',
|
|
3127
|
+
' } else if (msg.data.canvas) {',
|
|
3128
|
+
' SIZE.width = msg.data.canvas.width;',
|
|
3129
|
+
' SIZE.height = msg.data.canvas.height;',
|
|
3130
|
+
' CONFETTI = module.exports.create(msg.data.canvas);',
|
|
3131
|
+
' }',
|
|
3132
|
+
'}',
|
|
3133
|
+
].join('\n');
|
|
3134
|
+
try {
|
|
3135
|
+
worker = new Worker(URL.createObjectURL(new Blob([code])));
|
|
3136
|
+
} catch (e) {
|
|
3137
|
+
// eslint-disable-next-line no-console
|
|
3138
|
+
typeof console !== 'undefined' && typeof console.warn === 'function' ? console.warn('🎊 Could not load worker', e) : null;
|
|
3139
|
+
|
|
3140
|
+
return null;
|
|
3141
|
+
}
|
|
3142
|
+
|
|
3143
|
+
decorate(worker);
|
|
3144
|
+
}
|
|
3145
|
+
|
|
3146
|
+
return worker;
|
|
3147
|
+
};
|
|
3148
|
+
})();
|
|
3149
|
+
|
|
3150
|
+
var defaults = {
|
|
3151
|
+
particleCount: 50,
|
|
3152
|
+
angle: 90,
|
|
3153
|
+
spread: 45,
|
|
3154
|
+
startVelocity: 45,
|
|
3155
|
+
decay: 0.9,
|
|
3156
|
+
gravity: 1,
|
|
3157
|
+
drift: 0,
|
|
3158
|
+
ticks: 200,
|
|
3159
|
+
x: 0.5,
|
|
3160
|
+
y: 0.5,
|
|
3161
|
+
shapes: ['square', 'circle'],
|
|
3162
|
+
zIndex: 100,
|
|
3163
|
+
colors: [
|
|
3164
|
+
'#26ccff',
|
|
3165
|
+
'#a25afd',
|
|
3166
|
+
'#ff5e7e',
|
|
3167
|
+
'#88ff5a',
|
|
3168
|
+
'#fcff42',
|
|
3169
|
+
'#ffa62d',
|
|
3170
|
+
'#ff36ff'
|
|
3171
|
+
],
|
|
3172
|
+
// probably should be true, but back-compat
|
|
3173
|
+
disableForReducedMotion: false,
|
|
3174
|
+
scalar: 1
|
|
3175
|
+
};
|
|
3176
|
+
|
|
3177
|
+
function convert(val, transform) {
|
|
3178
|
+
return transform ? transform(val) : val;
|
|
3179
|
+
}
|
|
3180
|
+
|
|
3181
|
+
function isOk(val) {
|
|
3182
|
+
return !(val === null || val === undefined);
|
|
3183
|
+
}
|
|
3184
|
+
|
|
3185
|
+
function prop(options, name, transform) {
|
|
3186
|
+
return convert(
|
|
3187
|
+
options && isOk(options[name]) ? options[name] : defaults[name],
|
|
3188
|
+
transform
|
|
3189
|
+
);
|
|
3190
|
+
}
|
|
3191
|
+
|
|
3192
|
+
function onlyPositiveInt(number){
|
|
3193
|
+
return number < 0 ? 0 : Math.floor(number);
|
|
3194
|
+
}
|
|
3195
|
+
|
|
3196
|
+
function randomInt(min, max) {
|
|
3197
|
+
// [min, max)
|
|
3198
|
+
return Math.floor(Math.random() * (max - min)) + min;
|
|
3199
|
+
}
|
|
3200
|
+
|
|
3201
|
+
function toDecimal(str) {
|
|
3202
|
+
return parseInt(str, 16);
|
|
3203
|
+
}
|
|
3204
|
+
|
|
3205
|
+
function colorsToRgb(colors) {
|
|
3206
|
+
return colors.map(hexToRgb);
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3209
|
+
function hexToRgb(str) {
|
|
3210
|
+
var val = String(str).replace(/[^0-9a-f]/gi, '');
|
|
3211
|
+
|
|
3212
|
+
if (val.length < 6) {
|
|
3213
|
+
val = val[0]+val[0]+val[1]+val[1]+val[2]+val[2];
|
|
3214
|
+
}
|
|
3215
|
+
|
|
3216
|
+
return {
|
|
3217
|
+
r: toDecimal(val.substring(0,2)),
|
|
3218
|
+
g: toDecimal(val.substring(2,4)),
|
|
3219
|
+
b: toDecimal(val.substring(4,6))
|
|
3220
|
+
};
|
|
3221
|
+
}
|
|
3222
|
+
|
|
3223
|
+
function getOrigin(options) {
|
|
3224
|
+
var origin = prop(options, 'origin', Object);
|
|
3225
|
+
origin.x = prop(origin, 'x', Number);
|
|
3226
|
+
origin.y = prop(origin, 'y', Number);
|
|
3227
|
+
|
|
3228
|
+
return origin;
|
|
3229
|
+
}
|
|
3230
|
+
|
|
3231
|
+
function setCanvasWindowSize(canvas) {
|
|
3232
|
+
canvas.width = document.documentElement.clientWidth;
|
|
3233
|
+
canvas.height = document.documentElement.clientHeight;
|
|
3234
|
+
}
|
|
3235
|
+
|
|
3236
|
+
function setCanvasRectSize(canvas) {
|
|
3237
|
+
var rect = canvas.getBoundingClientRect();
|
|
3238
|
+
canvas.width = rect.width;
|
|
3239
|
+
canvas.height = rect.height;
|
|
3240
|
+
}
|
|
3241
|
+
|
|
3242
|
+
function getCanvas(zIndex) {
|
|
3243
|
+
var canvas = document.createElement('canvas');
|
|
3244
|
+
|
|
3245
|
+
canvas.style.position = 'fixed';
|
|
3246
|
+
canvas.style.top = '0px';
|
|
3247
|
+
canvas.style.left = '0px';
|
|
3248
|
+
canvas.style.pointerEvents = 'none';
|
|
3249
|
+
canvas.style.zIndex = zIndex;
|
|
3250
|
+
|
|
3251
|
+
return canvas;
|
|
3252
|
+
}
|
|
3253
|
+
|
|
3254
|
+
function ellipse(context, x, y, radiusX, radiusY, rotation, startAngle, endAngle, antiClockwise) {
|
|
3255
|
+
context.save();
|
|
3256
|
+
context.translate(x, y);
|
|
3257
|
+
context.rotate(rotation);
|
|
3258
|
+
context.scale(radiusX, radiusY);
|
|
3259
|
+
context.arc(0, 0, 1, startAngle, endAngle, antiClockwise);
|
|
3260
|
+
context.restore();
|
|
3261
|
+
}
|
|
3262
|
+
|
|
3263
|
+
function randomPhysics(opts) {
|
|
3264
|
+
var radAngle = opts.angle * (Math.PI / 180);
|
|
3265
|
+
var radSpread = opts.spread * (Math.PI / 180);
|
|
3266
|
+
|
|
3267
|
+
return {
|
|
3268
|
+
x: opts.x,
|
|
3269
|
+
y: opts.y,
|
|
3270
|
+
wobble: Math.random() * 10,
|
|
3271
|
+
wobbleSpeed: Math.min(0.11, Math.random() * 0.1 + 0.05),
|
|
3272
|
+
velocity: (opts.startVelocity * 0.5) + (Math.random() * opts.startVelocity),
|
|
3273
|
+
angle2D: -radAngle + ((0.5 * radSpread) - (Math.random() * radSpread)),
|
|
3274
|
+
tiltAngle: (Math.random() * (0.75 - 0.25) + 0.25) * Math.PI,
|
|
3275
|
+
color: opts.color,
|
|
3276
|
+
shape: opts.shape,
|
|
3277
|
+
tick: 0,
|
|
3278
|
+
totalTicks: opts.ticks,
|
|
3279
|
+
decay: opts.decay,
|
|
3280
|
+
drift: opts.drift,
|
|
3281
|
+
random: Math.random() + 2,
|
|
3282
|
+
tiltSin: 0,
|
|
3283
|
+
tiltCos: 0,
|
|
3284
|
+
wobbleX: 0,
|
|
3285
|
+
wobbleY: 0,
|
|
3286
|
+
gravity: opts.gravity * 3,
|
|
3287
|
+
ovalScalar: 0.6,
|
|
3288
|
+
scalar: opts.scalar,
|
|
3289
|
+
flat: opts.flat
|
|
3290
|
+
};
|
|
3291
|
+
}
|
|
3292
|
+
|
|
3293
|
+
function updateFetti(context, fetti) {
|
|
3294
|
+
fetti.x += Math.cos(fetti.angle2D) * fetti.velocity + fetti.drift;
|
|
3295
|
+
fetti.y += Math.sin(fetti.angle2D) * fetti.velocity + fetti.gravity;
|
|
3296
|
+
fetti.velocity *= fetti.decay;
|
|
3297
|
+
|
|
3298
|
+
if (fetti.flat) {
|
|
3299
|
+
fetti.wobble = 0;
|
|
3300
|
+
fetti.wobbleX = fetti.x + (10 * fetti.scalar);
|
|
3301
|
+
fetti.wobbleY = fetti.y + (10 * fetti.scalar);
|
|
3302
|
+
|
|
3303
|
+
fetti.tiltSin = 0;
|
|
3304
|
+
fetti.tiltCos = 0;
|
|
3305
|
+
fetti.random = 1;
|
|
3306
|
+
} else {
|
|
3307
|
+
fetti.wobble += fetti.wobbleSpeed;
|
|
3308
|
+
fetti.wobbleX = fetti.x + ((10 * fetti.scalar) * Math.cos(fetti.wobble));
|
|
3309
|
+
fetti.wobbleY = fetti.y + ((10 * fetti.scalar) * Math.sin(fetti.wobble));
|
|
3310
|
+
|
|
3311
|
+
fetti.tiltAngle += 0.1;
|
|
3312
|
+
fetti.tiltSin = Math.sin(fetti.tiltAngle);
|
|
3313
|
+
fetti.tiltCos = Math.cos(fetti.tiltAngle);
|
|
3314
|
+
fetti.random = Math.random() + 2;
|
|
3315
|
+
}
|
|
3316
|
+
|
|
3317
|
+
var progress = (fetti.tick++) / fetti.totalTicks;
|
|
3318
|
+
|
|
3319
|
+
var x1 = fetti.x + (fetti.random * fetti.tiltCos);
|
|
3320
|
+
var y1 = fetti.y + (fetti.random * fetti.tiltSin);
|
|
3321
|
+
var x2 = fetti.wobbleX + (fetti.random * fetti.tiltCos);
|
|
3322
|
+
var y2 = fetti.wobbleY + (fetti.random * fetti.tiltSin);
|
|
3323
|
+
|
|
3324
|
+
context.fillStyle = 'rgba(' + fetti.color.r + ', ' + fetti.color.g + ', ' + fetti.color.b + ', ' + (1 - progress) + ')';
|
|
3325
|
+
|
|
3326
|
+
context.beginPath();
|
|
3327
|
+
|
|
3328
|
+
if (canUsePaths && fetti.shape.type === 'path' && typeof fetti.shape.path === 'string' && Array.isArray(fetti.shape.matrix)) {
|
|
3329
|
+
context.fill(transformPath2D(
|
|
3330
|
+
fetti.shape.path,
|
|
3331
|
+
fetti.shape.matrix,
|
|
3332
|
+
fetti.x,
|
|
3333
|
+
fetti.y,
|
|
3334
|
+
Math.abs(x2 - x1) * 0.1,
|
|
3335
|
+
Math.abs(y2 - y1) * 0.1,
|
|
3336
|
+
Math.PI / 10 * fetti.wobble
|
|
3337
|
+
));
|
|
3338
|
+
} else if (fetti.shape.type === 'bitmap') {
|
|
3339
|
+
var rotation = Math.PI / 10 * fetti.wobble;
|
|
3340
|
+
var scaleX = Math.abs(x2 - x1) * 0.1;
|
|
3341
|
+
var scaleY = Math.abs(y2 - y1) * 0.1;
|
|
3342
|
+
var width = fetti.shape.bitmap.width * fetti.scalar;
|
|
3343
|
+
var height = fetti.shape.bitmap.height * fetti.scalar;
|
|
3344
|
+
|
|
3345
|
+
var matrix = new DOMMatrix([
|
|
3346
|
+
Math.cos(rotation) * scaleX,
|
|
3347
|
+
Math.sin(rotation) * scaleX,
|
|
3348
|
+
-Math.sin(rotation) * scaleY,
|
|
3349
|
+
Math.cos(rotation) * scaleY,
|
|
3350
|
+
fetti.x,
|
|
3351
|
+
fetti.y
|
|
3352
|
+
]);
|
|
3353
|
+
|
|
3354
|
+
// apply the transform matrix from the confetti shape
|
|
3355
|
+
matrix.multiplySelf(new DOMMatrix(fetti.shape.matrix));
|
|
3356
|
+
|
|
3357
|
+
var pattern = context.createPattern(bitmapMapper.transform(fetti.shape.bitmap), 'no-repeat');
|
|
3358
|
+
pattern.setTransform(matrix);
|
|
3359
|
+
|
|
3360
|
+
context.globalAlpha = (1 - progress);
|
|
3361
|
+
context.fillStyle = pattern;
|
|
3362
|
+
context.fillRect(
|
|
3363
|
+
fetti.x - (width / 2),
|
|
3364
|
+
fetti.y - (height / 2),
|
|
3365
|
+
width,
|
|
3366
|
+
height
|
|
3367
|
+
);
|
|
3368
|
+
context.globalAlpha = 1;
|
|
3369
|
+
} else if (fetti.shape === 'circle') {
|
|
3370
|
+
context.ellipse ?
|
|
3371
|
+
context.ellipse(fetti.x, fetti.y, Math.abs(x2 - x1) * fetti.ovalScalar, Math.abs(y2 - y1) * fetti.ovalScalar, Math.PI / 10 * fetti.wobble, 0, 2 * Math.PI) :
|
|
3372
|
+
ellipse(context, fetti.x, fetti.y, Math.abs(x2 - x1) * fetti.ovalScalar, Math.abs(y2 - y1) * fetti.ovalScalar, Math.PI / 10 * fetti.wobble, 0, 2 * Math.PI);
|
|
3373
|
+
} else if (fetti.shape === 'star') {
|
|
3374
|
+
var rot = Math.PI / 2 * 3;
|
|
3375
|
+
var innerRadius = 4 * fetti.scalar;
|
|
3376
|
+
var outerRadius = 8 * fetti.scalar;
|
|
3377
|
+
var x = fetti.x;
|
|
3378
|
+
var y = fetti.y;
|
|
3379
|
+
var spikes = 5;
|
|
3380
|
+
var step = Math.PI / spikes;
|
|
3381
|
+
|
|
3382
|
+
while (spikes--) {
|
|
3383
|
+
x = fetti.x + Math.cos(rot) * outerRadius;
|
|
3384
|
+
y = fetti.y + Math.sin(rot) * outerRadius;
|
|
3385
|
+
context.lineTo(x, y);
|
|
3386
|
+
rot += step;
|
|
3387
|
+
|
|
3388
|
+
x = fetti.x + Math.cos(rot) * innerRadius;
|
|
3389
|
+
y = fetti.y + Math.sin(rot) * innerRadius;
|
|
3390
|
+
context.lineTo(x, y);
|
|
3391
|
+
rot += step;
|
|
3392
|
+
}
|
|
3393
|
+
} else {
|
|
3394
|
+
context.moveTo(Math.floor(fetti.x), Math.floor(fetti.y));
|
|
3395
|
+
context.lineTo(Math.floor(fetti.wobbleX), Math.floor(y1));
|
|
3396
|
+
context.lineTo(Math.floor(x2), Math.floor(y2));
|
|
3397
|
+
context.lineTo(Math.floor(x1), Math.floor(fetti.wobbleY));
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
context.closePath();
|
|
3401
|
+
context.fill();
|
|
3402
|
+
|
|
3403
|
+
return fetti.tick < fetti.totalTicks;
|
|
3404
|
+
}
|
|
3405
|
+
|
|
3406
|
+
function animate(canvas, fettis, resizer, size, done) {
|
|
3407
|
+
var animatingFettis = fettis.slice();
|
|
3408
|
+
var context = canvas.getContext('2d');
|
|
3409
|
+
var animationFrame;
|
|
3410
|
+
var destroy;
|
|
3411
|
+
|
|
3412
|
+
var prom = promise(function (resolve) {
|
|
3413
|
+
function onDone() {
|
|
3414
|
+
animationFrame = destroy = null;
|
|
3415
|
+
|
|
3416
|
+
context.clearRect(0, 0, size.width, size.height);
|
|
3417
|
+
bitmapMapper.clear();
|
|
3418
|
+
|
|
3419
|
+
done();
|
|
3420
|
+
resolve();
|
|
3421
|
+
}
|
|
3422
|
+
|
|
3423
|
+
function update() {
|
|
3424
|
+
if (isWorker && !(size.width === workerSize.width && size.height === workerSize.height)) {
|
|
3425
|
+
size.width = canvas.width = workerSize.width;
|
|
3426
|
+
size.height = canvas.height = workerSize.height;
|
|
3427
|
+
}
|
|
3428
|
+
|
|
3429
|
+
if (!size.width && !size.height) {
|
|
3430
|
+
resizer(canvas);
|
|
3431
|
+
size.width = canvas.width;
|
|
3432
|
+
size.height = canvas.height;
|
|
3433
|
+
}
|
|
3434
|
+
|
|
3435
|
+
context.clearRect(0, 0, size.width, size.height);
|
|
3436
|
+
|
|
3437
|
+
animatingFettis = animatingFettis.filter(function (fetti) {
|
|
3438
|
+
return updateFetti(context, fetti);
|
|
3439
|
+
});
|
|
3440
|
+
|
|
3441
|
+
if (animatingFettis.length) {
|
|
3442
|
+
animationFrame = raf.frame(update);
|
|
3443
|
+
} else {
|
|
3444
|
+
onDone();
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
|
|
3448
|
+
animationFrame = raf.frame(update);
|
|
3449
|
+
destroy = onDone;
|
|
3450
|
+
});
|
|
3451
|
+
|
|
3452
|
+
return {
|
|
3453
|
+
addFettis: function (fettis) {
|
|
3454
|
+
animatingFettis = animatingFettis.concat(fettis);
|
|
3455
|
+
|
|
3456
|
+
return prom;
|
|
3457
|
+
},
|
|
3458
|
+
canvas: canvas,
|
|
3459
|
+
promise: prom,
|
|
3460
|
+
reset: function () {
|
|
3461
|
+
if (animationFrame) {
|
|
3462
|
+
raf.cancel(animationFrame);
|
|
3463
|
+
}
|
|
3464
|
+
|
|
3465
|
+
if (destroy) {
|
|
3466
|
+
destroy();
|
|
3467
|
+
}
|
|
3468
|
+
}
|
|
3469
|
+
};
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3472
|
+
function confettiCannon(canvas, globalOpts) {
|
|
3473
|
+
var isLibCanvas = !canvas;
|
|
3474
|
+
var allowResize = !!prop(globalOpts || {}, 'resize');
|
|
3475
|
+
var hasResizeEventRegistered = false;
|
|
3476
|
+
var globalDisableForReducedMotion = prop(globalOpts, 'disableForReducedMotion', Boolean);
|
|
3477
|
+
var shouldUseWorker = canUseWorker && !!prop(globalOpts || {}, 'useWorker');
|
|
3478
|
+
var worker = shouldUseWorker ? getWorker() : null;
|
|
3479
|
+
var resizer = isLibCanvas ? setCanvasWindowSize : setCanvasRectSize;
|
|
3480
|
+
var initialized = (canvas && worker) ? !!canvas.__confetti_initialized : false;
|
|
3481
|
+
var preferLessMotion = typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion)').matches;
|
|
3482
|
+
var animationObj;
|
|
3483
|
+
|
|
3484
|
+
function fireLocal(options, size, done) {
|
|
3485
|
+
var particleCount = prop(options, 'particleCount', onlyPositiveInt);
|
|
3486
|
+
var angle = prop(options, 'angle', Number);
|
|
3487
|
+
var spread = prop(options, 'spread', Number);
|
|
3488
|
+
var startVelocity = prop(options, 'startVelocity', Number);
|
|
3489
|
+
var decay = prop(options, 'decay', Number);
|
|
3490
|
+
var gravity = prop(options, 'gravity', Number);
|
|
3491
|
+
var drift = prop(options, 'drift', Number);
|
|
3492
|
+
var colors = prop(options, 'colors', colorsToRgb);
|
|
3493
|
+
var ticks = prop(options, 'ticks', Number);
|
|
3494
|
+
var shapes = prop(options, 'shapes');
|
|
3495
|
+
var scalar = prop(options, 'scalar');
|
|
3496
|
+
var flat = !!prop(options, 'flat');
|
|
3497
|
+
var origin = getOrigin(options);
|
|
3498
|
+
|
|
3499
|
+
var temp = particleCount;
|
|
3500
|
+
var fettis = [];
|
|
3501
|
+
|
|
3502
|
+
var startX = canvas.width * origin.x;
|
|
3503
|
+
var startY = canvas.height * origin.y;
|
|
3504
|
+
|
|
3505
|
+
while (temp--) {
|
|
3506
|
+
fettis.push(
|
|
3507
|
+
randomPhysics({
|
|
3508
|
+
x: startX,
|
|
3509
|
+
y: startY,
|
|
3510
|
+
angle: angle,
|
|
3511
|
+
spread: spread,
|
|
3512
|
+
startVelocity: startVelocity,
|
|
3513
|
+
color: colors[temp % colors.length],
|
|
3514
|
+
shape: shapes[randomInt(0, shapes.length)],
|
|
3515
|
+
ticks: ticks,
|
|
3516
|
+
decay: decay,
|
|
3517
|
+
gravity: gravity,
|
|
3518
|
+
drift: drift,
|
|
3519
|
+
scalar: scalar,
|
|
3520
|
+
flat: flat
|
|
3521
|
+
})
|
|
3522
|
+
);
|
|
3523
|
+
}
|
|
3524
|
+
|
|
3525
|
+
// if we have a previous canvas already animating,
|
|
3526
|
+
// add to it
|
|
3527
|
+
if (animationObj) {
|
|
3528
|
+
return animationObj.addFettis(fettis);
|
|
3529
|
+
}
|
|
3530
|
+
|
|
3531
|
+
animationObj = animate(canvas, fettis, resizer, size , done);
|
|
3532
|
+
|
|
3533
|
+
return animationObj.promise;
|
|
3534
|
+
}
|
|
3535
|
+
|
|
3536
|
+
function fire(options) {
|
|
3537
|
+
var disableForReducedMotion = globalDisableForReducedMotion || prop(options, 'disableForReducedMotion', Boolean);
|
|
3538
|
+
var zIndex = prop(options, 'zIndex', Number);
|
|
3539
|
+
|
|
3540
|
+
if (disableForReducedMotion && preferLessMotion) {
|
|
3541
|
+
return promise(function (resolve) {
|
|
3542
|
+
resolve();
|
|
3543
|
+
});
|
|
3544
|
+
}
|
|
3545
|
+
|
|
3546
|
+
if (isLibCanvas && animationObj) {
|
|
3547
|
+
// use existing canvas from in-progress animation
|
|
3548
|
+
canvas = animationObj.canvas;
|
|
3549
|
+
} else if (isLibCanvas && !canvas) {
|
|
3550
|
+
// create and initialize a new canvas
|
|
3551
|
+
canvas = getCanvas(zIndex);
|
|
3552
|
+
document.body.appendChild(canvas);
|
|
3553
|
+
}
|
|
3554
|
+
|
|
3555
|
+
if (allowResize && !initialized) {
|
|
3556
|
+
// initialize the size of a user-supplied canvas
|
|
3557
|
+
resizer(canvas);
|
|
3558
|
+
}
|
|
3559
|
+
|
|
3560
|
+
var size = {
|
|
3561
|
+
width: canvas.width,
|
|
3562
|
+
height: canvas.height
|
|
3563
|
+
};
|
|
3564
|
+
|
|
3565
|
+
if (worker && !initialized) {
|
|
3566
|
+
worker.init(canvas);
|
|
3567
|
+
}
|
|
3568
|
+
|
|
3569
|
+
initialized = true;
|
|
3570
|
+
|
|
3571
|
+
if (worker) {
|
|
3572
|
+
canvas.__confetti_initialized = true;
|
|
3573
|
+
}
|
|
3574
|
+
|
|
3575
|
+
function onResize() {
|
|
3576
|
+
if (worker) {
|
|
3577
|
+
// TODO this really shouldn't be immediate, because it is expensive
|
|
3578
|
+
var obj = {
|
|
3579
|
+
getBoundingClientRect: function () {
|
|
3580
|
+
if (!isLibCanvas) {
|
|
3581
|
+
return canvas.getBoundingClientRect();
|
|
3582
|
+
}
|
|
3583
|
+
}
|
|
3584
|
+
};
|
|
3585
|
+
|
|
3586
|
+
resizer(obj);
|
|
3587
|
+
|
|
3588
|
+
worker.postMessage({
|
|
3589
|
+
resize: {
|
|
3590
|
+
width: obj.width,
|
|
3591
|
+
height: obj.height
|
|
3592
|
+
}
|
|
3593
|
+
});
|
|
3594
|
+
return;
|
|
3595
|
+
}
|
|
3596
|
+
|
|
3597
|
+
// don't actually query the size here, since this
|
|
3598
|
+
// can execute frequently and rapidly
|
|
3599
|
+
size.width = size.height = null;
|
|
3600
|
+
}
|
|
3601
|
+
|
|
3602
|
+
function done() {
|
|
3603
|
+
animationObj = null;
|
|
3604
|
+
|
|
3605
|
+
if (allowResize) {
|
|
3606
|
+
hasResizeEventRegistered = false;
|
|
3607
|
+
global.removeEventListener('resize', onResize);
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3610
|
+
if (isLibCanvas && canvas) {
|
|
3611
|
+
if (document.body.contains(canvas)) {
|
|
3612
|
+
document.body.removeChild(canvas);
|
|
3613
|
+
}
|
|
3614
|
+
canvas = null;
|
|
3615
|
+
initialized = false;
|
|
3616
|
+
}
|
|
3617
|
+
}
|
|
3618
|
+
|
|
3619
|
+
if (allowResize && !hasResizeEventRegistered) {
|
|
3620
|
+
hasResizeEventRegistered = true;
|
|
3621
|
+
global.addEventListener('resize', onResize, false);
|
|
3622
|
+
}
|
|
3623
|
+
|
|
3624
|
+
if (worker) {
|
|
3625
|
+
return worker.fire(options, size, done);
|
|
3626
|
+
}
|
|
3627
|
+
|
|
3628
|
+
return fireLocal(options, size, done);
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
fire.reset = function () {
|
|
3632
|
+
if (worker) {
|
|
3633
|
+
worker.reset();
|
|
3634
|
+
}
|
|
3635
|
+
|
|
3636
|
+
if (animationObj) {
|
|
3637
|
+
animationObj.reset();
|
|
3638
|
+
}
|
|
3639
|
+
};
|
|
3640
|
+
|
|
3641
|
+
return fire;
|
|
3642
|
+
}
|
|
3643
|
+
|
|
3644
|
+
// Make default export lazy to defer worker creation until called.
|
|
3645
|
+
var defaultFire;
|
|
3646
|
+
function getDefaultFire() {
|
|
3647
|
+
if (!defaultFire) {
|
|
3648
|
+
defaultFire = confettiCannon(null, { useWorker: true, resize: true });
|
|
3649
|
+
}
|
|
3650
|
+
return defaultFire;
|
|
3651
|
+
}
|
|
3652
|
+
|
|
3653
|
+
function transformPath2D(pathString, pathMatrix, x, y, scaleX, scaleY, rotation) {
|
|
3654
|
+
var path2d = new Path2D(pathString);
|
|
3655
|
+
|
|
3656
|
+
var t1 = new Path2D();
|
|
3657
|
+
t1.addPath(path2d, new DOMMatrix(pathMatrix));
|
|
3658
|
+
|
|
3659
|
+
var t2 = new Path2D();
|
|
3660
|
+
// see https://developer.mozilla.org/en-US/docs/Web/API/DOMMatrix/DOMMatrix
|
|
3661
|
+
t2.addPath(t1, new DOMMatrix([
|
|
3662
|
+
Math.cos(rotation) * scaleX,
|
|
3663
|
+
Math.sin(rotation) * scaleX,
|
|
3664
|
+
-Math.sin(rotation) * scaleY,
|
|
3665
|
+
Math.cos(rotation) * scaleY,
|
|
3666
|
+
x,
|
|
3667
|
+
y
|
|
3668
|
+
]));
|
|
3669
|
+
|
|
3670
|
+
return t2;
|
|
3671
|
+
}
|
|
3672
|
+
|
|
3673
|
+
function shapeFromPath(pathData) {
|
|
3674
|
+
if (!canUsePaths) {
|
|
3675
|
+
throw new Error('path confetti are not supported in this browser');
|
|
3676
|
+
}
|
|
3677
|
+
|
|
3678
|
+
var path, matrix;
|
|
3679
|
+
|
|
3680
|
+
if (typeof pathData === 'string') {
|
|
3681
|
+
path = pathData;
|
|
3682
|
+
} else {
|
|
3683
|
+
path = pathData.path;
|
|
3684
|
+
matrix = pathData.matrix;
|
|
3685
|
+
}
|
|
3686
|
+
|
|
3687
|
+
var path2d = new Path2D(path);
|
|
3688
|
+
var tempCanvas = document.createElement('canvas');
|
|
3689
|
+
var tempCtx = tempCanvas.getContext('2d');
|
|
3690
|
+
|
|
3691
|
+
if (!matrix) {
|
|
3692
|
+
// attempt to figure out the width of the path, up to 1000x1000
|
|
3693
|
+
var maxSize = 1000;
|
|
3694
|
+
var minX = maxSize;
|
|
3695
|
+
var minY = maxSize;
|
|
3696
|
+
var maxX = 0;
|
|
3697
|
+
var maxY = 0;
|
|
3698
|
+
var width, height;
|
|
3699
|
+
|
|
3700
|
+
// do some line skipping... this is faster than checking
|
|
3701
|
+
// every pixel and will be mostly still correct
|
|
3702
|
+
for (var x = 0; x < maxSize; x += 2) {
|
|
3703
|
+
for (var y = 0; y < maxSize; y += 2) {
|
|
3704
|
+
if (tempCtx.isPointInPath(path2d, x, y, 'nonzero')) {
|
|
3705
|
+
minX = Math.min(minX, x);
|
|
3706
|
+
minY = Math.min(minY, y);
|
|
3707
|
+
maxX = Math.max(maxX, x);
|
|
3708
|
+
maxY = Math.max(maxY, y);
|
|
3709
|
+
}
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
3712
|
+
|
|
3713
|
+
width = maxX - minX;
|
|
3714
|
+
height = maxY - minY;
|
|
3715
|
+
|
|
3716
|
+
var maxDesiredSize = 10;
|
|
3717
|
+
var scale = Math.min(maxDesiredSize/width, maxDesiredSize/height);
|
|
3718
|
+
|
|
3719
|
+
matrix = [
|
|
3720
|
+
scale, 0, 0, scale,
|
|
3721
|
+
-Math.round((width/2) + minX) * scale,
|
|
3722
|
+
-Math.round((height/2) + minY) * scale
|
|
3723
|
+
];
|
|
3724
|
+
}
|
|
3725
|
+
|
|
3726
|
+
return {
|
|
3727
|
+
type: 'path',
|
|
3728
|
+
path: path,
|
|
3729
|
+
matrix: matrix
|
|
3730
|
+
};
|
|
3731
|
+
}
|
|
3732
|
+
|
|
3733
|
+
function shapeFromText(textData) {
|
|
3734
|
+
var text,
|
|
3735
|
+
scalar = 1,
|
|
3736
|
+
color = '#000000',
|
|
3737
|
+
// see https://nolanlawson.com/2022/04/08/the-struggle-of-using-native-emoji-on-the-web/
|
|
3738
|
+
fontFamily = '"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji", "EmojiOne Color", "Android Emoji", "Twemoji Mozilla", "system emoji", sans-serif';
|
|
3739
|
+
|
|
3740
|
+
if (typeof textData === 'string') {
|
|
3741
|
+
text = textData;
|
|
3742
|
+
} else {
|
|
3743
|
+
text = textData.text;
|
|
3744
|
+
scalar = 'scalar' in textData ? textData.scalar : scalar;
|
|
3745
|
+
fontFamily = 'fontFamily' in textData ? textData.fontFamily : fontFamily;
|
|
3746
|
+
color = 'color' in textData ? textData.color : color;
|
|
3747
|
+
}
|
|
3748
|
+
|
|
3749
|
+
// all other confetti are 10 pixels,
|
|
3750
|
+
// so this pixel size is the de-facto 100% scale confetti
|
|
3751
|
+
var fontSize = 10 * scalar;
|
|
3752
|
+
var font = '' + fontSize + 'px ' + fontFamily;
|
|
3753
|
+
|
|
3754
|
+
var canvas = new OffscreenCanvas(fontSize, fontSize);
|
|
3755
|
+
var ctx = canvas.getContext('2d');
|
|
3756
|
+
|
|
3757
|
+
ctx.font = font;
|
|
3758
|
+
var size = ctx.measureText(text);
|
|
3759
|
+
var width = Math.ceil(size.actualBoundingBoxRight + size.actualBoundingBoxLeft);
|
|
3760
|
+
var height = Math.ceil(size.actualBoundingBoxAscent + size.actualBoundingBoxDescent);
|
|
3761
|
+
|
|
3762
|
+
var padding = 2;
|
|
3763
|
+
var x = size.actualBoundingBoxLeft + padding;
|
|
3764
|
+
var y = size.actualBoundingBoxAscent + padding;
|
|
3765
|
+
width += padding + padding;
|
|
3766
|
+
height += padding + padding;
|
|
3767
|
+
|
|
3768
|
+
canvas = new OffscreenCanvas(width, height);
|
|
3769
|
+
ctx = canvas.getContext('2d');
|
|
3770
|
+
ctx.font = font;
|
|
3771
|
+
ctx.fillStyle = color;
|
|
3772
|
+
|
|
3773
|
+
ctx.fillText(text, x, y);
|
|
3774
|
+
|
|
3775
|
+
var scale = 1 / scalar;
|
|
3776
|
+
|
|
3777
|
+
return {
|
|
3778
|
+
type: 'bitmap',
|
|
3779
|
+
// TODO these probably need to be transfered for workers
|
|
3780
|
+
bitmap: canvas.transferToImageBitmap(),
|
|
3781
|
+
matrix: [scale, 0, 0, scale, -width * scale / 2, -height * scale / 2]
|
|
3782
|
+
};
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
module.exports = function() {
|
|
3786
|
+
return getDefaultFire().apply(this, arguments);
|
|
3787
|
+
};
|
|
3788
|
+
module.exports.reset = function() {
|
|
3789
|
+
getDefaultFire().reset();
|
|
3790
|
+
};
|
|
3791
|
+
module.exports.create = confettiCannon;
|
|
3792
|
+
module.exports.shapeFromPath = shapeFromPath;
|
|
3793
|
+
module.exports.shapeFromText = shapeFromText;
|
|
3794
|
+
}((function () {
|
|
3795
|
+
if (typeof window !== 'undefined') {
|
|
3796
|
+
return window;
|
|
3797
|
+
}
|
|
3798
|
+
|
|
3799
|
+
if (typeof self !== 'undefined') {
|
|
3800
|
+
return self;
|
|
3801
|
+
}
|
|
3802
|
+
|
|
3803
|
+
return this || {};
|
|
3804
|
+
})(), module$1, false));
|
|
3805
|
+
|
|
3806
|
+
// end source content
|
|
3807
|
+
|
|
3808
|
+
var confetti = module$1.exports;
|
|
3809
|
+
module$1.exports.create;
|
|
3810
|
+
|
|
3811
|
+
const defaultColors = ['#22c55e', '#3b82f6', '#a855f7', '#f59e0b', '#ef4444', '#ec4899'];
|
|
3812
|
+
/**
|
|
3813
|
+
* Celebration component for triggering confetti and other celebration animations.
|
|
3814
|
+
*
|
|
3815
|
+
* @example
|
|
3816
|
+
* // Basic confetti on goal completion
|
|
3817
|
+
* <Celebration trigger={goalCompleted} onComplete={() => setGoalCompleted(false)} />
|
|
3818
|
+
*
|
|
3819
|
+
* @example
|
|
3820
|
+
* // Fireworks for major achievements
|
|
3821
|
+
* <Celebration trigger={achieved} type="fireworks" duration={3000} />
|
|
3822
|
+
*
|
|
3823
|
+
* @example
|
|
3824
|
+
* // Stars with custom colors
|
|
3825
|
+
* <Celebration trigger={true} type="stars" colors={['#ffd700', '#ffed4a']} />
|
|
3826
|
+
*/
|
|
3827
|
+
function Celebration({ trigger = false, type = 'confetti', duration = 2000, particleCount = 100, spread = 70, origin = { x: 0.5, y: 0.6 }, colors = defaultColors, onComplete, enabled = true, }) {
|
|
3828
|
+
const animationRef = useRef(null);
|
|
3829
|
+
const endTimeRef = useRef(0);
|
|
3830
|
+
const fireConfetti = useCallback(() => {
|
|
3831
|
+
confetti({
|
|
3832
|
+
particleCount: Math.floor(particleCount / 3),
|
|
3833
|
+
spread,
|
|
3834
|
+
origin,
|
|
3835
|
+
colors,
|
|
3836
|
+
disableForReducedMotion: true,
|
|
3837
|
+
});
|
|
3838
|
+
}, [particleCount, spread, origin, colors]);
|
|
3839
|
+
const fireFireworks = useCallback(() => {
|
|
3840
|
+
const end = Date.now() + duration;
|
|
3841
|
+
endTimeRef.current = end;
|
|
3842
|
+
const frame = () => {
|
|
3843
|
+
confetti({
|
|
3844
|
+
particleCount: 3,
|
|
3845
|
+
angle: 60,
|
|
3846
|
+
spread: 55,
|
|
3847
|
+
origin: { x: 0 },
|
|
3848
|
+
colors,
|
|
3849
|
+
disableForReducedMotion: true,
|
|
3850
|
+
});
|
|
3851
|
+
confetti({
|
|
3852
|
+
particleCount: 3,
|
|
3853
|
+
angle: 120,
|
|
3854
|
+
spread: 55,
|
|
3855
|
+
origin: { x: 1 },
|
|
3856
|
+
colors,
|
|
3857
|
+
disableForReducedMotion: true,
|
|
3858
|
+
});
|
|
3859
|
+
if (Date.now() < endTimeRef.current) {
|
|
3860
|
+
animationRef.current = requestAnimationFrame(frame);
|
|
3861
|
+
}
|
|
3862
|
+
};
|
|
3863
|
+
frame();
|
|
3864
|
+
}, [duration, colors]);
|
|
3865
|
+
const fireStars = useCallback(() => {
|
|
3866
|
+
const defaults = {
|
|
3867
|
+
spread: 360,
|
|
3868
|
+
ticks: 50,
|
|
3869
|
+
gravity: 0,
|
|
3870
|
+
decay: 0.94,
|
|
3871
|
+
startVelocity: 30,
|
|
3872
|
+
colors,
|
|
3873
|
+
shapes: ['star'],
|
|
3874
|
+
disableForReducedMotion: true,
|
|
3875
|
+
};
|
|
3876
|
+
const shoot = () => {
|
|
3877
|
+
confetti({
|
|
3878
|
+
...defaults,
|
|
3879
|
+
particleCount: 10,
|
|
3880
|
+
scalar: 1.2,
|
|
3881
|
+
origin: { x: Math.random(), y: Math.random() * 0.5 },
|
|
3882
|
+
});
|
|
3883
|
+
confetti({
|
|
3884
|
+
...defaults,
|
|
3885
|
+
particleCount: 5,
|
|
3886
|
+
scalar: 0.75,
|
|
3887
|
+
origin: { x: Math.random(), y: Math.random() * 0.5 },
|
|
3888
|
+
});
|
|
3889
|
+
};
|
|
3890
|
+
shoot();
|
|
3891
|
+
setTimeout(shoot, 200);
|
|
3892
|
+
setTimeout(shoot, 400);
|
|
3893
|
+
}, [colors]);
|
|
3894
|
+
useEffect(() => {
|
|
3895
|
+
if (!trigger || !enabled)
|
|
3896
|
+
return;
|
|
3897
|
+
switch (type) {
|
|
3898
|
+
case 'fireworks':
|
|
3899
|
+
fireFireworks();
|
|
3900
|
+
break;
|
|
3901
|
+
case 'stars':
|
|
3902
|
+
fireStars();
|
|
3903
|
+
break;
|
|
3904
|
+
case 'confetti':
|
|
3905
|
+
default:
|
|
3906
|
+
// Fire multiple bursts for confetti
|
|
3907
|
+
fireConfetti();
|
|
3908
|
+
setTimeout(fireConfetti, 150);
|
|
3909
|
+
setTimeout(fireConfetti, 300);
|
|
3910
|
+
break;
|
|
3911
|
+
}
|
|
3912
|
+
const timeout = setTimeout(() => {
|
|
3913
|
+
onComplete?.();
|
|
3914
|
+
}, duration);
|
|
3915
|
+
return () => {
|
|
3916
|
+
clearTimeout(timeout);
|
|
3917
|
+
if (animationRef.current) {
|
|
3918
|
+
cancelAnimationFrame(animationRef.current);
|
|
3919
|
+
}
|
|
3920
|
+
};
|
|
3921
|
+
}, [trigger, type, enabled, duration, fireConfetti, fireFireworks, fireStars, onComplete]);
|
|
3922
|
+
// This component doesn't render anything visible
|
|
3923
|
+
return null;
|
|
3924
|
+
}
|
|
3925
|
+
/**
|
|
3926
|
+
* Hook for programmatically triggering celebrations
|
|
3927
|
+
*/
|
|
3928
|
+
function useCelebration() {
|
|
3929
|
+
const celebrate = useCallback((options) => {
|
|
3930
|
+
const { type = 'confetti', particleCount = 100, spread = 70, origin = { x: 0.5, y: 0.6 }, colors = defaultColors, duration = 2000, } = options || {};
|
|
3931
|
+
switch (type) {
|
|
3932
|
+
case 'fireworks': {
|
|
3933
|
+
const end = Date.now() + duration;
|
|
3934
|
+
const frame = () => {
|
|
3935
|
+
confetti({
|
|
3936
|
+
particleCount: 3,
|
|
3937
|
+
angle: 60,
|
|
3938
|
+
spread: 55,
|
|
3939
|
+
origin: { x: 0 },
|
|
3940
|
+
colors,
|
|
3941
|
+
disableForReducedMotion: true,
|
|
3942
|
+
});
|
|
3943
|
+
confetti({
|
|
3944
|
+
particleCount: 3,
|
|
3945
|
+
angle: 120,
|
|
3946
|
+
spread: 55,
|
|
3947
|
+
origin: { x: 1 },
|
|
3948
|
+
colors,
|
|
3949
|
+
disableForReducedMotion: true,
|
|
3950
|
+
});
|
|
3951
|
+
if (Date.now() < end) {
|
|
3952
|
+
requestAnimationFrame(frame);
|
|
3953
|
+
}
|
|
3954
|
+
};
|
|
3955
|
+
frame();
|
|
3956
|
+
break;
|
|
3957
|
+
}
|
|
3958
|
+
case 'stars': {
|
|
3959
|
+
const defaults = {
|
|
3960
|
+
spread: 360,
|
|
3961
|
+
ticks: 50,
|
|
3962
|
+
gravity: 0,
|
|
3963
|
+
decay: 0.94,
|
|
3964
|
+
startVelocity: 30,
|
|
3965
|
+
colors,
|
|
3966
|
+
shapes: ['star'],
|
|
3967
|
+
disableForReducedMotion: true,
|
|
3968
|
+
};
|
|
3969
|
+
const shoot = () => {
|
|
3970
|
+
confetti({
|
|
3971
|
+
...defaults,
|
|
3972
|
+
particleCount: 10,
|
|
3973
|
+
scalar: 1.2,
|
|
3974
|
+
origin: { x: Math.random(), y: Math.random() * 0.5 },
|
|
3975
|
+
});
|
|
3976
|
+
confetti({
|
|
3977
|
+
...defaults,
|
|
3978
|
+
particleCount: 5,
|
|
3979
|
+
scalar: 0.75,
|
|
3980
|
+
origin: { x: Math.random(), y: Math.random() * 0.5 },
|
|
3981
|
+
});
|
|
3982
|
+
};
|
|
3983
|
+
shoot();
|
|
3984
|
+
setTimeout(shoot, 200);
|
|
3985
|
+
setTimeout(shoot, 400);
|
|
3986
|
+
break;
|
|
3987
|
+
}
|
|
3988
|
+
case 'confetti':
|
|
3989
|
+
default: {
|
|
3990
|
+
const fire = () => {
|
|
3991
|
+
confetti({
|
|
3992
|
+
particleCount: Math.floor(particleCount / 3),
|
|
3993
|
+
spread,
|
|
3994
|
+
origin,
|
|
3995
|
+
colors,
|
|
3996
|
+
disableForReducedMotion: true,
|
|
3997
|
+
});
|
|
3998
|
+
};
|
|
3999
|
+
fire();
|
|
4000
|
+
setTimeout(fire, 150);
|
|
4001
|
+
setTimeout(fire, 300);
|
|
4002
|
+
break;
|
|
4003
|
+
}
|
|
4004
|
+
}
|
|
4005
|
+
}, []);
|
|
4006
|
+
return { celebrate };
|
|
4007
|
+
}
|
|
4008
|
+
|
|
2923
4009
|
/**
|
|
2924
4010
|
* Stack component for arranging children vertically or horizontally with consistent spacing.
|
|
2925
4011
|
*
|
|
@@ -59007,5 +60093,5 @@ function Responsive({ mobile, tablet, desktop, }) {
|
|
|
59007
60093
|
return jsx(Fragment, { children: mobile || tablet || desktop });
|
|
59008
60094
|
}
|
|
59009
60095
|
|
|
59010
|
-
export { Accordion, ActionBar, ActionBarCenter, ActionBarLeft, ActionBarRight, ActionButton, AdminModal, Alert, AlertDialog, AppLayout, Autocomplete, Avatar, BREAKPOINTS, Badge, BottomNavigation, BottomNavigationSpacer, BottomSheet, BottomSheetActions, BottomSheetContent, BottomSheetHeader, Box, Breadcrumbs, Button, ButtonGroup, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardView, Carousel, Checkbox, CheckboxList, Chip, ChipGroup, Collapsible, ColorPicker, Combobox, ComingSoon, CommandPalette, CompactStat, ConfirmDialog, ContextMenu, ControlBar, CurrencyDisplay, CurrencyInput, Dashboard, DashboardContent, DashboardHeader, DataGrid, DataTable, DataTableCardView, DateDisplay, DatePicker, DateRangePicker, DateTimePicker, DesktopOnly, Drawer, DrawerFooter, DropZone, Dropdown, DropdownTrigger, EmptyState, ErrorBoundary, ExpandablePanel, ExpandablePanelContainer, ExpandablePanelSpacer, ExpandableRowButton, ExpandableToolbar, ExpandedRowEditForm, ExportButton, FORMULA_CATEGORIES, FORMULA_DEFINITIONS, FORMULA_NAMES, FieldArray, FileUpload, FilterBar, FilterControls, FilterStatusBanner, FloatingActionButton, Form, FormContext, FormControl, FormWizard, Grid, GridItem, Hide, HorizontalScroll, HoverCard, InfiniteScroll, Input, KanbanBoard, Layout, Loading, LoadingOverlay, Logo, MarkdownEditor, MaskedInput, Menu, MenuDivider, MobileHeader, MobileHeaderSpacer, MobileLayout, MobileOnly, MobileProvider, Modal, ModalFooter, MultiSelect, NotificationBanner, NotificationBar, NotificationBell, NotificationIndicator, NumberInput, Page, PageHeader, PageLayout, PageNavigation, Pagination, PasswordInput, Popover, Progress, PullToRefresh, QueryTransparency, RadioGroup, Rating, Responsive, RichTextEditor, SearchBar, SearchableList, Select, Separator, Show, Sidebar, SidebarGroup, Skeleton, SkeletonCard$1 as SkeletonCard, SkeletonTable, Slider, Spreadsheet, SpreadsheetReport, Stack, StatCard, StatItem, StatsCardGrid, StatsGrid, StatusBadge, StatusBar, StepIndicator, Stepper, SwipeActions, SwipeableCard, SwipeableListItem, Switch, Tabs, TabsContent, TabsList, TabsRoot, TabsTrigger, Text, Textarea, ThemeToggle, TimePicker, Timeline, TimezoneSelector, Toast, ToastContainer, Tooltip, Transfer, TreeView, TwoColumnContent, UserProfileButton, addErrorMessage, addInfoMessage, addSuccessMessage, addWarningMessage, calculateColumnWidth, createActionsSection, createFiltersSection, createMultiSheetExcel, createPageControlsSection, createQueryDetailsSection, exportDataTableToExcel, exportToExcel, formatStatisticValue, formatStatistics, getFormula, getFormulasByCategory, getLocalTimezone, isValidTimezone, loadColumnOrder, loadColumnWidths, reorderArray, saveColumnOrder, saveColumnWidths, searchFormulas, statusManager, useBreadcrumbReset, useBreakpoint, useBreakpointValue, useColumnReorder, useColumnResize, useCommandPalette, useConfirmDialog, useFABScroll, useFormContext, useIsDesktop, useIsMobile, useIsTablet, useIsTouchDevice, useMediaQuery, useMobileContext, useOrientation, usePrefersMobile, useResponsiveCallback, useSafeAreaInsets, useViewportSize, withMobileContext };
|
|
60096
|
+
export { Accordion, ActionBar, ActionBarCenter, ActionBarLeft, ActionBarRight, ActionButton, AdminModal, Alert, AlertDialog, AppLayout, Autocomplete, Avatar, BREAKPOINTS, Badge, BottomNavigation, BottomNavigationSpacer, BottomSheet, BottomSheetActions, BottomSheetContent, BottomSheetHeader, Box, Breadcrumbs, Button, ButtonGroup, Calendar, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, CardView, Carousel, Celebration, Checkbox, CheckboxList, Chip, ChipGroup, Collapsible, ColorPicker, Combobox, ComingSoon, CommandPalette, CompactStat, ConfirmDialog, ContextMenu, ControlBar, CurrencyDisplay, CurrencyInput, Dashboard, DashboardContent, DashboardHeader, DataGrid, DataTable, DataTableCardView, DateDisplay, DatePicker, DateRangePicker, DateTimePicker, DesktopOnly, Drawer, DrawerFooter, DropZone, Dropdown, DropdownTrigger, EmptyState, ErrorBoundary, ExpandablePanel, ExpandablePanelContainer, ExpandablePanelSpacer, ExpandableRowButton, ExpandableToolbar, ExpandedRowEditForm, ExportButton, FORMULA_CATEGORIES, FORMULA_DEFINITIONS, FORMULA_NAMES, FieldArray, FileUpload, FilterBar, FilterControls, FilterStatusBanner, FloatingActionButton, Form, FormContext, FormControl, FormWizard, Grid, GridItem, Hide, HorizontalScroll, HoverCard, InfiniteScroll, Input, KanbanBoard, Layout, Loading, LoadingOverlay, Logo, MarkdownEditor, MaskedInput, Menu, MenuDivider, MobileHeader, MobileHeaderSpacer, MobileLayout, MobileOnly, MobileProvider, Modal, ModalFooter, MultiSelect, NotificationBanner, NotificationBar, NotificationBell, NotificationIndicator, NumberInput, Page, PageHeader, PageLayout, PageNavigation, Pagination, PasswordInput, Popover, Progress, PullToRefresh, QueryTransparency, RadioGroup, Rating, Responsive, RichTextEditor, SearchBar, SearchableList, Select, Separator, Show, Sidebar, SidebarGroup, Skeleton, SkeletonCard$1 as SkeletonCard, SkeletonTable, Slider, Spreadsheet, SpreadsheetReport, Stack, StatCard, StatItem, StatsCardGrid, StatsGrid, StatusBadge, StatusBar, StepIndicator, Stepper, SwipeActions, SwipeableCard, SwipeableListItem, Switch, Tabs, TabsContent, TabsList, TabsRoot, TabsTrigger, Text, Textarea, ThemeToggle, TimePicker, Timeline, TimezoneSelector, Toast, ToastContainer, Tooltip, Transfer, TreeView, TwoColumnContent, UserProfileButton, addErrorMessage, addInfoMessage, addSuccessMessage, addWarningMessage, calculateColumnWidth, createActionsSection, createFiltersSection, createMultiSheetExcel, createPageControlsSection, createQueryDetailsSection, exportDataTableToExcel, exportToExcel, formatStatisticValue, formatStatistics, getFormula, getFormulasByCategory, getLocalTimezone, isValidTimezone, loadColumnOrder, loadColumnWidths, reorderArray, saveColumnOrder, saveColumnWidths, searchFormulas, statusManager, useBreadcrumbReset, useBreakpoint, useBreakpointValue, useCelebration, useColumnReorder, useColumnResize, useCommandPalette, useConfirmDialog, useFABScroll, useFormContext, useIsDesktop, useIsMobile, useIsTablet, useIsTouchDevice, useMediaQuery, useMobileContext, useOrientation, usePrefersMobile, useResponsiveCallback, useSafeAreaInsets, useViewportSize, withMobileContext };
|
|
59011
60097
|
//# sourceMappingURL=index.esm.js.map
|