@neoconfetti/svelte
Advanced tools
Comparing version 1.0.0 to 2.0.0
@@ -1,60 +0,4 @@ | ||
/** | ||
* Actions can return an object containing the two properties defined in this interface. Both are optional. | ||
* - update: An action can have a parameter. This method will be called whenever that parameter changes, | ||
* immediately after Svelte has applied updates to the markup. | ||
* - destroy: Method that is called after the element is unmounted | ||
* | ||
* Additionally, you can specify which additional attributes and events the action enables on the applied element. | ||
* This applies to TypeScript typings only and has no effect at runtime. | ||
* | ||
* Example usage: | ||
* ```ts | ||
* interface Attributes { | ||
* newprop?: string; | ||
* 'on:event': (e: CustomEvent<boolean>) => void; | ||
* } | ||
* | ||
* export function myAction(node: HTMLElement, parameter: Parameter): ActionReturn<Parameter, Attributes> { | ||
* // ... | ||
* return { | ||
* update: (updatedParameter) => {...}, | ||
* destroy: () => {...} | ||
* }; | ||
* } | ||
* ``` | ||
* | ||
* Docs: https://svelte.dev/docs#template-syntax-element-directives-use-action | ||
*/ | ||
interface ActionReturn<Parameter = any, Attributes extends Record<string, any> = Record<never, any>> { | ||
update?: (parameter: Parameter) => void; | ||
destroy?: () => void; | ||
type ParticleShape = 'mix' | 'circles' | 'rectangles'; | ||
type ConfettiOptions = { | ||
/** | ||
* ### DO NOT USE THIS | ||
* This exists solely for type-checking and has no effect at runtime. | ||
* Set this through the `Attributes` generic instead. | ||
*/ | ||
$$_attributes?: Attributes; | ||
} | ||
/** | ||
* Actions are functions that are called when an element is created. | ||
* You can use this interface to type such actions. | ||
* The following example defines an action that only works on `<div>` elements | ||
* and optionally accepts a parameter which it has a default value for: | ||
* ```ts | ||
* export const myAction: Action<HTMLDivElement, { someProperty: boolean }> = (node, param = { someProperty: true }) => { | ||
* // ... | ||
* } | ||
* ``` | ||
* You can return an object with methods `update` and `destroy` from the function and type which additional attributes and events it has. | ||
* See interface `ActionReturn` for more details. | ||
* | ||
* Docs: https://svelte.dev/docs#template-syntax-element-directives-use-action | ||
*/ | ||
interface Action<Element = HTMLElement, Parameter = any, Attributes extends Record<string, any> = Record<never, any>> { | ||
<Node extends Element>(node: Node, parameter?: Parameter): void | ActionReturn<Parameter, Attributes>; | ||
} | ||
declare type ParticleShape = 'mix' | 'circles' | 'rectangles'; | ||
declare type ConfettiOptions = { | ||
/** | ||
* Number of confetti particles to create | ||
@@ -119,4 +63,7 @@ * | ||
}; | ||
declare const confetti: Action<HTMLElement, ConfettiOptions>; | ||
declare function confetti(node: HTMLElement, options?: ConfettiOptions): { | ||
update(newOptions: ConfettiOptions): void; | ||
destroy(): void; | ||
}; | ||
export { ConfettiOptions, ParticleShape as ConfettiParticleShape, confetti }; | ||
export { type ConfettiOptions, type ParticleShape as ConfettiParticleShape, confetti }; |
@@ -1,2 +0,159 @@ | ||
const t=(t,b={})=>{w(b);let{colors:k=["#FFC700","#FF0000","#2E3191","#41BBC7"],duration:W=3500,force:S=.5,particleCount:G=150,particleShape:X="mix",particleSize:_=12,destroyAfterDone:C=!0,stageHeight:z=800,stageWidth:E=1600}=b;!function(t){const e=f("style");e.dataset.neoconfetti="",e.textContent='@keyframes fk9XWG_y-axis{to{transform:translate3d(0,var(--stage-height),0)}}@keyframes fk9XWG_x-axis{to{transform:translate3d(var(--x-landing-point),0,0)}}@keyframes fk9XWG_rotation{50%{transform:rotate3d(var(--half-rotation),180deg)}to{transform:rotate3d(var(--rotation),360deg)}}.fk9XWG_container{width:0;height:0;z-index:1200;position:relative;overflow:visible}.fk9XWG_particle{animation:x-axis var(--duration-chaos)forwards cubic-bezier(var(--x1),var(--x2),var(--x3),var(--x4));animation-name:fk9XWG_x-axis}.fk9XWG_particle>div{animation:y-axis var(--duration-chaos)forwards cubic-bezier(var(--y1),var(--y2),var(--y3),var(--y4));width:var(--width);height:var(--height);animation-name:fk9XWG_y-axis;position:absolute;top:0;left:0}.fk9XWG_particle>div:before{height:100%;width:100%;content:"";background-color:var(--bgcolor);animation:rotation var(--rotation-duration)infinite linear;border-radius:var(--border-radius);animation-name:fk9XWG_rotation;display:block}',h(document.head,e)}(),t.classList.add("fk9XWG_container"),t.style.setProperty("--stage-height",z+"px");let P,A=p(G,k),H=e(t,A);function M(t,e){const f=l(c()*(x-1)),h="rectangles"!==X&&("circles"===X||v(f)),p=(e,r)=>t.style.setProperty(e,r+"");p("--x-landing-point",u(s(m(e,90)-180),0,180,-E/2,E/2)+"px"),p("--duration-chaos",W-l(1e3*c())+"ms");const b=c()<a?g(c()*i,2):0;p("--x1",b),p("--x2",-1*b),p("--x3",b),p("--x4",g(s(u(s(m(e,90)-180),0,180,-1,1)),4)),p("--y1",g(c()*n,4)),p("--y2",g(c()*S*(y()?1:-1),4)),p("--y3",n),p("--y4",g(d(u(s(e-180),0,180,S,-S),0),4)),p("--width",(h?_:l(4*c())+_/2)+"px"),p("--height",(h?_:l(2*c())+_)+"px");const k=f.toString(2).padStart(3,"0").split("");p("--half-rotation",k.map((t=>+t/2+""))),p("--rotation",k),p("--rotation-duration",g(c()*(o-r)+r)+"ms"),p("--border-radius",h?"50%":0)}for(const[t,e]of Object.entries(H))M(e,A[+t].degree);return Promise.resolve().then((()=>P=setTimeout((()=>C&&(t.innerHTML="")),W))),{update(r){w(r);const o=r.particleCount??G,a=r.colors??k,i=r.stageHeight??z;if(A=p(o,a),o===G&&JSON.stringify(k)!==JSON.stringify(a))for(const[t,{color:e}]of Object.entries(A))H[+t].style.setProperty("--bgcolor",e);o!==G&&(t.innerHTML="",H=e(t,A)),C&&!r.destroyAfterDone&&clearTimeout(P),t.style.setProperty("--stage-height",i+"px"),k=a,W=r.duration??W,S=r.force??S,G=o,X=r.particleShape??X,_=r.particleSize??_,C=r.destroyAfterDone??C,z=i,E=r.stageWidth??E},destroy(){clearTimeout(P)}}};function e(t,e=[]){const r=[];for(const{color:o}of e){const e=f("div");e.className="fk9XWG_particle",e.style.setProperty("--bgcolor",o);const a=f("div");h(e,a),h(t,e),r.push(e)}return r}const r=200,o=800,a=.1,i=.3,n=.5,s=Math.abs,c=Math.random,l=Math.round,d=Math.max,f=t=>document.createElement(t),h=(t,e)=>t.appendChild(e),p=(t,e)=>Array.from({length:t},((r,o)=>({color:e[o%e.length],degree:360*o/t}))),g=(t,e=2)=>l((t+Number.EPSILON)*10**e)/10**e,u=(t,e,r,o,a)=>(t-e)*(a-o)/(r-e)+o,m=(t,e)=>t+e>360?t+e-360:t+e,y=()=>c()>.5,x=6,v=t=>1!==t&&y(),b=t=>void 0===t,k=(t,e)=>{if(!b(t)&&Number.isSafeInteger(t)&&t<0)throw new Error(e+" must be a positive integer")},w=({particleCount:t,duration:e,colors:r,particleSize:o,force:a,stageHeight:i,stageWidth:n,particleShape:s})=>{if(k(t,"particleCount"),k(e,"duration"),k(o,"particleSize"),k(a,"force"),k(i,"stageHeight"),k(n,"stageWidth"),!b(s)&&!/^(mix|circles|rectangles)$/i.test(s))throw new Error('particlesShape should be either "mix" or "circles" or "rectangle"');if(!b(r)&&!Array.isArray(r))throw new Error("colors must be an array of strings");if(a>1)throw new Error("force must be within 0 and 1")};export{t as confetti}; | ||
//# sourceMappingURL=index.js.map | ||
// ../core/dist/index.js | ||
var style_module_default = '@keyframes Bc2PgW_y-axis{to{translate:0 var(--sh)}}@keyframes Bc2PgW_x-axis{to{translate:var(--xlp)0}}@keyframes Bc2PgW_rotation{50%{rotate:var(--hr)180deg}to{rotate:var(--r)360deg}}.Bc2PgW_container{z-index:1200;width:0;height:0;position:relative;overflow:visible}.Bc2PgW_particle{animation:x-axis var(--dc)forwards cubic-bezier(var(--x1),var(--x2),var(--x3),var(--x4));animation-name:Bc2PgW_x-axis}.Bc2PgW_particle>div{animation:y-axis var(--dc)forwards cubic-bezier(var(--y1),var(--y2),var(--y3),var(--y4));width:var(--w);height:var(--h);animation-name:Bc2PgW_y-axis;position:absolute;top:0;left:0}.Bc2PgW_particle>div:before{content:"";background-color:var(--bgc);animation:rotation var(--rd)infinite linear;border-radius:var(--br);width:100%;height:100%;animation-name:Bc2PgW_rotation;display:block}'; | ||
var particle = "Bc2PgW_particle"; | ||
var container = "Bc2PgW_container"; | ||
function confetti(node, options = {}) { | ||
let { | ||
colors = ["#FFC700", "#FF0000", "#2E3191", "#41BBC7"], | ||
duration = 3500, | ||
force = 0.5, | ||
particleCount = 150, | ||
particleShape = "mix", | ||
particleSize = 12, | ||
destroyAfterDone = true, | ||
stageHeight = 800, | ||
stageWidth = 1600 | ||
} = options; | ||
appendStyles(style_module_default); | ||
node.classList.add(container); | ||
node.style.setProperty("--sh", stageHeight + "px"); | ||
let particles = createParticles(particleCount, colors); | ||
let nodes = createParticleNodes(node, particles); | ||
function confettiStyles(node2, degree) { | ||
const rotationTransform = mathRound(random() * (POSSIBLE_ROTATION_TRANSFORMS - 1)); | ||
const isCircle = particleShape !== "rectangles" && (particleShape === "circles" || shouldBeCircle(rotationTransform)); | ||
const setCSSVar = (key, val) => node2.style.setProperty(key, val + ""); | ||
setCSSVar( | ||
// x landing point | ||
"--xlp", | ||
mapRange(abs(rotate(degree, 90) - 180), 0, 180, -stageWidth / 2, stageWidth / 2) + "px" | ||
); | ||
setCSSVar( | ||
// duration chaos | ||
"--dc", | ||
duration - mathRound(random() * 1e3) + "ms" | ||
); | ||
const x1 = random() < CRAZY_PARTICLES_FREQUENCY ? round(random() * CRAZY_PARTICLE_CRAZINESS, 2) : 0; | ||
setCSSVar("--x1", x1); | ||
setCSSVar("--x2", x1 * -1); | ||
setCSSVar("--x3", x1); | ||
setCSSVar("--x4", round(abs(mapRange(abs(rotate(degree, 90) - 180), 0, 180, -1, 1)), 4)); | ||
setCSSVar("--y1", round(random() * BEZIER_MEDIAN, 4)); | ||
setCSSVar("--y2", round(random() * force * (coinFlip() ? 1 : -1), 4)); | ||
setCSSVar("--y3", BEZIER_MEDIAN); | ||
setCSSVar("--y4", round(max(mapRange(abs(degree - 180), 0, 180, force, -force), 0), 4)); | ||
setCSSVar( | ||
// --width | ||
"--w", | ||
(isCircle ? particleSize : mathRound(random() * 4) + particleSize / 2) + "px" | ||
); | ||
setCSSVar( | ||
// --height | ||
"--h", | ||
(isCircle ? particleSize : mathRound(random() * 2) + particleSize) + "px" | ||
); | ||
const rotation = rotationTransform.toString(2).padStart(3, "0").split(""); | ||
setCSSVar( | ||
// --half-rotation | ||
"--hr", | ||
rotation.map((n) => +n / 2 + "").join(" ") | ||
); | ||
setCSSVar( | ||
// --rotation | ||
"--r", | ||
rotation.join(" ") | ||
); | ||
setCSSVar( | ||
// --rotation-duration | ||
"--rd", | ||
round(random() * (ROTATION_SPEED_MAX - ROTATION_SPEED_MIN) + ROTATION_SPEED_MIN) + "ms" | ||
); | ||
setCSSVar( | ||
// --border-radius | ||
"--br", | ||
isCircle ? "50%" : 0 | ||
); | ||
} | ||
for (const [i, node2] of Object.entries(nodes)) | ||
confettiStyles(node2, particles[+i].degree); | ||
let timer; | ||
Promise.resolve().then( | ||
() => timer = setTimeout(() => destroyAfterDone && (node.innerHTML = ""), duration) | ||
); | ||
return { | ||
update(newOptions) { | ||
const newParticleCount = newOptions.particleCount ?? particleCount; | ||
const newColors = newOptions.colors ?? colors; | ||
const newStageHeight = newOptions.stageHeight ?? stageHeight; | ||
particles = createParticles(newParticleCount, newColors); | ||
if (newParticleCount === particleCount && JSON.stringify(colors) !== JSON.stringify(newColors)) | ||
for (const [i, { color }] of Object.entries(particles)) | ||
nodes[+i].style.setProperty( | ||
// bgcolor | ||
"--bgc", | ||
color | ||
); | ||
if (newParticleCount !== particleCount) { | ||
node.innerHTML = ""; | ||
nodes = createParticleNodes(node, particles); | ||
} | ||
if (destroyAfterDone && !newOptions.destroyAfterDone) | ||
clearTimeout(timer); | ||
node.style.setProperty("--sh", newStageHeight + "px"); | ||
colors = newColors; | ||
duration = newOptions.duration ?? duration; | ||
force = newOptions.force ?? force; | ||
particleCount = newParticleCount; | ||
particleShape = newOptions.particleShape ?? particleShape; | ||
particleSize = newOptions.particleSize ?? particleSize; | ||
destroyAfterDone = newOptions.destroyAfterDone ?? destroyAfterDone; | ||
stageHeight = newStageHeight; | ||
stageWidth = newOptions.stageWidth ?? stageWidth; | ||
}, | ||
destroy() { | ||
clearTimeout(timer); | ||
} | ||
}; | ||
} | ||
function appendStyles(styles) { | ||
const style = element("style"); | ||
style.dataset.neoconfetti = ""; | ||
style.textContent = styles; | ||
appendChild(document.head, style); | ||
} | ||
function createParticleNodes(node, particles = []) { | ||
const particleNodes = []; | ||
for (const { color } of particles) { | ||
const particleNode = element("div"); | ||
particleNode.className = particle; | ||
particleNode.style.setProperty("--bgc", color); | ||
const innerParticle = element("div"); | ||
appendChild(particleNode, innerParticle); | ||
appendChild(node, particleNode); | ||
particleNodes.push(particleNode); | ||
} | ||
return particleNodes; | ||
} | ||
var ROTATION_SPEED_MIN = 200; | ||
var ROTATION_SPEED_MAX = 800; | ||
var CRAZY_PARTICLES_FREQUENCY = 0.1; | ||
var CRAZY_PARTICLE_CRAZINESS = 0.3; | ||
var BEZIER_MEDIAN = 0.5; | ||
var abs = Math.abs; | ||
var random = Math.random; | ||
var mathRound = Math.round; | ||
var max = Math.max; | ||
var element = (name) => document.createElement(name); | ||
var appendChild = (parent, child) => parent.appendChild(child); | ||
var createParticles = (count, colors) => Array.from({ length: count }, (_, i) => ({ | ||
color: colors[i % colors.length], | ||
degree: i * 360 / count | ||
})); | ||
var round = (num, precision = 2) => mathRound((num + Number.EPSILON) * 10 ** precision) / 10 ** precision; | ||
var mapRange = (value, x1, y1, x2, y2) => (value - x1) * (y2 - x2) / (y1 - x1) + x2; | ||
var rotate = (degree, amount) => degree + amount > 360 ? degree + amount - 360 : degree + amount; | ||
var coinFlip = () => random() > 0.5; | ||
var POSSIBLE_ROTATION_TRANSFORMS = 6; | ||
var shouldBeCircle = (rotationTransform) => rotationTransform !== 1 && coinFlip(); | ||
export { confetti }; |
{ | ||
"name": "@neoconfetti/svelte", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"description": "Confetti explosion in Svelte 🎉🎊", | ||
@@ -43,11 +43,11 @@ "author": "Puru Vijay", | ||
"devDependencies": { | ||
"@neoconfetti/core": "1.0.0" | ||
"@neoconfetti/core": "2.0.0" | ||
}, | ||
"scripts": { | ||
"dev": "rollup -cw", | ||
"build": "rollup -c ", | ||
"compile:watch": "tsup --watch", | ||
"compile": "tsup", | ||
"size": "echo 'Svelte size:' && brotli-size dist/min/index.js", | ||
"pub": "pnpm build && pnpm publish --no-git-checks --access public", | ||
"pub:dry": "pnpm build && pnpm publish --dry-run --no-git-checks --access public", | ||
"size": "echo 'Svelte size:' && brotli-size dist/index.js" | ||
"pub:dry": "pnpm build && pnpm publish --dry-run --no-git-checks --access public" | ||
} | ||
} |
@@ -77,3 +77,3 @@ # @neoconfetti/svelte | ||
```svelte | ||
<div use:confetti={{ particleSize:20 }} /> | ||
<div use:confetti={{ particleSize: 20 }} /> | ||
``` | ||
@@ -169,3 +169,3 @@ | ||
### shouldDestroyAfterDone | ||
### destroyAfterDone | ||
@@ -172,0 +172,0 @@ Whether or not destroy all confetti nodes after the `duration` period has passed. By default it destroys all nodes, to free up memory. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
228
17317
1