@numeric-text/core 0.1.0

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/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # @numeric-text/core
2
+
3
+ Framework-agnostic animated numeric text web component
@@ -0,0 +1,57 @@
1
+ type Value = string | number;
2
+ type Transition = {
3
+ /** @default 550 */
4
+ duration: number;
5
+ /** @default "linear(0,.1052,.3155,.532,.7112,.8414,.9265,.9765,1.0023,1.013,1.0151,1.0133,1.01,1.0068,1.0041,1.0022,1.001,1)" */
6
+ easing: string;
7
+ };
8
+ type Trend = -1 | 0 | 1;
9
+ type NumericTextOptions = {
10
+ transition?: Partial<Transition>;
11
+ /** @default 0 */
12
+ trend?: Trend;
13
+ /** @default true */
14
+ respectMotionPreference?: boolean;
15
+ };
16
+ type NumericTextProps = NumericTextOptions & {
17
+ value: Value;
18
+ /** @default true */
19
+ animated?: boolean;
20
+ };
21
+
22
+ declare const BROWSER: boolean;
23
+ declare const ServerSafeHTMLElement: {
24
+ new (): HTMLElement;
25
+ prototype: HTMLElement;
26
+ };
27
+
28
+ declare class NumericText extends ServerSafeHTMLElement {
29
+ private _prefix;
30
+ private _middle;
31
+ private _suffix;
32
+ private _chars;
33
+ private _exitingChars;
34
+ private _isRTL;
35
+ private _value;
36
+ private _prevValue;
37
+ transition: Transition;
38
+ trend: Trend;
39
+ respectMotionPreference: boolean;
40
+ constructor();
41
+ connectedCallback(): void;
42
+ get value(): Value;
43
+ set value(v: Value);
44
+ update(v: Value, withAnimation?: boolean): void;
45
+ setOptions(opts: NumericTextOptions): void;
46
+ private _render;
47
+ private _getStagger;
48
+ private _getEdgeDx;
49
+ private _animateChar;
50
+ }
51
+ declare global {
52
+ interface HTMLElementTagNameMap {
53
+ 'numeric-text': NumericText;
54
+ }
55
+ }
56
+
57
+ export { BROWSER, NumericText, type NumericTextOptions, type NumericTextProps, type Transition, type Trend, type Value };
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ var g={y:.35,scale:.6,blur:.1,rotate:2,stagger:.3},b={duration:550,easing:"linear(0,.1052,.3155,.532,.7112,.8414,.9265,.9765,1.0023,1.013,1.0151,1.0133,1.01,1.0068,1.0041,1.0022,1.001,1)"},O=`
2
+ :host {
3
+ position: relative;
4
+ display: inline-flex;
5
+ white-space: nowrap !important; /* no multi-line support */
6
+ isolation: isolate;
7
+ }
8
+ span {
9
+ margin: 0 !important;
10
+ padding: 0 !important;
11
+ transform-origin: center;
12
+ }
13
+ [inert] {
14
+ position: absolute !important;
15
+ display: inline-flex !important;
16
+ will-change: transform;
17
+ z-index: 0;
18
+ }
19
+ .section {
20
+ position: relative !important;
21
+ display: inline-flex !important;
22
+ will-change: transform;
23
+ z-index: 1;
24
+ }
25
+ .char {
26
+ display: inline-block !important;
27
+ white-space: pre !important;
28
+ }`;var _=typeof window<"u",P=_?HTMLElement:class{},I=()=>_&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,d=(a,t,i)=>{let r=document.createElement(a);return r.setAttribute("aria-hidden","true"),t&&(r.className=t),i&&(r.textContent=i),r},x=a=>a.getBoundingClientRect(),C=a=>{for(let t of a.getAnimations())t.cancel();},v=(a,t,i)=>{t&&(C(a),a.animate({transform:[`translateX(${t}px)`,""]},{duration:i.duration,easing:i.easing,fill:"both"}));},W=new Intl.Segmenter(void 0,{granularity:"grapheme"}),Y=a=>{let t=[];for(let i of W.segment(a))t.push(i.segment===" "?"\xA0":i.segment);return t},V=(a,t)=>{let i=Y(t),r=a.length,l=i.length,s=0;for(;s<r&&s<l&&a[s].textContent===i[s];)s++;let c=0,h=Math.min(r-s,l-s);for(;c<h&&a[r-1-c].textContent===i[l-1-c];)c++;let f=i.slice(s,l-c);return {prefixCount:s,suffixCount:c,middleLabels:f}};var M;_&&(M=new CSSStyleSheet,M.replaceSync(O));var R=class extends P{_prefix;_middle;_suffix;_chars=[];_exitingChars=[];_isRTL=false;_value="";_prevValue="";transition=b;trend=0;respectMotionPreference=true;constructor(){super();let t=this.attachShadow({mode:"open"});M&&(t.adoptedStyleSheets=[M]),this._prefix=d("span","section"),this._middle=d("span","section"),this._suffix=d("span","section"),t.append(this._prefix,this._middle,this._suffix);}connectedCallback(){this._isRTL=getComputedStyle(this).direction==="rtl",this._render(false);}get value(){return this._value}set value(t){this.update(t,false);}update(t,i=true){if(t=t+"",t===this._value)return;this._prevValue=this._value,this._value=t;let r=i&&!(this.respectMotionPreference&&I());this._render(r);}setOptions(t){t.transition&&(this.transition={...t.transition,...b}),typeof t.trend=="number"&&(this.trend=t.trend),typeof t.respectMotionPreference=="boolean"&&(this.respectMotionPreference=t.respectMotionPreference);}_render(t){let{prefixCount:i,suffixCount:r,middleLabels:l}=V(this._chars,this._value),s=l.length,c=this._chars.length-r,h=i+s+r;if(!t){let e=new Array(h),o=i+s;for(let n=0;n<i;n++)e[n]=this._chars[n];for(let n=0;n<s;n++)e[i+n]=d("span","char",l[n]);for(let n=0;n<r;n++)e[o+n]=this._chars[c+n];for(let n=i;n<c;n++)this._chars[n].remove();this._prefix.replaceChildren(...e.slice(0,i)),this._middle.replaceChildren(...e.slice(i,o)),this._suffix.replaceChildren(...e.slice(o)),this._chars=e;return}let f=this.trend;if(!f){let e=parseFloat(this._value),o=parseFloat(this._prevValue);f=!isNaN(e)&&!isNaN(o)?e>o?1:-1:1;}let S=x(this._prefix),L=x(this._middle),A=x(this._suffix),y=0;if(i<c){let e=this._chars[i],o=e.parentElement,n=o===this._prefix?S:o===this._suffix?A:L;this._isRTL?y=n.left+e.offsetLeft+e.offsetWidth:y=n.left+e.offsetLeft;}let m=new Array(h),p=[];for(let e=0;e<i;e++)m[e]=this._chars[e];for(let e=i;e<c;e++)p.push(this._chars[e]);let T=new Array(s);for(let e=0;e<s;e++){let o=d("span","char",l[e]);T[e]=o,m[i+e]=o;}let H=i+s;for(let e=0;e<r;e++)m[H+e]=this._chars[c+e];if(p.length){let e=d("span");e.toggleAttribute("inert",true);for(let u of p)e.appendChild(u);let o=[e,y];this._exitingChars.push(o),this.shadowRoot.appendChild(e);let n=p.length,G=this._getStagger(p);for(let u=0;u<p.length;u++){let N=p[u];this._animateChar(N,true,f,u*G,()=>{if(N.remove(),--n===0){e.remove();let D=this._exitingChars.indexOf(o);D!==-1&&this._exitingChars.splice(D,1);}});}}this._prefix.replaceChildren(...m.slice(0,i)),this._middle.replaceChildren(...T),this._suffix.replaceChildren(...m.slice(H)),this._chars=m,C(this._prefix),C(this._suffix);let w=x(this._prefix),$=x(this._suffix),k=this._isRTL?w.right:w.left;for(let[e,o]of this._exitingChars){let n=o-k;e.style.transform=`translateX(${n}px)`;}let X=this._getStagger(T);for(let e=0;e<s;e++)this._animateChar(T[e],false,f,e*X);let B=this._getEdgeDx(S,w,L,true),F=this._getEdgeDx(A,$,L,false);v(this._prefix,B,this.transition),v(this._suffix,F,this.transition);}_getStagger(t){let i=0;for(let r=0;r<t.length;r++)t[r].textContent!=="\xA0"&&i++;return this.transition.duration*g.stagger/(i||1)}_getEdgeDx(t,i,r,l){return this._isRTL===l?(t.width?t.right:r.right)-i.right:(t.width?t.left:r.left)-i.left}_animateChar(t,i,r,l,s){if(t.textContent==="\xA0"){i&&s&&setTimeout(s,this.transition.duration+l);return}let h=`translateY(${(i?-1:1)*r*g.y}em) scale(${g.scale}) rotateZ(${g.rotate}deg)`,f=`blur(${g.blur}em)`,S=t.animate({opacity:i?0:[0,1],transform:i?h:[h,""],filter:i?f:[f,""]},{duration:this.transition.duration,easing:this.transition.easing,fill:"both",delay:l});s&&(S.onfinish=s);}};_&&!customElements.get("numeric-text")&&customElements.define("numeric-text",R);export{_ as BROWSER,R as NumericText};//# sourceMappingURL=index.js.map
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/const.ts","../src/helpers.ts","../src/index.ts"],"names":["CONFIG","DEFAULT_TRANSITION","STYLES","BROWSER","ServerSafeHTMLElement","isReducedMotion","createEl","tag","className","text","el","getRect","cancelAnim","a","flip","dx","transition","segmenter","splitGraphemes","value","result","item","diff","prev","newValue","curr","lenOld","lenNew","start","end","maxSuffix","middleLabels","styleSheet","NumericText","shadow","v","withAnimation","shouldAnimate","opts","animate","prefixCount","suffixCount","newMiddleLen","oldSuffixStart","totalLen","nextChars","newSuffixStart","i","trend","c","p","oldPrefixRect","oldMiddleRect","oldSuffixRect","exitingX","exitingAnchor","parent","parentRect","exitingNodes","newMiddleNodes","group","node","newExitEntry","active","exitStagger","idx","newPrefixRect","newSuffixRect","exitingEdge","x","newX","enterStagger","pDx","sDx","nodes","animatingCount","oldRect","newRect","oldMiddle","isPrefix","isOut","delay","onFinish","transform","filter","anim"],"mappings":"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","file":"index.js","sourcesContent":["import type { Transition } from './types';\n\nexport const SPACE = '\\u00A0';\nexport const CONFIG = {\n y: 0.35,\n scale: 0.6,\n blur: 0.1,\n rotate: 2,\n stagger: 0.3,\n};\nexport const DEFAULT_TRANSITION: Transition = {\n duration: 550,\n easing:\n 'linear(0,.1052,.3155,.532,.7112,.8414,.9265,.9765,1.0023,1.013,1.0151,1.0133,1.01,1.0068,1.0041,1.0022,1.001,1)',\n};\nexport const STYLES = `\n :host {\n position: relative;\n display: inline-flex;\n white-space: nowrap !important; /* no multi-line support */\n isolation: isolate;\n }\n span {\n margin: 0 !important;\n padding: 0 !important;\n transform-origin: center;\n }\n [inert] {\n position: absolute !important;\n display: inline-flex !important;\n will-change: transform;\n z-index: 0;\n }\n .section {\n position: relative !important;\n display: inline-flex !important;\n will-change: transform;\n z-index: 1;\n }\n .char {\n display: inline-block !important;\n white-space: pre !important;\n }`;\n","import type { Transition } from './types';\nimport { SPACE } from './const';\n\nexport const BROWSER = typeof window !== 'undefined';\nexport const ServerSafeHTMLElement = BROWSER ? HTMLElement : (class {} as unknown as typeof HTMLElement);\nexport const isReducedMotion = () => {\n return BROWSER && window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n};\n\nexport const createEl = <K extends keyof HTMLElementTagNameMap>(tag: K, className?: string, text?: string) => {\n const el = document.createElement(tag);\n el.setAttribute('aria-hidden', 'true');\n if (className) el.className = className;\n if (text) el.textContent = text;\n return el;\n};\n\nexport const getRect = (el: HTMLElement) => el.getBoundingClientRect();\n\nexport const cancelAnim = (el: HTMLElement) => {\n for (const a of el.getAnimations()) a.cancel();\n};\n\nexport const flip = (el: HTMLElement, dx: number, transition: Transition) => {\n if (!dx) return;\n cancelAnim(el);\n el.animate(\n { transform: [`translateX(${dx}px)`, ''] },\n {\n duration: transition.duration,\n easing: transition.easing,\n fill: 'both',\n },\n );\n};\n\nconst segmenter = new Intl.Segmenter(undefined, { granularity: 'grapheme' });\nconst splitGraphemes = (value: string): string[] => {\n const result: string[] = [];\n for (const item of segmenter.segment(value)) {\n result.push(item.segment === ' ' ? SPACE : item.segment);\n }\n return result;\n};\n\nexport const diff = (prev: HTMLElement[], newValue: string) => {\n const curr = splitGraphemes(newValue);\n\n const lenOld = prev.length;\n const lenNew = curr.length;\n\n // 1. PREFIX SCAN\n let start = 0;\n while (start < lenOld && start < lenNew && prev[start].textContent === curr[start]) {\n start++;\n }\n\n // 2. SUFFIX SCAN\n let end = 0;\n const maxSuffix = Math.min(lenOld - start, lenNew - start);\n while (end < maxSuffix) {\n if (prev[lenOld - 1 - end].textContent !== curr[lenNew - 1 - end]) break;\n end++;\n }\n\n // 3. MIDDLE EXTRACTION\n const middleLabels = curr.slice(start, lenNew - end);\n\n return { prefixCount: start, suffixCount: end, middleLabels };\n};\n","import type { NumericTextOptions, Transition, Trend, Value } from './types';\nimport { ServerSafeHTMLElement, createEl, getRect, cancelAnim, BROWSER, flip, isReducedMotion, diff } from './helpers';\nimport { CONFIG, DEFAULT_TRANSITION, SPACE, STYLES } from './const';\n\nlet styleSheet: CSSStyleSheet;\nif (BROWSER) {\n styleSheet = new CSSStyleSheet();\n styleSheet.replaceSync(STYLES);\n}\n\nclass NumericText extends ServerSafeHTMLElement {\n private _prefix: HTMLElement;\n private _middle: HTMLElement;\n private _suffix: HTMLElement;\n\n private _chars: HTMLElement[] = [];\n private _exitingChars: [el: HTMLElement, left: number][] = [];\n\n private _isRTL: boolean = false;\n\n private _value: string = '';\n private _prevValue: string = '';\n\n public transition: Transition = DEFAULT_TRANSITION;\n public trend: Trend = 0;\n public respectMotionPreference: boolean = true;\n\n constructor() {\n super();\n\n const shadow = this.attachShadow({ mode: 'open' });\n if (styleSheet) shadow.adoptedStyleSheets = [styleSheet];\n\n this._prefix = createEl('span', 'section');\n this._middle = createEl('span', 'section');\n this._suffix = createEl('span', 'section');\n\n shadow.append(this._prefix, this._middle, this._suffix);\n }\n\n connectedCallback() {\n this._isRTL = getComputedStyle(this).direction === 'rtl';\n this._render(false);\n }\n\n get value() {\n return this._value;\n }\n set value(v: Value) {\n this.update(v, false);\n }\n\n update(v: Value, withAnimation = true) {\n v = v + '';\n if (v === this._value) return;\n\n this._prevValue = this._value;\n this._value = v;\n\n const shouldAnimate = withAnimation && !(this.respectMotionPreference && isReducedMotion());\n this._render(shouldAnimate);\n }\n\n setOptions(opts: NumericTextOptions) {\n if (opts.transition) this.transition = { ...opts.transition, ...DEFAULT_TRANSITION };\n if (typeof opts.trend === 'number') this.trend = opts.trend;\n if (typeof opts.respectMotionPreference === 'boolean') this.respectMotionPreference = opts.respectMotionPreference;\n }\n\n private _render(animate: boolean) {\n const { prefixCount, suffixCount, middleLabels } = diff(this._chars, this._value);\n\n const newMiddleLen = middleLabels.length;\n const oldSuffixStart = this._chars.length - suffixCount;\n const totalLen = prefixCount + newMiddleLen + suffixCount;\n\n if (!animate) {\n const nextChars = new Array(totalLen);\n const newSuffixStart = prefixCount + newMiddleLen;\n\n for (let i = 0; i < prefixCount; i++) nextChars[i] = this._chars[i];\n for (let i = 0; i < newMiddleLen; i++) {\n nextChars[prefixCount + i] = createEl('span', 'char', middleLabels[i]);\n }\n for (let i = 0; i < suffixCount; i++) {\n nextChars[newSuffixStart + i] = this._chars[oldSuffixStart + i];\n }\n\n for (let i = prefixCount; i < oldSuffixStart; i++) {\n this._chars[i].remove();\n }\n\n this._prefix.replaceChildren(...nextChars.slice(0, prefixCount));\n this._middle.replaceChildren(...nextChars.slice(prefixCount, newSuffixStart));\n this._suffix.replaceChildren(...nextChars.slice(newSuffixStart));\n\n this._chars = nextChars;\n return;\n }\n\n let trend = this.trend;\n if (!trend) {\n const c = parseFloat(this._value);\n const p = parseFloat(this._prevValue);\n trend = !isNaN(c) && !isNaN(p) ? (c > p ? 1 : -1) : 1;\n }\n\n const oldPrefixRect = getRect(this._prefix);\n const oldMiddleRect = getRect(this._middle);\n const oldSuffixRect = getRect(this._suffix);\n\n let exitingX = 0;\n if (prefixCount < oldSuffixStart) {\n const exitingAnchor = this._chars[prefixCount];\n const parent = exitingAnchor.parentElement!;\n const parentRect =\n parent === this._prefix ? oldPrefixRect : parent === this._suffix ? oldSuffixRect : oldMiddleRect;\n\n if (this._isRTL) exitingX = parentRect.left + exitingAnchor.offsetLeft + exitingAnchor.offsetWidth;\n else exitingX = parentRect.left + exitingAnchor.offsetLeft;\n }\n\n const nextChars = new Array(totalLen);\n const exitingNodes = [];\n for (let i = 0; i < prefixCount; i++) nextChars[i] = this._chars[i];\n for (let i = prefixCount; i < oldSuffixStart; i++) {\n exitingNodes.push(this._chars[i]);\n }\n\n const newMiddleNodes = new Array(newMiddleLen);\n for (let i = 0; i < newMiddleLen; i++) {\n const el = createEl('span', 'char', middleLabels[i]);\n newMiddleNodes[i] = el;\n nextChars[prefixCount + i] = el;\n }\n\n const newSuffixStart = prefixCount + newMiddleLen;\n for (let i = 0; i < suffixCount; i++) {\n nextChars[newSuffixStart + i] = this._chars[oldSuffixStart + i];\n }\n\n if (exitingNodes.length) {\n const group = createEl('span');\n group.toggleAttribute('inert', true);\n\n for (const node of exitingNodes) group.appendChild(node);\n\n const newExitEntry = [group, exitingX] as [HTMLElement, number];\n this._exitingChars.push(newExitEntry);\n this.shadowRoot!.appendChild(group);\n\n let active = exitingNodes.length;\n const exitStagger = this._getStagger(exitingNodes);\n for (let i = 0; i < exitingNodes.length; i++) {\n const node = exitingNodes[i];\n this._animateChar(node, true, trend, i * exitStagger, () => {\n node.remove();\n if (--active === 0) {\n group.remove();\n const idx = this._exitingChars.indexOf(newExitEntry!);\n if (idx !== -1) this._exitingChars.splice(idx, 1);\n }\n });\n }\n }\n\n this._prefix.replaceChildren(...nextChars.slice(0, prefixCount));\n this._middle.replaceChildren(...newMiddleNodes);\n this._suffix.replaceChildren(...nextChars.slice(newSuffixStart));\n this._chars = nextChars;\n\n cancelAnim(this._prefix);\n cancelAnim(this._suffix);\n const newPrefixRect = getRect(this._prefix);\n const newSuffixRect = getRect(this._suffix);\n\n const exitingEdge = this._isRTL ? newPrefixRect.right : newPrefixRect.left;\n for (const [el, x] of this._exitingChars) {\n const newX = x - exitingEdge;\n el.style.transform = `translateX(${newX}px)`;\n }\n\n const enterStagger = this._getStagger(newMiddleNodes);\n for (let i = 0; i < newMiddleLen; i++) {\n this._animateChar(newMiddleNodes[i], false, trend, i * enterStagger);\n }\n\n const pDx = this._getEdgeDx(oldPrefixRect, newPrefixRect, oldMiddleRect, true);\n const sDx = this._getEdgeDx(oldSuffixRect, newSuffixRect, oldMiddleRect, false);\n\n flip(this._prefix, pDx, this.transition);\n flip(this._suffix, sDx, this.transition);\n }\n\n private _getStagger(nodes: HTMLElement[]) {\n let animatingCount = 0;\n for (let i = 0; i < nodes.length; i++) {\n if (nodes[i].textContent !== SPACE) {\n animatingCount++;\n }\n }\n\n return (this.transition.duration * CONFIG.stagger) / (animatingCount || 1);\n }\n\n private _getEdgeDx(oldRect: DOMRect, newRect: DOMRect, oldMiddle: DOMRect, isPrefix: boolean) {\n if (this._isRTL === isPrefix) {\n const oldEdge = oldRect.width ? oldRect.right : oldMiddle.right;\n return oldEdge - newRect.right;\n } else {\n const oldEdge = oldRect.width ? oldRect.left : oldMiddle.left;\n return oldEdge - newRect.left;\n }\n }\n\n private _animateChar(el: HTMLElement, isOut: boolean, trend: number, delay: number, onFinish?: () => void) {\n if (el.textContent === SPACE) {\n if (isOut && onFinish) setTimeout(onFinish, this.transition.duration + delay);\n return;\n }\n\n const m = isOut ? -1 : 1;\n const transform = `translateY(${m * trend * CONFIG.y}em) scale(${CONFIG.scale}) rotateZ(${CONFIG.rotate}deg)`;\n const filter = `blur(${CONFIG.blur}em)`;\n\n const anim = el.animate(\n {\n opacity: isOut ? 0 : [0, 1],\n transform: isOut ? transform : [transform, ''],\n filter: isOut ? filter : [filter, ''],\n },\n {\n duration: this.transition.duration,\n easing: this.transition.easing,\n fill: 'both',\n delay,\n },\n );\n if (onFinish) anim.onfinish = onFinish;\n }\n}\n\nif (BROWSER && !customElements.get('numeric-text')) {\n customElements.define('numeric-text', NumericText);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'numeric-text': NumericText;\n }\n}\n\nexport type * from './types';\nexport { NumericText, BROWSER };\n"]}
package/dist/ssr.css ADDED
@@ -0,0 +1,4 @@
1
+ numeric-text:not(:defined) {
2
+ display: inline-flex;
3
+ white-space: nowrap !important;
4
+ }
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@numeric-text/core",
3
+ "type": "module",
4
+ "version": "0.1.0",
5
+ "description": "Framework-agnostic animated numeric text web component",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/shizukushq/numeric-text.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/shizukushq/numeric-text/issues"
13
+ },
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "module": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js"
23
+ },
24
+ "./ssr.css": "./dist/ssr.css"
25
+ },
26
+ "files": [
27
+ "dist",
28
+ "README.md"
29
+ ],
30
+ "scripts": {
31
+ "build": "tsup && cp src/ssr.css dist/ssr.css",
32
+ "dev": "tsup --watch"
33
+ },
34
+ "devDependencies": {
35
+ "tsup": "^8.5.1",
36
+ "typescript": "^5"
37
+ }
38
+ }