number-flow
Advanced tools
Comparing version 0.4.2 to 0.5.0
@@ -27,3 +27,3 @@ export type NumberPartType = Exclude<Intl.NumberFormatPartTypes, 'minusSign' | 'plusSign'> | 'sign' | 'prefix' | 'suffix'; | ||
}; | ||
export type Value = Exclude<Parameters<typeof Intl.NumberFormat.prototype.formatToParts>[0], bigint>; | ||
export type Value = Exclude<Parameters<typeof Intl.NumberFormat.prototype.formatToParts>[0], bigint | undefined>; | ||
export declare function formatToData(value: Value, formatter: Intl.NumberFormat, prefix?: string, suffix?: string): { | ||
@@ -30,0 +30,0 @@ pre: KeyedNumberPart[]; |
@@ -1,50 +0,6 @@ | ||
import { type Data } from './formatter'; | ||
import { ServerSafeHTMLElement } from './ssr'; | ||
export * from './lite'; | ||
export { define } from './util/dom'; | ||
export { prefersReducedMotion } from './styles'; | ||
export { renderInnerHTML } from './ssr'; | ||
export * from './plugins'; | ||
export * from './formatter'; | ||
export declare const canAnimate: boolean; | ||
export type Trend = number | ((oldValue: number, value: number) => number); | ||
export type DigitOptions = { | ||
max?: number; | ||
}; | ||
export type Digits = Record<number, DigitOptions>; | ||
export interface Props { | ||
transformTiming: EffectTiming; | ||
spinTiming: EffectTiming | undefined; | ||
opacityTiming: EffectTiming; | ||
animated: boolean; | ||
respectMotionPreference: boolean; | ||
trend: Trend; | ||
continuous: boolean; | ||
digits: Digits | undefined; | ||
} | ||
export interface NumberFlowLite extends Props { | ||
} | ||
export declare class NumberFlowLite extends ServerSafeHTMLElement implements Props { | ||
/** | ||
* Use `private _private` properties instead of `#private` to avoid # polyfill and | ||
* reduce bundle size. Also, use `readonly` properties instead of getters to save on bundle | ||
* size, even though you have to do gross stuff like `(this as Mutable<...>)` until TS | ||
* supports e.g. https://github.com/microsoft/TypeScript/issues/37487 | ||
*/ | ||
static defaultProps: Props; | ||
constructor(); | ||
private _animated; | ||
get animated(): boolean; | ||
set animated(val: boolean); | ||
readonly created: boolean; | ||
private _pre?; | ||
private _num?; | ||
private _post?; | ||
readonly computedTrend?: number; | ||
readonly startingPos?: number | null; | ||
readonly computedAnimated: boolean; | ||
private _data?; | ||
manual: boolean; | ||
set data(data: Data | undefined); | ||
willUpdate(): void; | ||
private _abortAnimationsFinish?; | ||
didUpdate(): void; | ||
} |
@@ -1,10 +0,1 @@ | ||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("esm-env"),g=(n,t,e)=>{const i=document.createElement(n),[s,r]=Array.isArray(t)?[void 0,t]:[t,e];return s&&Object.assign(i,s),r==null||r.forEach(a=>i.appendChild(a)),i},X=(n,t)=>{var e;return t==="left"?n.offsetLeft:(((e=n.offsetParent instanceof HTMLElement?n.offsetParent:null)==null?void 0:e.offsetWidth)??0)-n.offsetWidth-n.offsetLeft},D=n=>n.offsetWidth>0&&n.offsetHeight>0,I=(n,t)=>{v.BROWSER&&customElements.get(n)!==t&&customElements.define(n,t)};function z(n,t,{reverse:e=!1}={}){const i=n.length;for(let s=e?i-1:0;e?s>=0:s<i;e?s--:s++)t(n[s],s)}function Y(n,t,e,i){const s=t.formatToParts(n);e&&s.unshift({type:"prefix",value:e}),i&&s.push({type:"suffix",value:i});const r=[],a=[],o=[],d=[],u={},p=c=>`${c}:${u[c]=(u[c]??-1)+1}`;let y="",h=!1,f=!1;for(const c of s){y+=c.value;const l=c.type==="minusSign"||c.type==="plusSign"?"sign":c.type;l==="integer"?(h=!0,a.push(...c.value.split("").map(R=>({type:l,value:parseInt(R)})))):l==="group"?a.push({type:l,value:c.value}):l==="decimal"?(f=!0,o.push({type:l,value:c.value,key:p(l)})):l==="fraction"?o.push(...c.value.split("").map(R=>({type:l,value:parseInt(R),key:p(l),pos:-1-u[l]}))):(h||f?d:r).push({type:l,value:c.value,key:p(l)})}const T=[];for(let c=a.length-1;c>=0;c--){const l=a[c];T.unshift(l.type==="integer"?{...l,key:p(l.type),pos:u[l.type]}:{...l,key:p(l.type)})}return{pre:r,integer:T,fraction:o,post:d,valueAsString:y,value:typeof n=="string"?parseFloat(n):n}}const q=String.raw,W=String.raw,G=v.BROWSER&&typeof CSS<"u"&&CSS.supports&&CSS.supports("animation-timing-function","linear(1,2)"),K=v.BROWSER&&typeof CSS<"u"&&CSS.supports&&CSS.supports("line-height","mod(1,1)"),$=v.BROWSER&&typeof matchMedia<"u"?matchMedia("(prefers-reduced-motion: reduce)"):null,x="--_number-flow-d-opacity",A="--_number-flow-d-width",C="--_number-flow-dx",U="--_number-flow-d",Z=(()=>{try{return CSS.registerProperty({name:x,syntax:"<number>",inherits:!1,initialValue:"0"}),CSS.registerProperty({name:C,syntax:"<length>",inherits:!0,initialValue:"0px"}),CSS.registerProperty({name:A,syntax:"<number>",inherits:!1,initialValue:"0"}),CSS.registerProperty({name:U,syntax:"<number>",inherits:!0,initialValue:"0"}),!0}catch{return!1}})(),P="var(--number-flow-char-height, 1em)",m="var(--number-flow-mask-height, 0.25em)",E=`calc(${m} / 2)`,k="var(--number-flow-mask-width, 0.5em)",_=`calc(${k} / var(--scale-x))`,w="#000 0, transparent 71%",L=W`:host{display:inline-block;direction:ltr;white-space:nowrap;isolation:isolate;line-height:${P} !important}.number,.number__inner{display:inline-block;transform-origin:left top}:host([data-will-change]) :is(.number,.number__inner,.section,.digit,.digit__num,.symbol){will-change:transform}.number{--scale-x:calc(1 + var(${A}) / var(--width));transform:translateX(var(${C})) scaleX(var(--scale-x));margin:0 calc(-1 * ${k});position:relative;-webkit-mask-image:linear-gradient(to right,transparent 0,#000 ${_},#000 calc(100% - ${_}),transparent ),linear-gradient(to bottom,transparent 0,#000 ${m},#000 calc(100% - ${m}),transparent 100% ),radial-gradient(at bottom right,${w}),radial-gradient(at bottom left,${w}),radial-gradient(at top left,${w}),radial-gradient(at top right,${w});-webkit-mask-size:100% calc(100% - ${m} * 2),calc(100% - ${_} * 2) 100%,${_} ${m},${_} ${m},${_} ${m},${_} ${m};-webkit-mask-position:center,center,top left,top right,bottom right,bottom left;-webkit-mask-repeat:no-repeat}.number__inner{padding:${E} ${k};transform:scaleX(calc(1 / var(--scale-x))) translateX(calc(-1 * var(${C})))}:host > :not(.number){z-index:5}.section,.symbol{display:inline-block;position:relative;isolation:isolate}.section::after{content:'\200b';display:inline-block}.section--justify-left{transform-origin:center left}.section--justify-right{transform-origin:center right}.section__exiting,.symbol__exiting{margin:0 !important;position:absolute !important;z-index:-1}.digit{display:inline-block;position:relative;--c:var(--current) + var(${U})}.digit__num,.number .section::after{padding:${E} 0}.digit__num{display:inline-block;--offset-raw:mod(var(--length) + var(--n) - mod(var(--c),var(--length)),var(--length));--offset:calc( var(--offset-raw) - var(--length) * round(down,var(--offset-raw) / (var(--length) / 2),1) );--y:clamp(-100%,var(--offset) * 100%,100%);transform:translateY(var(--y))}.digit__num:not(.is-current){position:absolute;top:0;left:50%;transform:translateX(-50%) translateY(var(--y))}.digit:not(.is-spinning) .digit__num:not(.is-current){display:none}.symbol__value{display:inline-block;mix-blend-mode:plus-lighter;white-space:pre}.section--justify-left .symbol__exiting{left:0}.section--justify-right .symbol__exiting{right:0}.animate-presence{opacity:calc(1 + var(${x}))}`,J=v.BROWSER?HTMLElement:class{},Q=W`:host{display:inline-block;direction:ltr;white-space:nowrap;line-height:${P} !important}span{display:inline-block}:host([data-will-change]) span{will-change:transform}.number,.digit{padding:${E} 0}.symbol{white-space:pre}`,tt=n=>`<span class="${n.type==="integer"||n.type==="fraction"?"digit":"symbol"}" part="${n.type==="integer"||n.type==="fraction"?`digit ${n.type}-digit`:n.type}">${n.value}</span>`,b=(n,t)=>`<span part="${t}">${n.reduce((e,i)=>e+tt(i),"")}</span>`,et=n=>q`<template shadowroot="open" shadowrootmode="open" | ||
><style> | ||
${Q}</style | ||
>${b(n.pre,"left")}<span part="number" class="number" | ||
>${b(n.integer,"integer")}${b(n.fraction,"fraction")}</span | ||
>${b(n.post,"right")}</template | ||
><span | ||
style="font-kerning: none; display: inline-block; line-height: ${P} !important; padding: ${m} 0;" | ||
>${n.valueAsString}</span | ||
>`,it=(n,t)=>n==null?t:t==null?n:Math.max(n,t),V=K&&G&&Z;let S;class B extends J{constructor(){super(),this.created=!1,this.manual=!1;const{animated:t,...e}=this.constructor.defaultProps;this._animated=this.computedAnimated=t,Object.assign(this,e)}get animated(){return this._animated}set animated(t){var e;this.animated!==t&&(this._animated=t,(e=this.shadowRoot)==null||e.getAnimations().forEach(i=>i.finish()))}set data(t){if(t==null)return;const{pre:e,integer:i,fraction:s,post:r,value:a}=t;if(this.created){const o=this._data;if(this._data=t,this.computedTrend=typeof this.trend=="function"?this.trend(o.value,a):this.trend,this.startingPos=void 0,this.computedTrend&&this.continuous){const d=o.integer.concat(o.fraction).filter(h=>h.type==="integer"||h.type==="fraction"),u=t.integer.concat(t.fraction).filter(h=>h.type==="integer"||h.type==="fraction"),p=d.find(h=>!u.find(f=>f.pos===h.pos&&f.value===h.value)),y=u.find(h=>!d.find(f=>h.pos===f.pos&&h.value===f.value));this.startingPos=it(p==null?void 0:p.pos,y==null?void 0:y.pos)}this.computedAnimated=V&&this._animated&&(!this.respectMotionPreference||!($!=null&&$.matches))&&D(this),this.manual||this.willUpdate(),this._pre.update(e),this._num.update({integer:i,fraction:s}),this._post.update(r),this.manual||this.didUpdate()}else{if(this._data=t,this.attachShadow({mode:"open"}),typeof CSSStyleSheet<"u"&&this.shadowRoot.adoptedStyleSheets)S||(S=new CSSStyleSheet,S.replaceSync(L)),this.shadowRoot.adoptedStyleSheets=[S];else{const o=document.createElement("style");o.textContent=L,this.shadowRoot.appendChild(o)}this._pre=new N(this,e,{justify:"right",part:"left"}),this.shadowRoot.appendChild(this._pre.el),this._num=new st(this,i,s),this.shadowRoot.appendChild(this._num.el),this._post=new N(this,r,{justify:"left",part:"right"}),this.shadowRoot.appendChild(this._post.el)}this.created=!0}willUpdate(){this._pre.willUpdate(),this._num.willUpdate(),this._post.willUpdate()}didUpdate(){if(!this.computedAnimated)return;this._abortAnimationsFinish?this._abortAnimationsFinish.abort():this.dispatchEvent(new Event("animationsstart")),this._pre.didUpdate(),this._num.didUpdate(),this._post.didUpdate();const t=new AbortController;Promise.all(this.shadowRoot.getAnimations().map(e=>e.finished)).then(()=>{t.signal.aborted||(this.dispatchEvent(new Event("animationsfinish")),this._abortAnimationsFinish=void 0)}),this._abortAnimationsFinish=t}}B.defaultProps={transformTiming:{duration:900,easing:"linear(0,.005,.019,.039,.066,.096,.129,.165,.202,.24,.278,.316,.354,.39,.426,.461,.494,.526,.557,.586,.614,.64,.665,.689,.711,.731,.751,.769,.786,.802,.817,.831,.844,.856,.867,.877,.887,.896,.904,.912,.919,.925,.931,.937,.942,.947,.951,.955,.959,.962,.965,.968,.971,.973,.976,.978,.98,.981,.983,.984,.986,.987,.988,.989,.99,.991,.992,.992,.993,.994,.994,.995,.995,.996,.996,.9963,.9967,.9969,.9972,.9975,.9977,.9979,.9981,.9982,.9984,.9985,.9987,.9988,.9989,1)"},spinTiming:void 0,opacityTiming:{duration:450,easing:"ease-out"},animated:!0,trend:(n,t)=>Math.sign(t-n),continuous:!1,respectMotionPreference:!0,digits:void 0};class st{constructor(t,e,i,{className:s,...r}={}){this.flow=t,this._integer=new M(t,e,{justify:"right",part:"integer"}),this._fraction=new M(t,i,{justify:"left",part:"fraction"}),this._inner=g("span",{className:"number__inner"},[this._integer.el,this._fraction.el]),this.el=g("span",{...r,part:"number",className:`number ${s??""}`},[this._inner])}willUpdate(){this._prevWidth=this.el.offsetWidth,this._prevLeft=this.el.getBoundingClientRect().left,this._integer.willUpdate(),this._fraction.willUpdate()}update({integer:t,fraction:e}){this._integer.update(t),this._fraction.update(e)}didUpdate(){const t=this.el.getBoundingClientRect();this._integer.didUpdate(),this._fraction.didUpdate();const e=this._prevLeft-t.left,i=this.el.offsetWidth,s=this._prevWidth-i;this.el.style.setProperty("--width",String(i)),this.el.animate({[C]:[`${e}px`,"0px"],[A]:[s,0]},{...this.flow.transformTiming,composite:"accumulate"})}}class O{constructor(t,e,{justify:i,className:s,...r},a){this.flow=t,this.children=new Map,this.onCharRemove=d=>()=>{this.children.delete(d)},this.justify=i;const o=e.map(d=>this.addChar(d).el);this.el=g("span",{...r,className:`section section--justify-${i} ${s??""}`},a?a(o):o)}addChar(t,{startDigitsAtZero:e=!1,...i}={}){const s=t.type==="integer"||t.type==="fraction"?new H(this,t.type,e?0:t.value,t.pos,{...i,onRemove:this.onCharRemove(t.key)}):new nt(this,t.type,t.value,{...i,onRemove:this.onCharRemove(t.key)});return this.children.set(t.key,s),s}unpop(t){t.el.classList.remove("section__exiting"),t.el.style.top="",t.el.style[this.justify]=""}pop(t){t.forEach(e=>{e.el.style.top=`${e.el.offsetTop}px`,e.el.style[this.justify]=`${X(e.el,this.justify)}px`}),t.forEach(e=>{e.el.classList.add("section__exiting"),e.present=!1})}addNewAndUpdateExisting(t){const e=new Map,i=new Map,s=this.justify==="left",r=s?"prepend":"append";if(z(t,a=>{let o;this.children.has(a.key)?(o=this.children.get(a.key),i.set(a,o),this.unpop(o),o.present=!0):(o=this.addChar(a,{startDigitsAtZero:!0,animateIn:!0}),e.set(a,o)),this.el[r](o.el)},{reverse:s}),this.flow.computedAnimated){const a=this.el.getBoundingClientRect();e.forEach(o=>{o.willUpdate(a)})}e.forEach((a,o)=>{a.update(o.value)}),i.forEach((a,o)=>{a.update(o.value)})}willUpdate(){const t=this.el.getBoundingClientRect();this._prevOffset=t[this.justify],this.children.forEach(e=>e.willUpdate(t))}didUpdate(){const t=this.el.getBoundingClientRect();this.children.forEach(s=>s.didUpdate(t));const e=t[this.justify],i=this._prevOffset-e;i&&this.children.size&&this.el.animate({transform:[`translateX(${i}px)`,"none"]},{...this.flow.transformTiming,composite:"accumulate"})}}class M extends O{update(t){const e=new Map;this.children.forEach((i,s)=>{t.find(r=>r.key===s)||e.set(s,i),this.unpop(i)}),this.addNewAndUpdateExisting(t),e.forEach(i=>{i instanceof H&&i.update(0)}),this.pop(e)}}class N extends O{update(t){const e=new Map;this.children.forEach((i,s)=>{t.find(r=>r.key===s)||e.set(s,i)}),this.pop(e),this.addNewAndUpdateExisting(t)}}class j{constructor(t,e,{onRemove:i,animateIn:s=!1}={}){this.flow=t,this.el=e,this._present=!0,this._remove=()=>{var r;this.el.remove(),(r=this._onRemove)==null||r.call(this)},this.el.classList.add("animate-presence"),this.flow.computedAnimated&&s&&this.el.animate({[x]:[-.9999,0]},{...this.flow.opacityTiming,composite:"accumulate"}),this._onRemove=i}get present(){return this._present}set present(t){if(this._present!==t){if(this._present=t,!this.flow.computedAnimated){t||this._remove();return}this.el.style.setProperty("--_number-flow-d-opacity",t?"0":"-.999"),this.el.animate({[x]:t?[-.9999,0]:[.999,0]},{...this.flow.opacityTiming,composite:"accumulate"}),t?this.flow.removeEventListener("animationsfinish",this._remove):this.flow.addEventListener("animationsfinish",this._remove,{once:!0})}}}class F extends j{constructor(t,e,i,s){super(t.flow,i,s),this.section=t,this.value=e,this.el=i}}class H extends F{constructor(t,e,i,s,r){var u,p;const a=(((p=(u=t.flow.digits)==null?void 0:u[s])==null?void 0:p.max)??9)+1,o=Array.from({length:a}).map((y,h)=>{const f=g("span",{className:`digit__num${h===i?" is-current":""}`},[document.createTextNode(String(h))]);return f.style.setProperty("--n",String(h)),f}),d=g("span",{part:`digit ${e}-digit`,className:"digit"},o);d.style.setProperty("--current",String(i)),d.style.setProperty("--length",String(a)),super(t,i,d,r),this.pos=s,this._onAnimationsFinish=()=>{this.el.classList.remove("is-spinning")},this._numbers=o,this._length=a}willUpdate(t){const e=this.el.getBoundingClientRect();this._prevValue=this.value;const i=e[this.section.justify]-t[this.section.justify],s=e.width/2;this._prevCenter=this.section.justify==="left"?i+s:i-s}update(t){var e,i;(e=this._numbers[this.value])==null||e.classList.remove("is-current"),this.el.style.setProperty("--current",String(t)),(i=this._numbers[t])==null||i.classList.add("is-current"),this.value=t}didUpdate(t){const e=this.el.getBoundingClientRect(),i=e[this.section.justify]-t[this.section.justify],s=e.width/2,r=this.section.justify==="left"?i+s:i-s,a=this._prevCenter-r;a&&this.el.animate({transform:[`translateX(${a}px)`,"none"]},{...this.flow.transformTiming,composite:"accumulate"});const o=this.diff;o&&(this.el.classList.add("is-spinning"),this.el.animate({[U]:[-o,0]},{...this.flow.spinTiming??this.flow.transformTiming,composite:"accumulate"}),this.flow.addEventListener("animationsfinish",this._onAnimationsFinish,{once:!0}))}get diff(){let t=this.flow.computedTrend;const e=this.value-this._prevValue;return!e&&this.flow.startingPos!=null&&this.flow.startingPos>=this.pos?this._length*t:(t||(t=Math.sign(e)),t<0&&this.value>this._prevValue?this.value-this._length-this._prevValue:t>0&&this.value<this._prevValue?this._length-this._prevValue+this.value:e)}}class nt extends F{constructor(t,e,i,s){const r=g("span",{className:"symbol__value",textContent:i});super(t,i,g("span",{part:`symbol ${e}`,className:"symbol"},[r]),s),this.type=e,this._children=new Map,this._onChildRemove=a=>()=>{this._children.delete(a)},this._children.set(i,new j(this.flow,r,{onRemove:this._onChildRemove(i)}))}willUpdate(t){if(this.type==="decimal")return;const e=this.el.getBoundingClientRect();this._prevOffset=e[this.section.justify]-t[this.section.justify]}update(t){if(this.value!==t){const e=this._children.get(this.value);if(e.present=!1,e.el.classList.add("symbol__exiting"),this._children.has(t)){const i=this._children.get(t);i.present=!0,i.el.classList.remove("symbol__exiting")}else{const i=g("span",{className:"symbol__value",textContent:t});this.el.appendChild(i),this._children.set(t,new j(this.flow,i,{animateIn:!0,onRemove:this._onChildRemove(t)}))}}this.value=t}didUpdate(t){if(this.type==="decimal")return;const i=this.el.getBoundingClientRect()[this.section.justify]-t[this.section.justify],s=this._prevOffset-i;s&&this.el.animate({transform:[`translateX(${s}px)`,"none"]},{...this.flow.transformTiming,composite:"accumulate"})}}exports.NumberFlowLite=B;exports.canAnimate=V;exports.define=I;exports.formatToData=Y;exports.prefersReducedMotion=$;exports.renderInnerHTML=et; | ||
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const n=require("./continuous-B1RI4VTB.js");function T(o,h,l,c){const u=h.formatToParts(o);l&&u.unshift({type:"prefix",value:l}),c&&u.push({type:"suffix",value:c});const f=[],i=[],a=[],g=[],r={},s=t=>`${t}:${r[t]=(r[t]??-1)+1}`;let y="",m=!1,v=!1;for(const t of u){y+=t.value;const e=t.type==="minusSign"||t.type==="plusSign"?"sign":t.type;e==="integer"?(m=!0,i.push(...t.value.split("").map(p=>({type:e,value:parseInt(p)})))):e==="group"?i.push({type:e,value:t.value}):e==="decimal"?(v=!0,a.push({type:e,value:t.value,key:s(e)})):e==="fraction"?a.push(...t.value.split("").map(p=>({type:e,value:parseInt(p),key:s(e),pos:-1-r[e]}))):(m||v?g:f).push({type:e,value:t.value,key:s(e)})}const d=[];for(let t=i.length-1;t>=0;t--){const e=i[t];d.unshift(e.type==="integer"?{...e,key:s(e.type),pos:r[e.type]}:{...e,key:s(e.type)})}return{pre:f,integer:d,fraction:a,post:g,valueAsString:y,value:typeof o=="string"?parseFloat(o):o}}exports.Digit=n.Digit;exports.NumberFlowLite=n.NumberFlowLite;exports.canAnimate=n.canAnimate;exports.continuous=n.continuous;exports.define=n.define;exports.prefersReducedMotion=n.prefersReducedMotion;exports.renderInnerHTML=n.renderInnerHTML;exports.formatToData=T; |
@@ -6,3 +6,3 @@ { | ||
}, | ||
"version": "0.4.2", | ||
"version": "0.5.0", | ||
"author": { | ||
@@ -44,2 +44,7 @@ "name": "Maxwell Barvian", | ||
"require": "./dist/index.js" | ||
}, | ||
"./plugins": { | ||
"types": "./dist/plugins/index.d.ts", | ||
"import": "./dist/plugins.mjs", | ||
"require": "./dist/plugins.js" | ||
} | ||
@@ -46,0 +51,0 @@ }, |
Sorry, the diff of this file is not supported yet
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
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
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
48440
21
758
3
1