{"_id":"@agencecinq/spinbutton","_rev":"9-4afe4f2bc6df7030e03e72e9ba73a90e","name":"@agencecinq/spinbutton","dist-tags":{"latest":"4.0.0"},"versions":{"1.0.0":{"name":"@agencecinq/spinbutton","version":"1.0.0","author":{"url":"https://agencecinq.com","name":"Jérémy Levron","email":"jeremy@agencecinq.com"},"license":"MIT","_id":"@agencecinq/spinbutton@1.0.0","maintainers":[{"name":"19h47","email":"jeremylevron@19h47.fr"}],"homepage":"https://github.com/agencecinq/shopify#readme","bugs":{"url":"https://github.com/agencecinq/shopify/issues"},"dist":{"shasum":"e3277c877fd2936c1cce07ffebab9997a7a3bcfe","tarball":"https://registry.npmjs.org/@agencecinq/spinbutton/-/spinbutton-1.0.0.tgz","fileCount":7,"integrity":"sha512-AquWFhey1koevJfhoLU1Yw85p9heA7dgiCqkZwmoM2kArc5mcDpcCw2XtC3XYg8fs6oF/HYu0IWDsDUDBj9VRQ==","signatures":[{"sig":"MEYCIQC0ttnQFJ0QYqOIwN8gIp+bK9/UAXYmzr6m13cXzo5HDQIhAPKkSGj4ucaxld36VQqc0/9+1OgccvJrQ8xn1B3R1HKy","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":16797},"main":"./dist/index.js","type":"module","_from":"file:agencecinq-spinbutton-1.0.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","build":"vite build"},"_npmUser":{"name":"19h47","email":"jeremylevron@19h47.fr"},"_resolved":"/private/var/folders/vt/kpbgrh4d7k14zvxmcm01bfxh0000gn/T/032017aef12df275f266f94ec9ba398f/agencecinq-spinbutton-1.0.0.tgz","_integrity":"sha512-AquWFhey1koevJfhoLU1Yw85p9heA7dgiCqkZwmoM2kArc5mcDpcCw2XtC3XYg8fs6oF/HYu0IWDsDUDBj9VRQ==","repository":{"url":"git+https://github.com/agencecinq/shopify.git","type":"git","directory":"packages/spinbutton"},"_npmVersion":"11.12.1","description":"Accessible, WAI-ARIA spinbutton as a lightweight Web Component.","directories":{},"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","vite-plugin-dts":"^4.5.4","@agencecinq/utils":"5.0.0"},"peerDependencies":{"@agencecinq/utils":"*"},"_npmOperationalInternal":{"tmp":"tmp/spinbutton_1.0.0_1777372827433_0.576205127627136","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@agencecinq/spinbutton","version":"1.0.1","author":{"url":"https://agencecinq.com","name":"Jérémy Levron","email":"jeremy@agencecinq.com"},"license":"MIT","_id":"@agencecinq/spinbutton@1.0.1","maintainers":[{"name":"19h47","email":"jeremylevron@19h47.fr"}],"homepage":"https://github.com/agencecinq/shopify#readme","bugs":{"url":"https://github.com/agencecinq/shopify/issues"},"dist":{"shasum":"7e4ff77a1a02c4bf4acb8d343c19e7f69b6bf1e8","tarball":"https://registry.npmjs.org/@agencecinq/spinbutton/-/spinbutton-1.0.1.tgz","fileCount":7,"integrity":"sha512-ZQf2S5LTYeLoIT++qmzfzwFQbp6socSmcMgsjeR0FnNjERNrQuExL4eT9dHtjCFtg/SY4r28Dpqjcp6RorYPBQ==","signatures":[{"sig":"MEUCIF+f4gxIrri0BKs9nn2cqhGJj0PbWDcAeAvBpIKoaxRYAiEAoRAx+iOJ8dZJaMv/jAOVLqDaOW14uHYdalAWcb3xM9E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":16800},"main":"./dist/index.js","type":"module","_from":"file:agencecinq-spinbutton-1.0.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","build":"vite build"},"_npmUser":{"name":"19h47","email":"jeremylevron@19h47.fr"},"_resolved":"/private/var/folders/vt/kpbgrh4d7k14zvxmcm01bfxh0000gn/T/65faf94228eee6549c1772792920b194/agencecinq-spinbutton-1.0.1.tgz","_integrity":"sha512-ZQf2S5LTYeLoIT++qmzfzwFQbp6socSmcMgsjeR0FnNjERNrQuExL4eT9dHtjCFtg/SY4r28Dpqjcp6RorYPBQ==","repository":{"url":"git+https://github.com/agencecinq/shopify.git","type":"git","directory":"packages/spinbutton"},"_npmVersion":"11.12.1","description":"Accessible, WAI-ARIA spinbutton as a lightweight Web Component.","directories":{},"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","vite-plugin-dts":"^4.5.4","@agencecinq/utils":"5.0.1"},"peerDependencies":{"@agencecinq/utils":"*"},"_npmOperationalInternal":{"tmp":"tmp/spinbutton_1.0.1_1777443125368_0.09923032745366966","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@agencecinq/spinbutton","version":"1.0.2","author":{"url":"https://agencecinq.com","name":"Jérémy Levron","email":"jeremy@agencecinq.com"},"license":"MIT","_id":"@agencecinq/spinbutton@1.0.2","maintainers":[{"name":"19h47","email":"jeremylevron@19h47.fr"}],"homepage":"https://github.com/agencecinq/shopify#readme","bugs":{"url":"https://github.com/agencecinq/shopify/issues"},"dist":{"shasum":"abaa8c71c2eeac4aa92475368d075b2b7dbfe1fd","tarball":"https://registry.npmjs.org/@agencecinq/spinbutton/-/spinbutton-1.0.2.tgz","fileCount":7,"integrity":"sha512-atqd5NDZQBh0YSZyrCDK2CMTh3CsqI9t/tVgwv7SdB8hPZFbHVXv9PLqwq7PekgMoAAu2ERpxKvJrTBpIMq+LQ==","signatures":[{"sig":"MEYCIQD2QReZtxZ8wum5pTrN1xffrP28JKMyAWL/BChi8W54rAIhALQZlbHSTX0FMp6aezvZJZta1ZVT2fCQpc8asfdcCKgp","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":16953},"main":"./dist/index.js","type":"module","_from":"file:agencecinq-spinbutton-1.0.2.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","build":"vite build"},"_npmUser":{"name":"19h47","email":"jeremylevron@19h47.fr"},"_resolved":"/private/var/folders/vt/kpbgrh4d7k14zvxmcm01bfxh0000gn/T/026e46368cfe3d00b203bb033db9b99a/agencecinq-spinbutton-1.0.2.tgz","_integrity":"sha512-atqd5NDZQBh0YSZyrCDK2CMTh3CsqI9t/tVgwv7SdB8hPZFbHVXv9PLqwq7PekgMoAAu2ERpxKvJrTBpIMq+LQ==","repository":{"url":"git+https://github.com/agencecinq/shopify.git","type":"git","directory":"packages/spinbutton"},"_npmVersion":"11.14.1","description":"Accessible, WAI-ARIA spinbutton as a lightweight Web Component.","directories":{},"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","vite-plugin-dts":"^4.5.4","@agencecinq/utils":"5.0.1"},"peerDependencies":{"@agencecinq/utils":"*"},"_npmOperationalInternal":{"tmp":"tmp/spinbutton_1.0.2_1779349407843_0.3998561514473622","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@agencecinq/spinbutton","version":"1.0.3","author":{"url":"https://agencecinq.com","name":"Jérémy Levron","email":"jeremy@agencecinq.com"},"license":"MIT","_id":"@agencecinq/spinbutton@1.0.3","maintainers":[{"name":"19h47","email":"jeremylevron@19h47.fr"}],"homepage":"https://github.com/agencecinq/shopify#readme","bugs":{"url":"https://github.com/agencecinq/shopify/issues"},"dist":{"shasum":"6e117f178aeb65993bac62d067adee0959ba89eb","tarball":"https://registry.npmjs.org/@agencecinq/spinbutton/-/spinbutton-1.0.3.tgz","fileCount":7,"integrity":"sha512-NW2vv3qZGpQyg/Rj5Ff+WM6PmELfxWRQ/iM4L2qIjE49RSd0xwgoZ7HVw/JlsEJJAu0TkK8fGwmH2IW8PVrBng==","signatures":[{"sig":"MEYCIQD5ilPACtz6afKvGdOLFHHVX5ePIxJlSO0zna7nymYy/wIhANToIxUk/nwl5BUJDISiG4tUMKa/Ic0koTObGXUOi//5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17764},"main":"./dist/index.js","type":"module","_from":"file:agencecinq-spinbutton-1.0.3.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","build":"vite build"},"_npmUser":{"name":"19h47","email":"jeremylevron@19h47.fr"},"_resolved":"/private/var/folders/vt/kpbgrh4d7k14zvxmcm01bfxh0000gn/T/f26b71af06b052925c773ef404990f42/agencecinq-spinbutton-1.0.3.tgz","_integrity":"sha512-NW2vv3qZGpQyg/Rj5Ff+WM6PmELfxWRQ/iM4L2qIjE49RSd0xwgoZ7HVw/JlsEJJAu0TkK8fGwmH2IW8PVrBng==","repository":{"url":"git+https://github.com/agencecinq/shopify.git","type":"git","directory":"packages/spinbutton"},"_npmVersion":"11.18.0","description":"Accessible, WAI-ARIA spinbutton as a lightweight Web Component.","directories":{},"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.1.4","vite-plugin-dts":"^5.0.3","@agencecinq/utils":"5.1.0"},"peerDependencies":{"@agencecinq/utils":"*"},"_npmOperationalInternal":{"tmp":"tmp/spinbutton_1.0.3_1784557096719_0.10199938508304629","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@agencecinq/spinbutton","version":"1.0.4","author":{"url":"https://agencecinq.com","name":"Jérémy Levron","email":"jeremy@agencecinq.com"},"license":"MIT","_id":"@agencecinq/spinbutton@1.0.4","maintainers":[{"name":"19h47","email":"jeremylevron@19h47.fr"}],"homepage":"https://github.com/agencecinq/shopify#readme","bugs":{"url":"https://github.com/agencecinq/shopify/issues"},"dist":{"shasum":"01ae43da96536fd33a8f52a6568a0980f41815b3","tarball":"https://registry.npmjs.org/@agencecinq/spinbutton/-/spinbutton-1.0.4.tgz","fileCount":7,"integrity":"sha512-wjM70gDCAqXUtX4VwUVEd5PLo0eQqtWbQfqDYaOc/rhsrLM96/au8eqBcM9FY7feP7BcwpF3Ld+l97FpEggIhg==","signatures":[{"sig":"MEUCIQCoEW5yvtsoN9HdEbmM5qNk288K1nc/jnfG+HBsukYgOwIgYLG4PJ6m0w+6oXUt4W9TbO2Jyl0uPkWrsfbPhFOy52s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17764},"main":"./dist/index.js","type":"module","_from":"file:agencecinq-spinbutton-1.0.4.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","build":"vite build"},"_npmUser":{"name":"19h47","email":"jeremylevron@19h47.fr"},"_resolved":"/private/var/folders/vt/kpbgrh4d7k14zvxmcm01bfxh0000gn/T/c19620a549de87b57c79c6e0b24cfa5d/agencecinq-spinbutton-1.0.4.tgz","_integrity":"sha512-wjM70gDCAqXUtX4VwUVEd5PLo0eQqtWbQfqDYaOc/rhsrLM96/au8eqBcM9FY7feP7BcwpF3Ld+l97FpEggIhg==","repository":{"url":"git+https://github.com/agencecinq/shopify.git","type":"git","directory":"packages/spinbutton"},"_npmVersion":"11.18.0","description":"Accessible, WAI-ARIA spinbutton as a lightweight Web Component.","directories":{},"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.1.4","vite-plugin-dts":"^5.0.3","@agencecinq/utils":"5.2.0"},"peerDependencies":{"@agencecinq/utils":"*"},"_npmOperationalInternal":{"tmp":"tmp/spinbutton_1.0.4_1784619145047_0.4601206422483466","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@agencecinq/spinbutton","version":"2.0.0","author":{"url":"https://agencecinq.com","name":"Jérémy Levron","email":"jeremy@agencecinq.com"},"license":"MIT","_id":"@agencecinq/spinbutton@2.0.0","maintainers":[{"name":"19h47","email":"jeremylevron@19h47.fr"}],"homepage":"https://github.com/agencecinq/shopify#readme","bugs":{"url":"https://github.com/agencecinq/shopify/issues"},"dist":{"shasum":"6d32f2e321083e015fdf7dd0b697a560db134d0a","tarball":"https://registry.npmjs.org/@agencecinq/spinbutton/-/spinbutton-2.0.0.tgz","fileCount":9,"integrity":"sha512-NaMBAPXFnTnTTafwLtW06yUXJPZNcl2TTmGuAyz2VMZNTbF8Zh7HxeIqDC0xa7z3mRjaEHf10NDfCn0hpWuhzg==","signatures":[{"sig":"MEQCIDCwohC1hOKms7kEmafBRqvBob3iYEddmBRfhEFrQiWKAiB+J11KB9Qglbw3cChWMC46+L2IABWeX5niFbzXC8zzWA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17741},"main":"./dist/index.js","type":"module","_from":"file:agencecinq-spinbutton-2.0.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","build":"vite build"},"_npmUser":{"name":"19h47","email":"jeremylevron@19h47.fr"},"_resolved":"/private/var/folders/vt/kpbgrh4d7k14zvxmcm01bfxh0000gn/T/569c09095a286caeab11e3b7ae5fe210/agencecinq-spinbutton-2.0.0.tgz","_integrity":"sha512-NaMBAPXFnTnTTafwLtW06yUXJPZNcl2TTmGuAyz2VMZNTbF8Zh7HxeIqDC0xa7z3mRjaEHf10NDfCn0hpWuhzg==","repository":{"url":"git+https://github.com/agencecinq/shopify.git","type":"git","directory":"packages/spinbutton"},"_npmVersion":"11.18.0","description":"Accessible, WAI-ARIA spinbutton as a lightweight Web Component.","directories":{},"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.2.0","vite-plugin-dts":"^5.0.3","@agencecinq/utils":"6.0.0"},"peerDependencies":{"@agencecinq/utils":"*"},"_npmOperationalInternal":{"tmp":"tmp/spinbutton_2.0.0_1785918370760_0.31880344382777626","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"name":"@agencecinq/spinbutton","version":"3.0.0","author":{"url":"https://agencecinq.com","name":"Jérémy Levron","email":"jeremy@agencecinq.com"},"license":"MIT","_id":"@agencecinq/spinbutton@3.0.0","maintainers":[{"name":"19h47","email":"jeremylevron@19h47.fr"}],"homepage":"https://github.com/agencecinq/shopify#readme","bugs":{"url":"https://github.com/agencecinq/shopify/issues"},"dist":{"shasum":"96740fc714465ef679b866f59071a42683445d9a","tarball":"https://registry.npmjs.org/@agencecinq/spinbutton/-/spinbutton-3.0.0.tgz","fileCount":9,"integrity":"sha512-wY6bnarj8/TViluSBxtgyAMTF8RSqnGXGTQGQtRr6vBZfobHumgrYh0FF4WzSEKkvU8HUBWYKzKx4taS/yPgpQ==","signatures":[{"sig":"MEYCIQCwTSn3Xjb8H+GYjz2XBIIMLC8WHSunIecS7tv2U6LycQIhAOx+Qbzyk0X1Y2jADbt+sxMiOjkONhM59XXnNKGt8PBE","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17770},"main":"./dist/index.js","type":"module","_from":"file:agencecinq-spinbutton-3.0.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","build":"vite build"},"_npmUser":{"name":"19h47","email":"jeremylevron@19h47.fr"},"_resolved":"/private/var/folders/vt/kpbgrh4d7k14zvxmcm01bfxh0000gn/T/34955854a3d94507c0bc5ef0c3b2f02e/agencecinq-spinbutton-3.0.0.tgz","_integrity":"sha512-wY6bnarj8/TViluSBxtgyAMTF8RSqnGXGTQGQtRr6vBZfobHumgrYh0FF4WzSEKkvU8HUBWYKzKx4taS/yPgpQ==","repository":{"url":"git+https://github.com/agencecinq/shopify.git","type":"git","directory":"packages/spinbutton"},"_npmVersion":"11.19.1","description":"Accessible, WAI-ARIA spinbutton as a lightweight Web Component.","directories":{},"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.2.0","vite-plugin-dts":"^5.0.3","@agencecinq/utils":"6.1.0"},"peerDependencies":{"@agencecinq/utils":"*"},"_npmOperationalInternal":{"tmp":"tmp/spinbutton_3.0.0_1788157220251_0.1556824723796597","host":"s3://npm-registry-packages-npm-production"}},"4.0.0":{"name":"@agencecinq/spinbutton","version":"4.0.0","author":{"url":"https://agencecinq.com","name":"Jérémy Levron","email":"jeremy@agencecinq.com"},"license":"MIT","_id":"@agencecinq/spinbutton@4.0.0","maintainers":[{"name":"19h47","email":"jeremylevron@19h47.fr"}],"homepage":"https://github.com/agencecinq/shopify#readme","bugs":{"url":"https://github.com/agencecinq/shopify/issues"},"dist":{"shasum":"d1dea350653b13399f397e8bdf7994b12d2e8b13","tarball":"https://registry.npmjs.org/@agencecinq/spinbutton/-/spinbutton-4.0.0.tgz","fileCount":9,"integrity":"sha512-z1r11h3YtDPvpqqMaKkGxSeXFwM7+REvp2Xzjk6k05Z3fUiElWaFZduH2u2Xk9X6TlqCjgXF896ZQgzd1KUuBQ==","signatures":[{"sig":"MEYCIQCm7n6X/FZgwTWppHK/i4Ua00BGVnXDfJHyCE/6xnPaiAIhAIohiC5Zzchq+vnQV576oX1FZnn0vqgF3Hr76u46jGhG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":15709},"main":"./dist/index.js","type":"module","_from":"file:agencecinq-spinbutton-4.0.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"vite build --watch","build":"vite build"},"_npmUser":{"name":"19h47","email":"jeremylevron@19h47.fr"},"_resolved":"/private/var/folders/vt/kpbgrh4d7k14zvxmcm01bfxh0000gn/T/ce7e9fe215445245f755d13572d406a7/agencecinq-spinbutton-4.0.0.tgz","_integrity":"sha512-z1r11h3YtDPvpqqMaKkGxSeXFwM7+REvp2Xzjk6k05Z3fUiElWaFZduH2u2Xk9X6TlqCjgXF896ZQgzd1KUuBQ==","repository":{"url":"git+https://github.com/agencecinq/shopify.git","type":"git","directory":"packages/spinbutton"},"_npmVersion":"11.19.1","description":"Accessible, WAI-ARIA spinbutton as a lightweight Web Component.","directories":{},"_nodeVersion":"22.22.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.2.0","vite-plugin-dts":"^5.0.3","@agencecinq/utils":"7.2.0"},"peerDependencies":{"@agencecinq/utils":">=7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/spinbutton_4.0.0_1788879106206_0.4922911689407372","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-04-28T10:40:27.342Z","modified":"2026-09-15T13:10:47.911Z","1.0.0":"2026-04-28T10:40:27.565Z","1.0.1":"2026-04-29T06:12:05.494Z","1.0.2":"2026-05-21T07:43:28.001Z","1.0.3":"2026-07-20T14:18:16.860Z","1.0.4":"2026-07-21T07:32:25.211Z","2.0.0":"2026-08-05T08:26:10.888Z","3.0.0":"2026-08-31T06:20:20.462Z","4.0.0":"2026-09-08T14:51:46.324Z"},"bugs":{"url":"https://github.com/agencecinq/shopify/issues"},"author":{"url":"https://agencecinq.com","name":"Jérémy Levron","email":"jeremy@agencecinq.com"},"license":"MIT","homepage":"https://github.com/agencecinq/shopify#readme","repository":{"url":"git+https://github.com/agencecinq/shopify.git","type":"git","directory":"packages/spinbutton"},"description":"Accessible, WAI-ARIA spinbutton as a lightweight Web Component.","maintainers":[{"email":"jeremylevron@19h47.fr","name":"19h47"},{"email":"pauline@agencecinq.com","name":"paulinecinq"}],"readme":"[![](https://img.shields.io/npm/v/@agencecinq/spinbutton)](https://www.npmjs.com/package/@agencecinq/spinbutton)\n[![](https://img.shields.io/npm/dm/@agencecinq/spinbutton)](https://www.npmjs.com/package/@agencecinq/spinbutton)\n\n# @agencecinq/spinbutton\n\n> Accessible, WAI-ARIA spinbutton as a lightweight Web Component.\n\nA spinbutton restricts its value to a set or range of discrete values. `<cinq-spinbutton>`\nprovides an accessible, keyboard-navigable interface for numerical input that\nmaintains value constraints, and dispatches events when values change.\n\nImplementation follows the\n[WAI-ARIA Authoring Practices spinbutton pattern](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/).\nInspired by [`@19h47/spinbutton`](https://github.com/19h47/19h47-spinbutton/).\n\n## Installation\n\n```bash\npnpm add @agencecinq/spinbutton\n```\n\n## Usage\n\n### Web Component (`<cinq-spinbutton>`)\n\n```html\n<cinq-spinbutton>\n  <button name=\"decrease\" type=\"button\" aria-label=\"Decrease\" tabindex=\"-1\">\n    −\n  </button>\n\n  <input\n    type=\"number\"\n    aria-label=\"Quantity\"\n    aria-valuemin=\"0\"\n    aria-valuemax=\"10\"\n    aria-valuenow=\"1\"\n    value=\"1\"\n  />\n\n  <button name=\"increase\" type=\"button\" aria-label=\"Increase\" tabindex=\"-1\">\n    +\n  </button>\n\n  <!-- Optional: announce changes while the input stays focused -->\n  <div aria-live=\"polite\" aria-atomic=\"true\" class=\"sr-only\"></div>\n</cinq-spinbutton>\n```\n\n```js\nimport \"@agencecinq/spinbutton\";\n```\n\nImporting `@agencecinq/spinbutton` registers the Web Component automatically.\nNo manual `init()` call required.\n\n> **HTML is the source of truth.** The component will not auto-set `role`,\n> auto-migrate attributes, or warn about missing labels. Use an a11y linter\n> (axe-core, Lighthouse) to catch invalid markup.\n\nUse `input type=\"number\"` (implicit `role=\"spinbutton\"`) or set `role=\"spinbutton\"`\nexplicitly on `input type=\"text\"`.\n\n### Required markup\n\n| Attribute / element | Required | Role |\n| ------------------- | -------- | ---- |\n| `<cinq-spinbutton>` | **Yes** | Wrapper component, controls the inner input. Carries no ARIA state. |\n| `<input>` | **Yes** | The focusable element. One input per host. Hosts `role=\"spinbutton\"` and ARIA value state. |\n| `button[name=\"increase\"]` | Optional | Click to increase by step. Auto-disabled at the max. |\n| `button[name=\"decrease\"]` | Optional | Click to decrease by step. Auto-disabled at the min. |\n| `[aria-live]` | Optional | Live region mirrored when `formatValue` is set. One per host. Style/hide in your CSS. |\n\nThe component writes `aria-valuenow` and `value` on the input. Set `aria-valuetext`\nin the markup yourself, or assign `formatValue` to keep it in sync (and optionally\nmirror into `[aria-live]`). Without `formatValue`, the component does not touch\n`aria-valuetext`.\n\nPer the [APG spinbutton pattern](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/),\nall ARIA state lives on the focusable `<input>`. The host carries no ARIA state.\n\n### Markup variants\n\n| Variant | Markup |\n| ------- | ------ |\n| Number input | `input type=\"number\"` (implicit `role=\"spinbutton\"`) |\n| Text input | `input type=\"text\"` + `role=\"spinbutton\"` |\n| Visible label | `aria-labelledby` referencing external text |\n| Compact | `aria-label` on the `<input>` |\n| Input only | `<input>` without + / − buttons |\n| `formatValue` | `(value) => string` for `aria-valuetext` (+ optional `[aria-live]`) |\n\nSee the [interactive docs](https://agencecinq.github.io/ui/components/spinbutton/) for live examples of each variant.\n\n### `formatValue` and plural rules\n\nAssign `formatValue` in JS. Use `Intl.PluralRules` (or your i18n library) for\nlocale-aware pluralisation (English: one/other, Polish: one/few/many/other;\nArabic: up to six categories):\n\n```js\nconst labels = { one: \"level\", other: \"levels\" };\nconst pluralRules = new Intl.PluralRules(\"en\");\n\nhost.formatValue = (value) => {\n  const unit = labels[pluralRules.select(value)] ?? labels.other;\n  return `${value} ${unit}`;\n};\n```\n\n### Buttons out of the tab sequence\n\nThe + / − buttons must not be in the tab order. They are operated via the\nkeyboard arrows of the `<input>` itself (per the APG pattern). Always set\n`tabindex=\"-1\"` on them, and provide an `aria-label` so screen-reader users\nwho do reach them via swipe gestures still get a meaningful name.\n\n### API\n\n| Attribute | Type | Default | Description |\n| --------- | ---- | ------- | ----------- |\n| `data-step` | number | `1` | Increment used by buttons and arrow keys. |\n| `data-delay` | number | `100` | Minimum interval (ms) between `spinbutton:change` dispatches during rapid value changes. DOM updates are not throttled. |\n\n| Property | Description |\n| -------- | ----------- |\n| `formatValue` | Optional formatter for `aria-valuetext` and the optional `[aria-live]` child. |\n\n| Method | Description |\n| ------ | ----------- |\n| `init()` | Binds markup + listeners. Call `destroy()` first if already bound. |\n| `setValue(value, emit?)` | Sets the current value. Clamped to min/max. |\n| `setMin(value, emit?)` | Updates `aria-valuemin` and re-clamps the current value. |\n| `setMax(value, emit?)` | Updates `aria-valuemax` and re-clamps the current value. |\n| `increase()` | Adds step to the current value. |\n| `decrease()` | Subtracts step from the current value. |\n| `destroy()` | Detaches listeners. |\n\n| Property | Description |\n| -------- | ----------- |\n| `$input` | The inner `<input>`. |\n| `$increase` | The optional increase `<button>`. |\n| `$decrease` | The optional decrease `<button>`. |\n| `$live` | The optional `[aria-live]` element. |\n\n### Keyboard support\n\nStrictly the keys defined by the\n[APG pattern](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/#keyboardinteraction).\nOther keys (Arrow Left/Right, Backspace, Delete, printable characters) are left\nto the browser so the user can freely edit the input's text.\n\n| Key | Function |\n| --- | -------- |\n| Arrow Up | Increase value by step. |\n| Arrow Down | Decrease value by step. |\n| Page Up | Increase value by step × 5 (optional per APG). |\n| Page Down | Decrease value by step × 5 (optional per APG). |\n| Home | Jump to `aria-valuemin` (when defined). |\n| End | Jump to `aria-valuemax` (when defined). |\n\nTyped values commit on `change` (blur / Enter), not on every keystroke. Out-of-range\nentries set `aria-invalid=\"true\"` on the input, then clamp to the nearest bound.\n\n### Programmatic API\n\n```js\nconst $spinbutton = document.querySelector(\"cinq-spinbutton\");\n\n$spinbutton.setMin(10);\n$spinbutton.setMax(200);\n$spinbutton.setValue(50);\n$spinbutton.increase();\n$spinbutton.decrease();\n```\n\n`setValue()`, `setMin()`, and `setMax()` accept an optional `emit` argument (default\n`true`). Pass `false` to update state without dispatching an event.\n\nCall `destroy()` when removing the element from the DOM to detach listeners.\nAfter mutating light DOM (e.g. swapping the input), call `destroy()` then\n`init()`:\n\n```js\n$spinbutton.destroy();\n// mutate light DOM...\n$spinbutton.init();\n```\n\n## Events\n\n| Event | Cancelable | Detail | Description |\n| ----- | ---------- | ------ | ----------- |\n| `spinbutton:change` | Yes | value: number | Throttled notification when the value changes (see `data-delay`). |\n\n```js\nimport { EVENTS } from \"@agencecinq/utils\";\n\n$spinbutton.addEventListener(EVENTS.SPINBUTTON_CHANGE, (event) => {\n  console.log(event.detail.value);\n});\n```\n\n`spinbutton:change` is a throttled notification fired after the value is\ncommitted to the DOM. Calling `event.preventDefault()` does not revert the value.\n\n## Build setup\n\n```bash\npnpm -C packages/spinbutton build\n```\n\n## Acknowledgments\n\n- [Spinbutton Pattern (WAI-ARIA Practices)](https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/)\n- [`@19h47/spinbutton`](https://github.com/19h47/19h47-spinbutton/): original implementation\n","readmeFilename":"README.md"}