{"_id":"xiaodao-spreader","_rev":"39-48fe68f5dc80053fde3d8b390d00f8ca","name":"xiaodao-spreader","dist-tags":{"latest":"0.1.45"},"versions":{"0.1.2":{"name":"xiaodao-spreader","version":"0.1.2","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.2","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"b0def59dd1656cef4ed5967e8c565b084d443612","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.2.tgz","fileCount":13,"integrity":"sha512-9D3WOgVpBjY1XASkaQLmvNE0z/Rtx3I/6vKqcfSWQ/yBnjWa9RjTiKiInLiHjupdww/D+CG7bpHV9gGnyjXhag==","signatures":[{"sig":"MEYCIQC9CBdCflV2h3McFTVjdyIkJzjSNEYVm+PdQJjVGJy2zwIhAPE9lW5ModQKom3i9PXv1O34FHpS468xG829ueKqaQQW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":119448},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.2_1787037375747_0.6297441419602019","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"xiaodao-spreader","version":"0.1.3","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.3","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"2905256baf3b8a3290f7292e2bd306d0b8416480","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.3.tgz","fileCount":18,"integrity":"sha512-dbzhzImVw7Sayk3W7RioRmZvV6UUpMhnLSwTaMzLAvKaTttFJRBcI5ODHzC13YIFIVRvit7ufrQYcyxAU872Hw==","signatures":[{"sig":"MEQCIFPq+OYFZayZXuI+ybAUKNRAoWcadxu4s7VvF9fUSkntAiBlIxPdfutfeO2aXs15/DvOSver2Z3YK8tSAECgR85+Bg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":279261},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.3_1787205333026_0.3752565645886454","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"xiaodao-spreader","version":"0.1.4","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.4","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"fdabf6179a2a94e28efeee2f57dbff17d1241f70","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.4.tgz","fileCount":18,"integrity":"sha512-bxgBQxQw66DGBBmrZIAuEgn+Nv5+vXTY887RBhxauGgtdx69Zt0zB356NXOJqUP/6ITSZYJDE1XCpxBjCAzifQ==","signatures":[{"sig":"MEQCIFmNvPfTo/C7qYT/jYLGxvvdzJkYdCQN7hHUKjjiSwaaAiAmYFhgjoZRtSEUGsurBCmOg/fv+dexgtGC6NVEXm63YQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":303633},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.4_1787219219580_0.2193300854545961","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"xiaodao-spreader","version":"0.1.5","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.5","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"ea9894c399306b641b632101528b889a29463c3f","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.5.tgz","fileCount":26,"integrity":"sha512-/yFzHFvvaln7hhjsaVQhy/JI2E+Y/rQeagMjQOoqgzh67A48gLGuauDB24xOLnRsBBN81IUtXek+ytNZxOAkmQ==","signatures":[{"sig":"MEUCIG8nKd54etdonZ6uKEmDSDKi0NvAbsyX73rU0xgJ34tbAiEA3MTyrakZfMus7quhvN04fZuXO9aPanjClljePv5Jvk8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":438309},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.5_1787299958364_0.24012315145530505","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"xiaodao-spreader","version":"0.1.6","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.6","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"8e142f50bf166ce471a82e7e00593ea2cdb08d10","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.6.tgz","fileCount":26,"integrity":"sha512-ORGxADgVaRKqkaFWGBNCTs5EFDl5Z8piMoLTNzO3czWJJMx8jmc1MWNLqs43ThYP0rQvQDFRJdcl5GeP7y9E7g==","signatures":[{"sig":"MEUCIHEzi24pcg3iTUT5A1JaLS37aLm0Gxu6oPD4VTuppZDKAiEAtPN3IGr1EzCkxMRj9Ku1mnt9YwITC07e30cuHjPTXbw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":439817},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":false,"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.6_1787302592891_0.3754073144811094","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"xiaodao-spreader","version":"0.1.7","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.7","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"2d5943db03cde9f6db557bb6d110886cb78cd7fd","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.7.tgz","fileCount":25,"integrity":"sha512-8Lu9Hr5C6sZCvNBDA2nMetm7ziIWexG81TSJDdqYXPrFDcIo+88wU1KewIVfLQS22Iy+y+WgX6fKBfEtzq5Gug==","signatures":[{"sig":"MEYCIQCj09MT0NKa/G54VKCBRCKvtUCRjX6NDyKeW71vcRARsAIhAO+9cxej9iclSVPa0KlBA3ym1a9Pc6kdFx4Z46MugX3E","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":440225},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.7_1787309185677_0.17891755723082903","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"xiaodao-spreader","version":"0.1.8","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.8","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"db51e94dc1b0847f1ded6b173a55f80224e07b2e","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.8.tgz","fileCount":26,"integrity":"sha512-+bJNEJYcszEuHrlcroov4+vsOaOMUkyPl81bY2zbd5Pbj71Ij0rZKT0XAfqZ1Knx6Pp4ztW3Wt7FCDJ1FpPkhg==","signatures":[{"sig":"MEYCIQCZazi8mq6i5FYM2ECg+fyU2EVCKNu8+Q7Pq1sLDthFJwIhANjfwbZz4YOsmdCwaIWBhAHTw1iDxsZ4RZLXpOXh+sNK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":440979},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.8_1787310209994_0.17799560519296498","host":"s3://npm-registry-packages-npm-production"}},"0.1.9":{"name":"xiaodao-spreader","version":"0.1.9","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.9","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"3715c648fb7751a3309f4dacb4b4ccbaaddcfe48","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.9.tgz","fileCount":26,"integrity":"sha512-MJPekVKosfeoCpaYl4ZZv7C6/6gdvlxxPN3bHphNCBgvKGxdtssRVB2GRd6YGdyf+iC4qx+ilLMRShDsQYfRiA==","signatures":[{"sig":"MEYCIQDe0N6sCa2RgUR4S5P2gAVLx1xftlPZc4V6Kzc+1cxtsQIhAIKAuj1cY948zyJF5YY+94kVQXn+m9wO7W7oPJXZLK1i","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":443691},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.9_1787328966120_0.13517964556175088","host":"s3://npm-registry-packages-npm-production"}},"0.1.10":{"name":"xiaodao-spreader","version":"0.1.10","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.10","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"860e512fd15cda4053e1a3c4dbb554fe9477b1a3","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.10.tgz","fileCount":27,"integrity":"sha512-9uB3KWrl9Mfz86dBuU884Brc2VXfc5epCJH+PtveOaBbtEcb3EBh57CZ3o1mEJBQjuNeX4vKbWwzK8V+1Pq7pQ==","signatures":[{"sig":"MEYCIQDUUuGwriaS85LrKian9kZ52gG1hfNeVBENJ0iD9MSNbgIhAJ6i9X/KhHIFANe5Io6ZqSsHF2r8o2yCpPEuaJgy4DrC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":460015},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.10_1787480272888_0.08902264011559158","host":"s3://npm-registry-packages-npm-production"}},"0.1.11":{"name":"xiaodao-spreader","version":"0.1.11","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.11","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"8c20f73cb7c70fe682e74d88760338e25bcd43f0","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.11.tgz","fileCount":29,"integrity":"sha512-kZE2peBLM/ztvhwPM5/wManZZBll39BbO3+XskKNOvv8v7k66HAPrRD5iDLX26Lpm0+ajmjlT/MbZfnvrRRgTA==","signatures":[{"sig":"MEQCIGbr3SVFzEgLzydkcj/BQzshTCGxN1Z+oEmHiqIwhhHvAiAb2N0WeNHV6Wb/Gf+niTmAbtKzXsbsq9uCLCHdVjqBiw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":556424},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.11_1787569315030_0.15070741574315605","host":"s3://npm-registry-packages-npm-production"}},"0.1.12":{"name":"xiaodao-spreader","version":"0.1.12","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.12","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"1f24fc58d7d89c92238562a0a8c1330fe153c9ff","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.12.tgz","fileCount":29,"integrity":"sha512-Ul9Bti9CgyB124DHKFSJc4jH68ARyZ4I2cKqCyJJjglBNWYOfKJ6tx821qZiBrc+dfcNauz7on49g3zXZ/0IYQ==","signatures":[{"sig":"MEQCIBOoaTHjy2Y47JsnVzGD5lFmoazsitGV3tRrvl/ElSOIAiAwDdX9CFttmpbcJ0cAuN6iwgUYdY7QGS6Csn/VmpXUrg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":577592},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.12_1787574598827_0.4500230836355268","host":"s3://npm-registry-packages-npm-production"}},"0.1.13":{"name":"xiaodao-spreader","version":"0.1.13","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.13","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"5208609ccecfbd774e96aa07f120afb1fb15fc6c","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.13.tgz","fileCount":32,"integrity":"sha512-LEsyQXWTJi8+OmucfW3+ztJvO+px5neg8vYLyG0oeUJPCxOzL21d8XR5ra6qLJagXlzMe538g9aIMHo6NniFlw==","signatures":[{"sig":"MEUCICp20wQhrEa24LKa5L3jEmb7THpuVDFCf9YWiQD5zjKpAiEAq2IaQ8h8kG5capE/DkAmnRScxfI3J4J5w2wV05GSRZM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":614950},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test dist-test/test/find-replace-core.test.js","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.13_1787581082766_0.6287103369649261","host":"s3://npm-registry-packages-npm-production"}},"0.1.14":{"name":"xiaodao-spreader","version":"0.1.14","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.14","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"2b2590f37c15542927c081ca760812cf4936f9c4","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.14.tgz","fileCount":32,"integrity":"sha512-eSHKLN+La8vcaN2Hj2AuA7cgl96x81o332d9OR4k97aE/gvP7QdZGKgAaE5ggQpmqvVupSOTgfemNTnLNrcjtA==","signatures":[{"sig":"MEUCIQDUXB6j2fKFA/cfILA8eCVWlYAqjV3DyZUD+TB2Fi9V2gIgByUWePVVNiWy9ZEe1j8S5OiRo2yQVW5FlUQy6kXA0pg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":614950},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test dist-test/test/find-replace-core.test.js","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.14_1787581384203_0.2343707971542628","host":"s3://npm-registry-packages-npm-production"}},"0.1.15":{"name":"xiaodao-spreader","version":"0.1.15","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.15","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"dist":{"shasum":"a7a876ecfeffc25e69626ca467f6ec69862fca97","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.15.tgz","fileCount":32,"integrity":"sha512-YpdWTakSYFqtcf/Rrizu7pyNJmhJGAvmxTtPnwSba1bgW4jYTPejHpRvYLUGo+XjpDPYlO3i2OEuXJszftbjUg==","signatures":[{"sig":"MEQCIBw7nLdUuhWdEBtDWbT5JbEeD0o5oWPFnh1yJhzkdchNAiBUA4saE/AHiLIB2DQyXJMThD3V1L0nyEjg91qHYKG+3Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":614984},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test dist-test/test/find-replace-core.test.js","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.15_1787582427291_0.4243916249159678","host":"s3://npm-registry-packages-npm-production"}},"0.1.16":{"name":"xiaodao-spreader","version":"0.1.16","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.16","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"15403dc139e07d908d303f97ef23928b92cb966f","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.16.tgz","fileCount":32,"integrity":"sha512-7OJ3wgYyzqSs/K5p8wUKEo79AX2RGVSH1MbKWq4URj5yrXZAxwZlUpop3+WqVEo6c3n22a57xg/i/IwuyvdlUQ==","signatures":[{"sig":"MEQCIHuBQkDOUAloaDSxfRFa2ld4mIuIV0aHHLskNsOPIsjfAiA9beSh13Vs1HYyo7ZlZy5Je/TJ8w84kzEoh8yZsUuKww==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":614001},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test dist-test/test/find-replace-core.test.js","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.16_1787627219959_0.09064590723668209","host":"s3://npm-registry-packages-npm-production"}},"0.1.17":{"name":"xiaodao-spreader","version":"0.1.17","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.17","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"75b3ac3cf0119670f1ad912438c9b8b304522f45","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.17.tgz","fileCount":32,"integrity":"sha512-hy5CeF5oJeIVMLhuSCwrgwmxUhU7KgI2zrnjsrIPukp27Rag9B610hh5v/OU/PtAv3Nu3gnqnfXg1Wd34Cw/Qg==","signatures":[{"sig":"MEUCIQCrrsozKkCmxtXn1AQy/X02wj/14NWbgz+tIkJpvh9bFAIgLfUgZrlbec2/Mm/74OUUwUHIVX6UxaOAom4mNcJRt/I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":614657},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test dist-test/test/find-replace-core.test.js","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.17_1787632723823_0.08212553077364326","host":"s3://npm-registry-packages-npm-production"}},"0.1.18":{"name":"xiaodao-spreader","version":"0.1.18","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.18","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"23d9a105130badb08a72b4f3050813b2ac601d2d","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.18.tgz","fileCount":32,"integrity":"sha512-wjYGU2qskzLARO8rfmseAXAzNVsDoh+LW+XzkuvcSBHdzyaLrlHiSYu35AhcxgU1R/3B7jhtwTA+b0bGsskehg==","signatures":[{"sig":"MEYCIQD64U5mvPXzMjQFq+0o7Ubss9iHWn9bLUTqxcn+V9hwfAIhAJjlPKVz6+8wJGevAEJfA9NOXQsgOclxRVvq2sa7FDKG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":615724},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test dist-test/test/find-replace-core.test.js","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.18_1787635133900_0.16025304293679743","host":"s3://npm-registry-packages-npm-production"}},"0.1.19":{"name":"xiaodao-spreader","version":"0.1.19","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.19","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"a01ad244b0e0f5026e5f285567dce1d977fa2201","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.19.tgz","fileCount":32,"integrity":"sha512-mjW0kUu7B5JPqWVTeoMIFmdsGli2sWNrmXXIoiT33Muo15vZyPPsTqZCyQzTG1s027X0EkEYe96vPnigcnvB8A==","signatures":[{"sig":"MEUCIEapeiCFIBxEslHxPt2iF7j9UlZRh7MzzNPL3Drk1/xdAiEA8wRjAtgfpA7DqGAVqae5jCJuaqdXrEgw0+xiQAYty8Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":628492},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test dist-test/test/find-replace-core.test.js","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.19_1787637154775_0.03599540278494873","host":"s3://npm-registry-packages-npm-production"}},"0.1.20":{"name":"xiaodao-spreader","version":"0.1.20","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.20","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"b0c014d205064b6dd9b71f31372588d2500a77c2","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.20.tgz","fileCount":35,"integrity":"sha512-87A19miquh/6nag8jm+fCdX9t5r1pdKkxfm93+pKbAo+YUtENLDUTiWsRvpjLXB0G33VZqMTrDKCHzMbcdzfbQ==","signatures":[{"sig":"MEUCIQCWJjGIsFxGVIHySK2OEtHDZrB8d2E+sO74DQH7roVZ8gIgC07l9d2Z1gRTPg2TR50XgAENoTuD4ti9HxVBUmlzHXM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":669511},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.20_1787653000467_0.51661608360278","host":"s3://npm-registry-packages-npm-production"}},"0.1.21":{"name":"xiaodao-spreader","version":"0.1.21","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.21","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"a2bd4564429e8a2487b407789e6fcbec5d15048c","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.21.tgz","fileCount":35,"integrity":"sha512-twUFvneuYlVMIvMtHkqbFvJ7hTOhrvLTt3/ujghnvL+VXhMEBUyUhYfCUoWfkgHkLP/JcogMdMyYKiEhU1d8BQ==","signatures":[{"sig":"MEUCICWnpS3F6bCFD8UjDhYZQKKJlVqKwWRJKhPJVbkZf83xAiEA+RjbzuC/E5Y+yEU3kdKzvJHbmuFJ6b8tByLQ92W4d2k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":693882},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.21_1787655923526_0.8316953990238749","host":"s3://npm-registry-packages-npm-production"}},"0.1.25":{"name":"xiaodao-spreader","version":"0.1.25","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.25","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"8512c7fd2f949575ef76e930ea12f09409c9ea41","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.25.tgz","fileCount":39,"integrity":"sha512-qslg9kApPlpYfIjlr1DzFQdidNf2OxGwy2rTWAxHRf0/FM8HMBaDEAr+uHgUPZkI/Su7IT2aT4tkkjR7khCOyQ==","signatures":[{"sig":"MEUCIDgo2fKRISU0f6jAGtwGL1w3J8sNVXNKbCDpqo43lC5/AiEAyQbJALm/CZCe82xsJhTxlG6v7AnLqVWtcUP3Zgo4Zh0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":768498},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.25_1787728000908_0.7958957918158971","host":"s3://npm-registry-packages-npm-production"}},"0.1.26":{"name":"xiaodao-spreader","version":"0.1.26","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.26","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"cf4565c31ddcdc5f2e2e069612da0b9cf4d7a242","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.26.tgz","fileCount":39,"integrity":"sha512-SMY/cOTQnf+lmLL3GA/97uXQ1aUyzlgihYB8auH7KqOQ2TyFXtSEqZt8qzTh9JSnlk+0LkAtF09agIoTG0LS+g==","signatures":[{"sig":"MEUCIQDDQEoA+KTCuiKPwJ7e0Dsc1Li/GEmuuylgZ/iI+JMxkAIgLeSrOAScIOo6xwFPXf/BwxYgvUgOPl+gdMFkErQgEl4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":778285},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.26_1787730770872_0.5207997898531627","host":"s3://npm-registry-packages-npm-production"}},"0.1.27":{"name":"xiaodao-spreader","version":"0.1.27","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.27","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"2ae19f39b3e23adad16fc1b37211e34d05ac2209","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.27.tgz","fileCount":39,"integrity":"sha512-1XambAezOL6jW0es6+yluKCceqMqSqi+C3DSM77QfUAh2dYOsR44Wd5A0hjb6aP6AangFBY7Dlwv1hcRv7fzYg==","signatures":[{"sig":"MEYCIQCA31k/SCn8iLPXa8uW5tCN5ciZPUp/ZQcTrs5PYy5W2AIhANW/Q9hQNNEZtf0btN2Vi1FauAI7JNkarJMoalyVtY8z","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":792511},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.27_1787741273950_0.5719816101462647","host":"s3://npm-registry-packages-npm-production"}},"0.1.28":{"name":"xiaodao-spreader","version":"0.1.28","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.28","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"564a2ed17196dbe3855f4c708ae834272feb450c","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.28.tgz","fileCount":39,"integrity":"sha512-1bL6iRJot5ZcDMGPi71wRERSqumnlpIrIVzMbB1fOj88oUlIOSNVcSrwi8OrwFK/teBA5Wma9/s6Ew/xCfwePQ==","signatures":[{"sig":"MEQCIFMfZ5b4H765MchSp/j4soxHkGQMH6x7mQX+XhQUon4EAiBSnsQlQ/VP5ZIMmQB8zhxEDEtLaApuHKf9kl2BA/KMoA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":833035},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.28_1787812578658_0.7285641931949656","host":"s3://npm-registry-packages-npm-production"}},"0.1.29":{"name":"xiaodao-spreader","version":"0.1.29","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.29","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"94ffcb29624e99bd90be92ed0a1b8712cb5cabbb","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.29.tgz","fileCount":40,"integrity":"sha512-UOIC8+R0F0p131EbdIZlHR4tD5jYWfnUGKDCHGacwXMRJRC89BmxLm204vtufEC28DB2AGdxMqmmnoJmq1Xi7A==","signatures":[{"sig":"MEUCIBt0EN4kJ2VCmE8TPaDR2Kczo+NHSP0vjgx6hKv1mRX0AiEAuyHkbnXpAJk01c78aAvGDtIn2xbZ1jgSFSu83yvCGew=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":871141},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.29_1787819887776_0.9602487804037145","host":"s3://npm-registry-packages-npm-production"}},"0.1.30":{"name":"xiaodao-spreader","version":"0.1.30","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.30","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"d6a8ec4a893866d5e5e13064d5e84db787b604d0","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.30.tgz","fileCount":42,"integrity":"sha512-cWq7p8Nhk4OvKTFdwL897OzlLHatyWxH/Jgdiazznjd762dI7rfseDTcRViVvCyX5YiZuI2Lq9+4HbMP0YXpvA==","signatures":[{"sig":"MEUCIQC7sRk55Jnss1pjrfXdGF9Ncl0/Z/wsvjHOjLuMUIGEWwIgWBkR1MMJCPEYDAjgUIeZF1CCx/v0BfmZANl6dUvLWjY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":956741},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.30_1787845195206_0.559905708871403","host":"s3://npm-registry-packages-npm-production"}},"0.1.31":{"name":"xiaodao-spreader","version":"0.1.31","keywords":["vue","canvas","spreader","sheet"],"license":"MIT","_id":"xiaodao-spreader@0.1.31","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"cae5086dc8f727bdbbf22b5f9b4f8384b0e42896","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.31.tgz","fileCount":42,"integrity":"sha512-4jIH+MpVyHs3X+g8kTZv9iw6Pbmn8DDBztxUi1yeJcp+f0GqIF3RNzrhfNh5rjh9/QYRXJobjCibMZDGXelePA==","signatures":[{"sig":"MEUCIA4BXV5810k+Emtj3gmwJE2TMetU6DxMVdBtMliMqauTAiEAi10eWI+A1UJozsnLvd6crNvNFghuPXi/jGNtcCKmMK4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":961306},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.31_1787885700503_0.5392612203985001","host":"s3://npm-registry-packages-npm-production"}},"0.1.32":{"name":"xiaodao-spreader","version":"0.1.32","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.32","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"e915091e7a0464d5f0fc504f65b79be0c9a8af2d","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.32.tgz","fileCount":42,"integrity":"sha512-rznx3LdotQ2FhLQq2Kace6Ku+rPXC9aVmm42jGx6hcxCKjeyJLRFYWEk2AUtv+xjon1W48GXeQHV976LL338ow==","signatures":[{"sig":"MEUCIQDAu7EsKBfqAgJxc5Lk/NwJucZRiF5M4JrA12Vs9dmLtwIgMPwJBhgyNQKGy+aqQt6nAn1MdHvcsVlQy22kN14Xj4c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":961541},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.32_1787889287398_0.7410018127462736","host":"s3://npm-registry-packages-npm-production"}},"0.1.33":{"name":"xiaodao-spreader","version":"0.1.33","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.33","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"a36af97e4c9206c8f93021f0f3f5e9eb36a70d1a","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.33.tgz","fileCount":46,"integrity":"sha512-WeSt4lG8ZJaEjrOIl/w4vhScNcZyydl49tHFSptNgvINv+Zu122z8epMit1RkWa2pCWiSCYKE+GAv94tHhfTQQ==","signatures":[{"sig":"MEYCIQCzWvu/BwsSUe1JTdTtSLZzDer7UVO145uCB01DVEQlZwIhAO4Tqzvp5YSWZkKNU1QFjDOjFNeKYQazLwsEdgBzOsuG","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1147164},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.33_1787913784843_0.6721628576199783","host":"s3://npm-registry-packages-npm-production"}},"0.1.34":{"name":"xiaodao-spreader","version":"0.1.34","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.34","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"5cb8174bc5b29ab498bed50824d102b5121832a5","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.34.tgz","fileCount":46,"integrity":"sha512-dDG0A9RznDmdRkggSSDvr4KNB2RBUvt72u5nBGCNkOUVLfPMklN+HtZpeVUpQ3xSxIjqSCw8gFkPQWrtD3+lKQ==","signatures":[{"sig":"MEQCIG4nPgfALrFo5OUze6eqCe5p62rYMfakydQbZhybfowGAiBL3eH7E3fVkyydI4dwgYhdvYH/iQJN/Lps4oigNkmMmA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1147434},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.34_1787915358642_0.5775128613753833","host":"s3://npm-registry-packages-npm-production"}},"0.1.35":{"name":"xiaodao-spreader","version":"0.1.35","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.35","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"36e7feabd51ad8b621befcec6ec465d293e9bce2","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.35.tgz","fileCount":51,"integrity":"sha512-4VXmMnf9YVO/a9/y5LG6aW2mU3tO/pYX+W5KQHCs9QlvSp/CWNI6k3RBGbIG5r6pm9EnFth70RUUtgYYAD3EWA==","signatures":[{"sig":"MEQCIFdC/GJfP3axfJ/rCpUuIJOmshf+bI1XrmueS7Qs/tPcAiBeEducBsNdTGTi2+R8oH2XNynmONXO3VgCBYGKtUNUnA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1301566},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.35_1788149523298_0.9500547135329349","host":"s3://npm-registry-packages-npm-production"}},"0.1.36":{"name":"xiaodao-spreader","version":"0.1.36","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.36","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"88272c91a81cef2576b76b36c06a21beb641b50b","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.36.tgz","fileCount":53,"integrity":"sha512-sLu4NPVfP6/vjxl++W4LJ6Fl9TFUYdTjnrjstLMBTCbXhctZLvnL0rSBw74oeodRtf0XLKNRrS0PgsdMBF3gwA==","signatures":[{"sig":"MEUCIQCpcYwVrtk7mqpVdWtUU46W3gLqsmKl6SylfNYV6lGwtAIgSVW7rSlmduPtFK1OMSuTSC4EzoN9lV14idheLCHkc3I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1379922},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.36_1788174875484_0.8258878651834967","host":"s3://npm-registry-packages-npm-production"}},"0.1.37":{"name":"xiaodao-spreader","version":"0.1.37","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.37","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"a4cba2b9634d0ecb9726eeab9ebdf4fe1f4c453e","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.37.tgz","fileCount":54,"integrity":"sha512-GpeAEXPm1hAUyY5dRGhQZWJ62w4jmm339dipXKA7poM5gQnghGo92KfluD6TNFtAJRtyaPGnUWRmScnl47Jh3g==","signatures":[{"sig":"MEUCIDmwsIlBBVNj4IhzlY2YWCf2JdLdtvWQRaeusf6Neu7kAiEA1A0vrO2vCzCwpI97DB9eVfqfbdDZIozHTnKmOAR9sWw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1398075},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.37_1788245672706_0.993888727592799","host":"s3://npm-registry-packages-npm-production"}},"0.1.38":{"name":"xiaodao-spreader","version":"0.1.38","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.38","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"5fd279cf5d00b601290578c8577a962f1e90ad6d","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.38.tgz","fileCount":56,"integrity":"sha512-grtZuhZDKXf+VjoBkaWPWToMCTxAid+HCeE9bKKUfkWdYsTP2ciHzfD4i8XlktEFtiEa8wWHqz4aH2uon3Iy7Q==","signatures":[{"sig":"MEUCIQCeg52mp+CRvUFke2r2VkUeRyAGdKBKMkwWUpGAhoWUzgIgA/9iCmo8jtMDu/HkqW+4Op9szveghMf2fZCqB0VFarg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1439213},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.38_1788261486174_0.5903906926085825","host":"s3://npm-registry-packages-npm-production"}},"0.1.41":{"name":"xiaodao-spreader","version":"0.1.41","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.41","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"64aab3db44b99a7da0dbe414d43868505ae61620","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.41.tgz","fileCount":62,"integrity":"sha512-Uv2TsRvb5K1qHeTdZThTZf4q/qAjyPb/G0THVVFTAjq/drjIGJiDDPcj1vJGkfdbErfnoT+2Du4b19B4x6rkfg==","signatures":[{"sig":"MEUCIG3XVSPhddBPeiqh/5CeyA21/VZEhKXeCPaQBs0x7KpkAiEAw74FF9hYrJGHPd0L+TLqDOMD7WTc+IXBFM5beHcMMIo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1519971},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.41_1788343861480_0.507500511939273","host":"s3://npm-registry-packages-npm-production"}},"0.1.42":{"name":"xiaodao-spreader","version":"0.1.42","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.42","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"6f4440aec2bf122119852a2e4521b9b640fc87c5","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.42.tgz","fileCount":62,"integrity":"sha512-Y9NpOP/Fac4k6Au2xv/CTdNNBt/zAJUHz3y6olUZu40i3AnTkvFA8xjXKBhnMSZe3GSkhrUmDBBiCIs8bIBl1g==","signatures":[{"sig":"MEYCIQDSXdJ8KOZFdQXa3lf5IvHM60zn7/V9V6EPGzl8EexMdwIhAKFeXxhEazqKbCegtlvZVvWNenG0s79KlMIvI5td7uUb","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1520210},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A Vue 3 component for spreading sheets","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.42_1788347614162_0.12667890120581404","host":"s3://npm-registry-packages-npm-production"}},"0.1.43":{"name":"xiaodao-spreader","version":"0.1.43","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.43","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"4b8b43167710bf1d4c59775f9d74c1b5687bc80d","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.43.tgz","fileCount":63,"integrity":"sha512-bM+uVd67fDm8XjTetJ15gFAbwhQtzWQO/XtGxFiVa2qBeRT1C8B0hkc/FlXCZn61YFVH4ZSahvA+j8u7UR3VkA==","signatures":[{"sig":"MEUCIDV7MSJU6yjHR3Cq1PPw87hMfJ5DTR3sIlNrCklMjQiWAiEAmsEKOFJHDSJqLwTqeU6GXkAwVxtGgYGrcKv6srcKSdw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1526889},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A high-performance, canvas-based spreadsheet component for Vue 3: bringing an Excel-like editing experience to the web. Keep developing!","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.43_1788407790829_0.39745109409200263","host":"s3://npm-registry-packages-npm-production"}},"0.1.44":{"name":"xiaodao-spreader","version":"0.1.44","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"license":"MIT","_id":"xiaodao-spreader@0.1.44","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","dist":{"shasum":"90d6ea436226ac5aba70e187f2d391678832fcc6","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.44.tgz","fileCount":63,"integrity":"sha512-Z/yytDqhbvSauurTNKrIgKOruRdryDUaW/kumofp7e0jYZASn4OdehIrzhFWXsV2eNoOoMOjZEhwZW0PpH3uuA==","signatures":[{"sig":"MEUCIDf5fMijecrddZY43d1hoj24ICRUwXiPy66m9DShy4gSAiEAonx7Wl6jRSH/lIFxdYLGYA/7nglMqfatw5cO7GL7ULQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1533134},"main":"./dist/xiaodao-spreader.umd.js","type":"module","types":"./dist/types/index.d.ts","module":"./dist/xiaodao-spreader.es.js","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"scripts":{"dev":"vite","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\"","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","preview":"vite preview","build:demo":"vite build --mode demo","type-check":"vue-tsc --noEmit"},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"repository":{"url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git","type":"git"},"description":"A high-performance, canvas-based spreadsheet component for Vue 3: bringing an Excel-like editing experience to the web. Keep developing!","directories":{},"sideEffects":["*.vue","*.css"],"_nodeVersion":"24.19.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"vue":"^3.4.0","vite":"^5.0.0","vue-tsc":"^2.2.0","typescript":"~5.4.0","@types/node":"^20.0.0","@vitejs/plugin-vue":"^5.0.0"},"peerDependencies":{"vue":"^3.4.0"},"_npmOperationalInternal":{"tmp":"tmp/xiaodao-spreader_0.1.44_1788414654850_0.08779758695861872","host":"s3://npm-registry-packages-npm-production"}},"0.1.45":{"name":"xiaodao-spreader","version":"0.1.45","description":"A high-performance, canvas-based spreadsheet component for Vue 3: bringing an Excel-like editing experience to the web. Keep developing!","type":"module","license":"MIT","homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"main":"./dist/xiaodao-spreader.umd.js","module":"./dist/xiaodao-spreader.es.js","types":"./dist/types/index.d.ts","exports":{".":{"types":"./dist/types/index.d.ts","import":"./dist/xiaodao-spreader.es.js","require":"./dist/xiaodao-spreader.umd.js"}},"sideEffects":["*.vue","*.css"],"peerDependencies":{"vue":"^3.4.0"},"devDependencies":{"@vitejs/plugin-vue":"^5.0.0","@types/node":"^20.0.0","typescript":"~5.4.0","vite":"^5.0.0","vue":"^3.4.0","vue-tsc":"^2.2.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"repository":{"type":"git","url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git"},"scripts":{"dev":"vite","build":"vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json","build:demo":"vite build --mode demo","preview":"vite preview","type-check":"vue-tsc --noEmit","test":"tsc -p tsconfig.test.json && node -e \"require('fs').writeFileSync('dist-test/package.json','{\\\"type\\\":\\\"commonjs\\\"}')\" && node --test \"dist-test/test/*.test.js\""},"_nodeVersion":"24.19.0","_id":"xiaodao-spreader@0.1.45","dist":{"integrity":"sha512-kidf3ysKkhDdrLXLoY/L3Z23xNt9TJHRMNjatb6KDXqj8x5n9xe5soSDPH/78xm7+Wn5XNKk3FvnXdAUcg4aoQ==","shasum":"b61b99029f419f68f41df969ac9d2cf68cbb654c","tarball":"https://registry.npmjs.org/xiaodao-spreader/-/xiaodao-spreader-0.1.45.tgz","fileCount":63,"unpackedSize":1561612,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAKBFbvkwV4a08iBLjiQo+2CiXMAYzsOOd/fqw7hte1IAiAP1dVmRDLmtVZcWjUE7rDu4cb6Sfsw2CFyCjuQNkMFYQ=="}]},"_npmUser":{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"},"directories":{},"maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/xiaodao-spreader_0.1.45_1788427792103_0.3274897915640378"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-18T07:16:14.921Z","modified":"2026-09-03T09:29:52.430Z","0.1.2":"2026-08-18T07:16:15.915Z","0.1.3":"2026-08-20T05:55:33.187Z","0.1.4":"2026-08-20T09:46:59.724Z","0.1.5":"2026-08-21T08:12:38.497Z","0.1.6":"2026-08-21T08:56:33.011Z","0.1.7":"2026-08-21T10:46:25.811Z","0.1.8":"2026-08-21T11:03:30.147Z","0.1.9":"2026-08-21T16:16:06.273Z","0.1.10":"2026-08-23T10:17:53.035Z","0.1.11":"2026-08-24T11:01:55.198Z","0.1.12":"2026-08-24T12:29:58.970Z","0.1.13":"2026-08-24T14:18:02.900Z","0.1.14":"2026-08-24T14:23:04.348Z","0.1.15":"2026-08-24T14:40:27.428Z","0.1.16":"2026-08-25T03:07:00.124Z","0.1.17":"2026-08-25T04:38:43.985Z","0.1.18":"2026-08-25T05:18:54.041Z","0.1.19":"2026-08-25T05:52:34.906Z","0.1.20":"2026-08-25T10:16:40.636Z","0.1.21":"2026-08-25T11:05:23.692Z","0.1.25":"2026-08-26T07:06:41.054Z","0.1.26":"2026-08-26T07:52:51.018Z","0.1.27":"2026-08-26T10:47:54.120Z","0.1.28":"2026-08-27T06:36:18.813Z","0.1.29":"2026-08-27T08:38:07.944Z","0.1.30":"2026-08-27T15:39:55.376Z","0.1.31":"2026-08-28T02:55:00.678Z","0.1.32":"2026-08-28T03:54:47.536Z","0.1.33":"2026-08-28T10:43:05.067Z","0.1.34":"2026-08-28T11:09:18.778Z","0.1.35":"2026-08-31T04:12:03.424Z","0.1.36":"2026-08-31T11:14:35.688Z","0.1.37":"2026-09-01T06:54:32.882Z","0.1.38":"2026-09-01T11:18:06.338Z","0.1.41":"2026-09-02T10:11:01.629Z","0.1.42":"2026-09-02T11:13:34.341Z","0.1.43":"2026-09-03T03:56:30.963Z","0.1.44":"2026-09-03T05:50:54.985Z","0.1.45":"2026-09-03T09:29:52.246Z"},"license":"MIT","homepage":"https://xiaodaozhi.com/xiaodao-spreader.html","keywords":["vue","vue3","vue-component","spreadsheet","excel","sheet","grid","data-grid","table","canvas","cell","edit-table","电子表格","表格组件","工作表","单元格","数据表格","在线表格"],"repository":{"type":"git","url":"git+https://github.com/xiaodaozhi/xiaodao-spreader.git"},"description":"A high-performance, canvas-based spreadsheet component for Vue 3: bringing an Excel-like editing experience to the web. Keep developing!","maintainers":[{"name":"leeqwind","email":"leeqwind@xiaodaozhi.com"}],"readme":"# Xiaodao Spreader\r\n\r\n[中文](./README.ZH.md) | **English** | [Demo](https://spreader.xdz.me)\r\n\r\n[![Downloads](https://img.shields.io/npm/d18m/xiaodao-spreader)](https://www.npmjs.com/package/xiaodao-spreader)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\r\n[![Vue 3](https://img.shields.io/badge/Vue-3.4+-42b883.svg)](https://vuejs.org/)\r\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.4+-3178C6.svg)](https://www.typescriptlang.org/)\r\n[![Vite](https://img.shields.io/badge/Vite-5.0+-646CFF.svg)](https://vitejs.dev/)\r\n\r\nA high-performance, canvas-based spreadsheet component for Vue 3: bringing an Excel-like editing experience to the web. It supports full cell editing, formula evaluation with relative/absolute/mixed references, clipboard cut/copy/paste, merge cells, frozen panes, number formatting, borders, find & replace, sorting, and auto-fill: all rendered on a single virtualized canvas with smooth scrolling across hundreds of thousands of rows. The pure-logic core (formula engine, sort, find-replace, auto-fill) is fully decoupled from Vue/Canvas and unit-tested, making it easy to embed or reuse across projects.\r\n\r\n![Preview](./img/preview.png)\r\n\r\n---\r\n\r\n## Features\r\n\r\n### Core Spreadsheet\r\n- **Dynamic Sheet Expansion**: Excel-like dynamic row/column expansion; default 26 columns (A-Z) × 200 rows, automatically expands when scrolling near boundaries, inputting at edges, pasting beyond current range, or inserting rows/columns that would push data out of bounds\r\n- **Canvas 2D Rendering**: High-DPI aware with DPR scaling, virtual viewport rendering for dynamically-sized sheets\r\n- **Multi-Sheet Workbook**: Tab bar with add, rename, duplicate, delete, reorder\r\n- **Formula Engine**: `=SUM()`, `=AVERAGE()`, `=COUNT()`, `=IF()`, `=VLOOKUP()`, `=CONCATENATE()` with dependency tracking and circular-reference detection; toolbar and context menu provide one-click sum/average/count\r\n- **Merge Cells**: Merge & Center, Merge Across, Unmerge; merged-region borders stored at the anchor, shared borders resolved at render time\r\n- **Freeze Panes**: Pin frozen top rows / left columns so they keep visible while the body scrolls. The toolbar \"Freeze Panes\" dropdown exposes *Freeze Panes* (freezes at the top-left corner of the current selection / active cell: Excel's \"Freeze Panes\" behavior), *Freeze First Row*, *Freeze First Column*, and *Unfreeze* (shown only when a pane is already frozen, replacing the \"Freeze Panes\" entry). Per-sheet view state (`freeze: { rows, cols }`) persisted through v-model; merged cells straddling the freeze line are handled correctly: only the frozen portion stays pinned, the rest scrolls away\r\n- **Rich Cell Formatting**: Font family, font size (5–72), bold, italic, underline, strikethrough, text color, fill color, horizontal & vertical alignment, wrap text\r\n- **Borders**: Top / bottom / left / right / outside / all / none with 5 predefined styles, custom color, and per-side line type (solid / dashed / dotted); stored in a dedicated border pool, shared borders resolved at render time\r\n- **Undo / Redo**: Full state snapshots for cells, column widths, and row heights (50 steps)\r\n- **Format Painter**: Copy & apply cell formatting across ranges\r\n- **Number Format**: Excel-style number formatting (General / Text / Number / Currency / Accounting / Percent / Scientific / Date / Time / DateTime / Duration) with a custom format dialog; display-only, never mutates the stored cell value\r\n- **Smart Data Recognition**: Typing `100%`, `1,234`, `¥1,234.56` auto-converts the text to a number and applies the matching format; common date/time text auto-converts to dates: matching Excel input behavior\r\n- **Sorting & Sort Warning**: Sort any column by its **displayed content** (numbers / dates / text); sorting moves data only, never cell styles; ranges containing merged cells or formulas are auto-disabled; when adjacent data sits outside the selection, an Excel-style **Sort Warning** dialog lets you choose \"Expand the selection\" or \"Sort the current selection only\"\r\n- **Auto Filter (AutoFilter)**: Excel-style auto filter on a normal range. Enable via the toolbar **Data → Filter** or `Ctrl+Shift+L`; select a data cell (or a single-row multi-column range) and the filter is created by intelligently probing the contiguous data region **downward** from that header row. Each column header shows a filter drop-down arrow; opening it reveals the filter panel (values / text / number / date / search / blanks / multi-column AND). Clearing one column's criteria clears only that column; removing the AutoFilter clears everything. Only columns inside the Filter Range get an arrow; selecting a single merged cell with no active filter disables the filter button - *see [Auto Filter (AutoFilter)](#auto-filter-autofilter)*\r\n- **Find & Replace**: Open via the toolbar find button or `Ctrl/Cmd+F` (also `Ctrl/Cmd+H`); three scopes: current sheet / entire workbook / current selection; match case and match entire cell; highlights all matches and locates the active one with wrap-around navigation; single and replace-all both integrate with undo/redo, mutating only the raw `value` (always kept a string), never format / border / merge\r\n- **Conditional Formatting**: Excel-style conditional formatting rules stored per-sheet. The toolbar \"Conditional Formatting\" dropdown offers preset rules (greater than / less than / between / text contains / duplicate / unique / blank / not blank) and a \"New Rule\" dialog with cell value and formula-based conditions. Rules render as temporary style overlays on top of the base cell style - no mutation of the underlying cell `value` or `styleId`. Rule priority (smaller number = higher), `stopIfTrue` semantics, and automatic cache invalidation on cell value change. Inserting / deleting rows or columns adjusts rule ranges and formula references via the same `shiftFormulaRefs` engine used by auto-fill. Includes a \"Manage Rules\" dialog for editing, reordering, and deleting rules; the \"Clear Rules\" sub-dialog lets you clear all rules or rules from selected ranges. Render-time style synthesis correctly composes CF background, font color, bold, italic, underline, and strikethrough with the base cell style. *see [Conditional Formatting](#conditional-formatting)*\r\n- **Data Validation**: Excel-style data validation rules stored per-sheet. The toolbar \"Data Validation\" button opens a dialog to set the allowed type (any value / list / whole number / decimal / date / time / text length / custom formula), the operator (between, not between, equal, greater than, …), and the criterion values. List validation shows an in-cell dropdown with search and full keyboard navigation (↑ ↓ / Home / End / PageUp / PageDown / Enter / Esc). Per-rule input message and error alert (Stop / Warning / Information) are supported; validation runs *before* the value is committed, so Stop-level violations reject the edit while Warning/Information let the user confirm. All rules on a range must pass. Rules persist through v-model, integrate with undo/redo, and adjust automatically on row/column insert/delete. Copy/paste and Auto Fill validate atomically - a Stop violation cancels the whole operation. *see [Data Validation](#data-validation)*\r\n- **Cell Notes**: Excel-style cell notes (comments). Right-click menu to create / edit / delete; red triangle indicator at cell corner marks cells with notes; hover to preview, click to edit. Notes are independent from cell values and styles, stored via a Note Pool (Sheet-level notes pool + cell.noteId reference), so sort / insert-delete moves cells together with their notes. Notes support multi-line text, optional author, and create/update timestamps. Author name can be set via the noteAuthor prop. *see [Cell Notes](#cell-notes)*\r\n- **Auto Fill (Fill Handle)**: Excel-style fill handle at the bottom-right corner of the active selection. Drag it up/down/left/right to fill cells: single values copy, number/date/text-number sequences auto-continue (e.g. `1,2 → 3,4,5`), formula references adjust per relative/absolute/mixed rules (e.g. `=A1*2` → `=A2*2`), and source `styleId` is reused via the style pool. Live preview during drag, edge auto-scroll, dynamic sheet expansion, freeze-pane compatibility, and a single undo step per operation: *see [Auto Fill](#auto-fill)*\r\n- **Row / Column Grouping & Collapsing**: Excel-style row/column outlines. Select whole rows or columns, then the toolbar \"Group\" dropdown (between Sort and Filter) offers Add Group / Ungroup / Clear Outline / Expand All / Collapse All, applied directly to the selected axis; row/column context menus expose a matching \"Group\" submenu. Only one level of non-overlapping groups is supported - nesting and partial overlap are rejected with a message. Group ranges get alternating background colors in the row/column header band; ± collapse buttons float inside the header band without reserving a separate gutter. Collapsed rows/columns are skipped during content rendering; inserting/deleting rows or columns shifts group ranges and auto-removes emptied groups. Groups persist per-sheet (`rowOutlines` / `columnOutlines`) through v-model, and every mutation integrates with undo/redo. *see [Row / Column Grouping & Collapsing](#row--column-grouping--collapsing)*\r\n- **Read-only Mode**: the `editable` prop (default `true`) toggles between full editing and a read-only view. With `editable={false}` every data / format mutation is blocked (editing, paste/cut/delete, fill, row/column insert & resize, sort/filter, CF/DV/notes, merge/borders, freeze panes, format painter, find & replace), all editing controls (toolbar, context menus, dialog confirm/insert buttons, formula bar, find & replace bar) are truly disabled, while selection, scrolling, copying, find-locate and viewing stay available. Guarding is layered (UI disabled → event gate → handler guard → underlying mutation guard) as defense in depth, runtime toggling takes effect immediately and never pollutes the undo history: *see [Read-only Mode](#read-only-mode)*\r\n\r\n### Interaction\r\n- **Smart Selection**: Click, drag, Shift+Click, row/column header select, corner-cell select-all\r\n- **Double-Click Editing**: Inline cell editor with `<textarea>` for multi-line input\r\n- **Formula Bar**: Dedicated input bar with cell label and live formula display\r\n- **Full Keyboard Navigation**: Arrow keys, Tab, Enter, Home, End, Ctrl+Home, Ctrl+End\r\n- **Context Menus**: Context-aware menus for cells, rows, columns, sheet tabs, with nested submenus\r\n- **Row / Column Operations**: Insert, delete, cut, copy, paste via right-click menu\r\n- **Column Width / Row Height**: Drag-to-resize with live preview and double-click auto-fit\r\n- **Touch Support**: Swipe scrolling, double-tap to edit\r\n- **Responsive**: ResizeObserver for dynamic container sizing\r\n\r\n### Visual\r\n- **Light / Dark Theme**: Full color palette with 50+ CSS custom properties\r\n- **Internationalization**: English & Chinese (zh-CN) out of the box\r\n- **Overflow Toolbar**: Responsive toolbar that automatically collapses overflow buttons into a dropdown menu\r\n- **Custom Scrollbars**: Native-styled scrollbars with arrow buttons and draggable thumbs\r\n\r\n---\r\n\r\n## Installation\r\n\r\n```bash\r\n# pnpm (recommended)\r\npnpm add xiaodao-spreader\r\n\r\n# npm\r\nnpm install xiaodao-spreader\r\n\r\n# yarn\r\nyarn add xiaodao-spreader\r\n```\r\n\r\n### Peer Dependencies\r\n\r\n- `vue` ^3.4.0\r\n\r\n---\r\n\r\n## Quick Start\r\n\r\n```bash\r\n# Clone the repository\r\ngit clone https://github.com/xiaodaozhi/xiaodao-spreader.git\r\ncd xiaodao-spreader\r\n\r\n# Install dependencies\r\npnpm install\r\n\r\n# Start dev server\r\npnpm dev\r\n```\r\n\r\nNavigate to `http://localhost:5173` to see the demo application.\r\n\r\n---\r\n\r\n## Basic Usage\r\n\r\n```vue\r\n<template>\r\n  <Spreader\r\n    v-model:data=\"myData\"\r\n    :row-count=\"100\"\r\n    :col-count=\"12\"\r\n    theme=\"light\"\r\n    locale=\"zh-CN\"\r\n  />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from 'vue';\r\nimport Spreader from 'xiaodao-spreader';\r\nimport type { SheetModelData } from 'xiaodao-spreader';\r\n\r\nconst myData = ref<SheetModelData[]>([\r\n  {\r\n    name: 'Sheet1',\r\n    styles: [{}, { fontSize: 14, fontWeight: 'bold' }],\r\n    cells: {\r\n      '0,0': { value: 'Name' },\r\n      '0,1': { value: 'Age' },\r\n      '1,0': { value: 'Alice', styleId: 1 },\r\n      '1,1': { value: '28' },\r\n    },\r\n    colWidths: { 0: 120, 1: 80 },\r\n  },\r\n]);\r\n</script>\r\n```\r\n\r\n---\r\n\r\n## Props\r\n\r\n| Prop | Type | Default | Description |\r\n|------|------|---------|-------------|\r\n| `data` (v-model) | `SheetModelData[]` | `[]` | Multi-sheet data (two-way binding) |\r\n| `rowCount` | `number` | `200` | Initial rows per sheet (can be exceeded dynamically) |\r\n| `colCount` | `number` | `26` | Initial columns per sheet (can be exceeded dynamically) |\r\n| `width` | `number \\| string` | - | Component width (pixels; omit or pass `string` for responsive) |\r\n| `height` | `number \\| string` | - | Component height (pixels; omit or pass `string` for responsive) |\r\n| `theme` | `'light' \\| 'dark'` | `'light'` | Theme mode |\r\n| `locale` | `string` | `'zh-CN'` | Language: `'zh-CN'` \\| `'en-US'` |\r\n| `noteAuthor` | `string` | `''` | Current note author name; when empty, saved notes have empty author field that renders as i18n placeholder |\r\n| `editable` | `boolean` | `true` | Whether editing is allowed; `false` enters read-only mode (see [Read-only Mode](#read-only-mode)) |\r\n\r\n---\r\n\r\n## Read-only Mode\r\n\r\nPass the `editable` prop to switch the component into a read-only view (default `true`, i.e. fully editable). With `editable={false}`:\r\n\r\n- **Every mutation is blocked**: cell editing and direct typing, paste / cut / delete, the fill handle, row / column insert & resize, sorting & filtering, conditional formatting, data validation, note add/edit/delete, merge cells, borders, font / alignment / fill / text color, number format, format painter, freeze panes, find & replace, and undo / redo.\r\n- **Viewing stays available**: selection & multi-range selection, scrolling, frozen-pane viewing, copying, inspecting cell content / format / notes, and find navigation (previous / next) are unaffected.\r\n- **UI stays consistent with logic**: every editing control (toolbar buttons & dropdowns, context-menu items, dialog confirm / insert buttons, formula-bar buttons, find & replace buttons and the \"replace with\" input) is truly disabled or read-only; the moment read-only is switched on, any open editing overlay or dialog closes automatically - no more \"buttons look clickable but do nothing\".\r\n- **Defense in depth**: four guard layers - ① UI `:disabled` / readonly (UX) → ② toolbar emit gate & event interception → ③ guard at the top of each handler → ④ underlying mutation guards (last line of defense). Removing the HTML `disabled` attribute via DevTools cannot bypass the guards, so the data can never be rewritten; read-only never pushes undo snapshots, so the undo history stays unpolluted.\r\n- **Runtime toggling takes effect immediately** without remounting; the `v-model` data and formatting are untouched and editing works as usual after switching back.\r\n\r\n```vue\r\n<template>\r\n  <button @click=\"editable = !editable\">\r\n    {{ editable ? 'Switch to read-only' : 'Switch to editable' }}\r\n  </button>\r\n  <Spreader v-model:data=\"myData\" :editable=\"editable\" />\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\nimport { ref } from 'vue';\r\nimport Spreader from 'xiaodao-spreader';\r\nimport type { SheetModelData } from 'xiaodao-spreader';\r\n\r\nconst myData = ref<SheetModelData[]>([]);\r\nconst editable = ref(true);\r\n</script>\r\n```\r\n\r\n## Data Model\r\n\r\n### `SheetModelData`\r\n\r\nThe external data format used for v-model two-way binding:\r\n\r\n```typescript\r\ninterface SheetModelData {\r\n  name: string;\r\n  styles?: CellStyle[];\r\n  borders?: BorderStyle[];\r\n  cells: Record<string, {\r\n    value: string;\r\n    styleId?: number;\r\n    /** Note reference pointing to a CellNote in the Sheet-level notes pool */\r\n    noteId?: string;\r\n  }>;\r\n  merges?: Record<string, SelectionRange>;\r\n  freeze?: { rows: number; cols: number };\r\n  colWidths?: Record<number, number>;\r\n  rowHeights?: Record<number, number>;\r\n  // Grid dimensions (colCount/rowCount) are not persisted: they are derived from\r\n  // content on load (deriveModelDims), at least the props default 26x200, then\r\n  // extended by data / custom row/column sizes / rule ranges\r\n  /** Cell notes pool: CellNote objects keyed by noteId; cell.noteId references into this pool */\r\n  notes?: Record<string, CellNote>;\r\n}\r\n```\r\n\r\n- **`styles`**: Style pool: `styles[0]` is always the default empty style `{}`. Cells reference styles by index (`styleId`).\r\n- **`borders`**: Border pool: `borders[0]` is always the default empty border `{}`. Styles reference borders by index (`borderId`); auto-migrated from legacy inline border props when omitted.\r\n- **`cells`**: Key is `\"col,row\"` (e.g., `\"0,0\"` for cell A1). `styleId` references into the `styles` array; `styleId=0` or omitted means default style.\r\n- **`merges`**: Merge cell definitions, keyed by merge anchor cell.\r\n- **`freeze`**: View state for frozen panes: `{ rows, cols }` freezes the top `rows` rows and the left `cols` columns; `{ rows: 0, cols: 0 }` means no freeze. Persisted per sheet and restored on sheet switch.\r\n- **`colWidths` / `rowHeights`**: Sparse maps: only stores non-default values.\r\n\r\n### Type Exports\r\n\r\n```typescript\r\nimport type {\r\n  CellCoord,       // { col: number; row: number }\r\n  SelectionRange,  // { startCol; startRow; endCol; endRow }\r\n  CellData,        // { value: string; styleId?: number }\r\n  CellStyle,       // Typed style interface (font, color, border, alignment, etc.)\r\n  BorderStyle,     // Four-side border { top; right; bottom; left }\r\n  BorderSide,      // Single border side { width; color; style; owner? }\r\n  BorderSource,    // Border source 'cell' | 'merge'\r\n  Range,           // { start: number; end: number }\r\n  SpreadsheetOptions,\r\n  SpreadsheetData,\r\n  SheetModelData,  // ← main data interface\r\n  SheetState,      // internal runtime state\r\n  UndoSnapshot,\r\n  ContextMenuItem,\r\n  ThemeColors,\r\n  Point,\r\n} from 'xiaodao-spreader';\r\n\r\n// Runtime utilities\r\nimport { StylePool, resolveStyle, migrateCells, cloneCells } from 'xiaodao-spreader';\r\n```\r\n\r\n---\r\n\r\n## Architecture\r\n\r\n```\r\nsrc/\r\n├── index.ts                          # Library entry: re-exports from spreader/\r\n├── App.vue                           # Demo application\r\n└── components/\r\n    └── spreader/\r\n        ├── index.ts                  # Unified export: component + types (barrel)\r\n        ├── theme.css                 # Global theme stylesheet: --sp-* variables (.spreadsheet-outer / .sp-spreader-overlay scope, light + dark pairs)\r\n        ├── components/\r\n        │   ├── spreader.vue         # Entry component: template + style + composition\r\n        │   ├── toolbar.vue          # Toolbar with overflow dropdown\r\n        │   ├── tabbar.vue           # Sheet tab bar\r\n        │   ├── dropdown.vue         # Generic dropdown component\r\n        │   ├── find-replace-bar.vue # Find/replace bar UI\r\n        │   ├── note-overlay.vue     # Note view/edit overlay (dual-mode: view + edit)\r\n        │   └── pickers/\r\n        │       ├── border-picker.vue                  # Border picker (per-side type/color/line style + submenus)\r\n        │       ├── calc-picker.vue                    # Sum / average / count picker\r\n        │       ├── color-palette.vue                  # Shared color swatch palette for text / fill / border\r\n        │       ├── color-picker.vue                   # Text & fill color picker\r\n        │       ├── conditional-format-manager.vue     # Conditional formatting \"Manage Rules\" dialog\r\n        │       ├── conditional-format-menu.vue        # Conditional formatting toolbar dropdown (presets + new / manage / clear rules)\r\n        │       ├── conditional-format-rule-editor.vue # Conditional formatting \"New / Edit Rule\" dialog\r\n        │       ├── data-validation-alert.vue          # Data validation error alert (Stop / Warning / Information)\r\n        │       ├── data-validation-dialog.vue         # Data validation settings dialog\r\n        │       ├── data-validation-dropdown.vue       # Data validation list dropdown (search + virtual list + keyboard)\r\n        │       ├── data-validation-input-message.vue  # Cell-focus input message tooltip\r\n        │       ├── filter-popup.vue                   # Auto Filter panel (values / text / number / date + search + blanks + multi-column AND)\r\n        │       ├── insert-function-dialog.vue         # Insert function dialog\r\n        │       ├── merge-picker.vue                   # Merge cell picker\r\n        │       ├── number-format-dialog.vue           # Number format dialog\r\n        │       ├── outline-picker.vue                 # Toolbar \"Group\" dropdown (add / ungroup / clear, expand / collapse)\r\n        │       ├── sort-confirm-dialog.vue            # Excel-style sort warning dialog\r\n        │       └── sort-picker.vue                    # Sort dropdown\r\n        ├── composables/\r\n        │   ├── borders-merge.ts       # Border ops, merge ops, clipboard, sum/avg/count\r\n        │   ├── core-state.ts          # Props, cells/merges/selection, font metrics, navigation, outline state\r\n        │   ├── find-replace.ts        # Find/replace state & interaction (Vue-dependent)\r\n        │   ├── interactions.ts        # Renderer, formula bar, tab bar, context menu, scrollbar, events\r\n        │   ├── sheets-ops.ts          # Row/col ops, multi-sheet, v-model emit, refs\r\n        │   ├── undo-styles.ts         # Undo/redo, format painter, font/alignment/color\r\n        │   └── float-menu-position.ts # Shared toolbar dropdown positioning (right-anchor + flip/clamp)\r\n        └── core/\r\n            ├── autofill.ts               # Auto-fill pure engine (pattern inference, fill handle, zero Vue deps)\r\n            ├── border-color.ts           # Per-side border color: color decoupled from line type, plan color changes\r\n            ├── border-icon.ts            # Border icon single source (toolbar + picker)\r\n            ├── border-pool.ts            # Border pool: dedup, registration, resolve, migration, GC\r\n            ├── border-resolve.ts         # Shared-border conflict resolution (resolveSharedBorder)\r\n            ├── border-style.ts           # Border line type (solid / dashed / dotted): normalize + dash pattern\r\n            ├── conditional-formatting.ts # Conditional formatting engine (condition eval + rule cache, pure)\r\n            ├── constants.ts              # Layout constants, i18n text, theme color palette\r\n            ├── data-validation.ts        # Data validation engine (pure)\r\n            ├── filter-core.ts            # AutoFilter engine (pure, cascading candidates)\r\n            ├── find-replace-core.ts      # Find/replace pure algorithms (zero Vue deps, unit-testable)\r\n            ├── formula.ts                # Formula engine (parsing, evaluation, dependency tracking)\r\n            ├── model-dims.ts             # Model dimensions derived from content (pure)\r\n            ├── notes.ts                  # Note pool management: CRUD, persistence, undo integration\r\n            ├── number-format.ts          # Number format engine (Excel-style display formatting)\r\n            ├── outline-core.ts           # Row/column grouping pure engine (validation / shifting / collapse)\r\n            ├── sort-core.ts              # Sort pure algorithms (zero Vue deps, unit-testable)\r\n            ├── sort-icon.ts              # Sort icon single source (toolbar + picker)\r\n            ├── style-pool.ts             # Style pool: dedup, registration, resolve, migration, GC\r\n            ├── theme.ts                  # Theme types + light/dark palettes (for Canvas); buildOuterStyle now returns size only\r\n            ├── types.ts                  # All type definitions\r\n            └── utils.ts                  # Pure utilities (column label, hit test, resolve size)\r\n```\r\n\r\n### Design Principles\r\n\r\n- **Sparse Data Model**: Only cells with actual data are stored; expanding the logical range does not create empty cells\r\n- **Dynamic Range**: Each sheet maintains a reactive logical range (`colCount`/`rowCount`) that starts from the `colCount`/`rowCount` props (default 26/200) and grows as needed via `ensureCapacity(minCol, minRow)`. Expansion uses buffer steps (8 columns / 32 rows) to reduce frequent resize overhead\r\n- **Composition API**: All business logic extracted into `composables/`, maintaining single-responsibility modules\r\n- **Barrel Export**: `spreader/index.ts` centralizes all component and type exports; `src/index.ts` re-exports everything, so consumers import uniformly from `xiaodao-spreader`\r\n- **Canvas 2D Rendering**: Only visible cells are drawn (virtual rendering), ensuring smooth performance on large sheets\r\n- **No Dirty Flags**: Manual `scheduleRender()` calls at interaction end-points; `requestAnimationFrame` automatically merges multiple calls within the same frame\r\n- **Style Pool**: Each sheet maintains a `styles: CellStyle[]` array; cells reference styles via `styleId` (array index). Identical styles are automatically deduplicated. Runtime style resolution via `resolveStyle()` / `registerStyle()`; GC (`compactStyles`) runs only at save/export time\r\n- **Border Pool**: Borders are stored separately from regular styles in a per-sheet `borders: BorderStyle[]` pool; styles reference borders via `borderId` (array index). Adjacent shared borders are resolved at render time via `resolveSharedBorder()`; setting a border no longer mutates neighboring cells\r\n- **Shared State**: A central `CoreState` object is injected into each composable, enabling cross-module communication without tight coupling\r\n- **Reactive Wrap**: Composable return values are wrapped in `reactive()` for automatic ref/computed unwrapping in templates\r\n\r\n---\r\n\r\n## Keyboard Shortcuts\r\n\r\n### Navigation\r\n\r\n| Keys | Action |\r\n|------|--------|\r\n| `↑` `↓` `←` `→` | Move active cell |\r\n| `Tab` / `Shift+Tab` | Move right / left |\r\n| `Enter` / `Shift+Enter` | Move down / up |\r\n| `Home` / `End` | Jump to first / last column |\r\n| `Ctrl+Home` / `Ctrl+End` | Jump to A1 / bottom-right |\r\n| `PageUp` / `PageDown` | Scroll one page up / down |\r\n\r\n### Editing\r\n\r\n| Keys | Action |\r\n|------|--------|\r\n| `F2` / `双击` / `直接输入` | Enter edit mode |\r\n| `Enter` (in edit) | Commit and move down |\r\n| `Tab` (in edit) | Commit and move right |\r\n| `Escape` (in edit) | Cancel edit |\r\n| `Ctrl+Enter` | Line break in multi-line cells |\r\n| `Delete` / `Backspace` | Clear selection |\r\n\r\n### Clipboard & History\r\n\r\n| Keys | Action |\r\n|------|--------|\r\n| `Ctrl+C` / `Ctrl+X` / `Ctrl+V` | Copy / Cut / Paste |\r\n| `Ctrl+Z` / `Ctrl+Y` | Undo / Redo |\r\n| `Ctrl+A` | Select all |\r\n| `Ctrl+Shift+L` | Toggle Auto Filter |\r\n\r\n### Formatting\r\n\r\n| Keys | Action |\r\n|------|--------|\r\n| `Ctrl+B` | Bold |\r\n| `Ctrl+I` | Italic |\r\n| `Ctrl+U` | Underline |\r\n\r\n---\r\n\r\n## Formula Engine\r\n\r\n### Supported Formulas\r\n\r\n| Formula | Syntax | Description |\r\n|---------|--------|-------------|\r\n| `SUM` | `=SUM(A1:B5)` | Range summation |\r\n| `AVERAGE` | `=AVERAGE(A1:B5)` | Range average |\r\n| `COUNT` | `=COUNT(A1:B5)` | Count numeric cells in range |\r\n| `IF` | `=IF(A1>5, A1*2, 0)` | Conditional branching; supports comparison operators (`> < >= <= = <>`) and arithmetic |\r\n| `VLOOKUP` | `=VLOOKUP(value, A1:C5, 2, FALSE)` | Vertical lookup; exact match by default, `TRUE` for approximate match |\r\n| `CONCATENATE` | `=CONCATENATE(A1, \" \", B1)` | Concatenate multiple values into a string |\r\n| Absolute ref | `$A$1` | Lock column and row |\r\n| Mixed ref | `$A1`, `A$1` | Lock column or row only |\r\n\r\n### Dependency Tracking\r\n\r\nThe `FormulaDeps` class maintains a bidirectional dependency graph:\r\n\r\n- **Forward**: `formulaKey` → `[depKey, ...]`: which cells a formula references\r\n- **Reverse**: `depKey` → `Set<formulaKey>`: which formulas depend on a cell\r\n\r\nWhen a cell changes, dirty flags propagate through the reverse graph. Circular references are detected via a separate `inProgress` set and return `#ERROR`.\r\n\r\n### Reference Offsetting During Paste\r\n\r\n`shiftFormulaRefs()` automatically adjusts cell references in formulas when pasting, with `$` absolute reference locking.\r\n\r\n---\r\n\r\n## Number Format\r\n\r\nAn Excel-style number formatting engine (`spreader/core/number-format.ts`) that controls **how a cell value is displayed**: it never mutates the stored `value` (which always remains a raw string).\r\n\r\n### Categories\r\n\r\n| Category | Example display | Format code |\r\n|----------|-----------------|-------------|\r\n| General | Auto (numbers, sci-notation for very large/small) | `` (empty) |\r\n| Text | Verbatim | `@` |\r\n| Number | `1,234.56` | `#,##0.00` |\r\n| Percent | `12.34%` | `0.00%` |\r\n| Scientific | `1.23E+03` | `0.00E+00` |\r\n| Currency | `¥1,234.56` / `$1,234.56` | `¥#,##0.00` |\r\n| Currency (rounded) | `¥1,235` | `¥#,##0` |\r\n| Accounting | `(¥1,234.56)` for negatives | `¥#,##0.00;(¥#,##0.00);¥\"-\"` |\r\n| Financial | `[Red](#,##0.00)` for negatives | `#,##0.00;[Red](#,##0.00)` |\r\n| Date | `2026年8月24日` / `8/24/2026` | `yyyy\"年\"m\"月\"d\"日\"` |\r\n| Time | `13:45:30` | `h:mm:ss` |\r\n| Date & Time | `2026年8月24日 13:45:30` | `yyyy\"年\"m\"月\"d\"日\" h:mm:ss` |\r\n| Duration | `26:30:00` | `[h]:mm:ss` |\r\n| Custom | User-defined Excel-style code | - |\r\n\r\n### How it works\r\n\r\n- **Storage**: the format code is stored per-cell in the resolved style's `numberFormat` property (a string). Omitting the property (or empty string) means General.\r\n- **UI**: the toolbar number-format dropdown applies presets to the current selection; the **「Format…」(格式…)** item opens `numberFormatDialog.vue` for a custom code, decimals, and thousands separator.\r\n- **Display**: `formatNumber(value, format, locale)` parses the code (cached), applies thousands separators / decimals / percent scaling / date-serial conversion, and returns the display string. Invalid date/duration serials render as `###`.\r\n- **Alignment**: numeric formats default to right-aligned; Text and General-with-non-numeric keep left alignment: matching Excel semantics.\r\n- **i18n**: currency symbol (`¥` / `$`), month and weekday names follow the `locale` prop.\r\n\r\n---\r\n\r\n## Conditional Formatting\r\n\r\nExcel-style conditional formatting stored per-sheet in `SheetState.conditionalFormats` (array of `ConditionalFormattingRule`). The engine lives in `spreader/core/conditional-formatting.ts` - pure-logic, zero Vue/Canvas deps, with unit tests in `test/conditional-formatting.test.ts`.\r\n\r\n### Rule Structure\r\n\r\nEach rule has a stable `id`, a `condition`, a `format` override, one or more `ranges`, a numeric `priority` (smaller = higher precedence), `stopIfTrue`, and `enabled` flag. The `format` carries only visual properties (`backgroundColor`, `color`, `fontWeight`, `fontStyle`, `underline`, `strikethrough`) - it never writes back to `cell.styleId`.\r\n\r\n### Supported Condition Types\r\n\r\nPreset rules exposed via the toolbar dropdown and the \"New Rule\" dialog:\r\n\r\n| Type | Key | Description |\r\n|------|-----|-------------|\r\n| Cell value | `cellIs` | compare against threshold(s): greater than, less than, between, equal to |\r\n| Text | `textContains` / `textNotContains` / `beginsWith` / `endsWith` | string match with optional case sensitivity |\r\n| Blank | `blank` / `notBlank` | cell value is empty or whitespace-only |\r\n| Duplicate | `duplicate` | value appears more than once within rule scope |\r\n| Unique | `unique` | value appears exactly once within rule scope |\r\n| Formula | `formula` | custom formula evaluated relative to the rule anchor (e.g. `=A1>100`); supports absolute references (`$B$2`) which stay fixed during range expansion |\r\n\r\nColor scale, data bar, icon set, top/bottom N, and above/below average are type stubs (`colorScale`, `dataBar`, `iconSet`, `topBottom`, `aboveBelowAverage`) in the type system for forward compatibility; preset UI and rendering for these are planned.\r\n\r\n### Priority & Stop-If-True\r\n\r\nRules fire in ascending priority order (lowest number first). The first rule whose condition matches the cell contributes its format properties; subsequent rules add only properties not yet set. If a matched rule has `stopIfTrue: true`, the scan halts immediately for that cell.\r\n\r\n### Cache & Invalidation\r\n\r\nDuplicate / unique / top-bottom / above-below rules need a value-frequency statistic over the rule range. `CfValueCache` keyed by range+rule type computes these on first access and caches them. Any `setCellValue` in `composables/core-state.ts` invalidates the affected rule caches before the next render pass.\r\n\r\n### Insert / Delete Propagation\r\n\r\n`shiftFormulaRefsSafe` in the CF engine reuses the same `shiftFormulaRefs` function from the formula engine - so `$B$2` (absolute) stays locked while `A1` (relative) shifts. Rule ranges also expand/shrink accordingly; ranges completely removed from the sheet are auto-deleted.\r\n\r\n### Render-time Style Synthesis\r\n\r\n`resolveConditionalFormatting` is called per viewport cell inside `drawCells`. It walks all enabled rules whose ranges contain the cell, applies priority-merging, and produces a temporary `cfStyle`. `applyCfFormat` merges this onto the base resolved style, composing `backgroundColor`, `color`, `fontWeight`, `fontStyle`, `underline`, and `strikethrough` - including correct handling of merged cells (CF applies to the anchor cell and propagates to the entire merge region).\r\n\r\n### UI Components\r\n\r\n| File | Role |\r\n|------|------|\r\n| `conditional-format-menu.vue` | Toolbar dropdown: preset rules (highlight cells, blank, duplicate, unique), New Rule, Manage Rules, Clear Rules submenu. Teleport-based submenus with hover-intent (150ms debounce) for cross-gap hover transitions |\r\n| `conditional-format-rule-editor.vue` | \"New Rule\" dialog: condition type selector (reuses `SpDropdown`), threshold inputs, format panel (background color picker, text color picker, bold, italic, underline, strikethrough - all reuse toolbar picker/button styles), application range auto-filled from current selection |\r\n| `conditional-format-manager.vue` | \"Manage Rules\" dialog: list all rules for the active sheet, drag-to-reorder priority toggle, edit/delete per rule, clear all / clear selection |\r\n\r\n---\r\n\r\n## Data Validation\r\n\r\nExcel-style data validation stored per-sheet in `SheetState.dataValidations` (array of `DataValidationRule`). The engine lives in `spreader/core/data-validation.ts` - pure-logic, zero Vue/Canvas deps, with unit tests in `test/data-validation.test.ts` and `test/data-validation-integration.test.ts`.\r\n\r\n### Rule Structure\r\n\r\nEach rule has a stable `id`, a `type`, an `operator`, criterion values `formula1`/`formula2`, one or more `ranges`, `allowBlank` (ignore blanks), `showDropdown`, input-message fields (`showInputMessage`, `inputTitle`, `inputMessage`), error-alert fields (`showErrorMessage`, `errorStyle`, `errorTitle`, `errorMessage`), and `enabled`.\r\n\r\n### Supported Types & Operators\r\n\r\n| Type | Description |\r\n|------|-------------|\r\n| `any` | No constraint - selecting it on save clears validation for the range |\r\n| `list` | In-cell dropdown from fixed values or a cell range |\r\n| `wholeNumber` / `decimal` | Numeric constraint |\r\n| `date` / `time` | Date / time constraint (ISO, `YYYY年M月D日`, US `m/d/yyyy`, or Excel serial) |\r\n| `textLength` | String length constraint |\r\n| `custom` | Formula evaluated relative to the candidate cell, e.g. `=AND(B2>=0,B2<=100)` |\r\n\r\nAll value types support 8 operators: `between`, `notBetween`, `equal`, `notEqual`, `greaterThan`, `greaterThanOrEqual`, `lessThan`, `lessThanOrEqual`. `between`/`notBetween` require both `formula1` (min) and `formula2` (max); the other operators use only `formula1`.\r\n\r\n### List Source\r\n\r\nList validation resolves its items from either fixed `values` (`{ type: 'values', values: [...] }`) or a `range` reference (`{ type: 'range', range, sheetId }`) that updates dynamically when the source cells change.\r\n\r\n### Validation Flow\r\n\r\nValidation runs **before** the value is committed. `commitEdit` returns `Promise<boolean>` - `false` means a Stop-level violation rejected the edit and the editor state is preserved. Warning/Information alerts call `showValidationAlert` and await user confirmation before proceeding. When multiple rules target the same range, **all** must pass (`rules.every()`).\r\n\r\n### Range Index\r\n\r\nA spatial row-band index (`DvIndex`) maps a (row, col) lookup to candidate rules in O(1) with zero per-input allocation, so a single rule covering A1:A100000 stays cheap.\r\n\r\n### Atomic Paste / Auto Fill\r\n\r\nCopy/paste and Auto Fill compute every candidate first, run `validateCells`, and cancel the whole operation if any Stop-level violation occurs - no partial commit.\r\n\r\n### Insert / Delete Propagation\r\n\r\n`adjustDvRangeForInsert/Delete` and `translateDvRange` reuse the formula engine's `shiftFormulaRefs`, so absolute references stay fixed while relative refs shift; ranges expand/shrink and fully-removed rules auto-delete.\r\n\r\n### UI Components\r\n\r\n| File | Role |\r\n|------|------|\r\n| `data-validation-dialog.vue` | Toolbar \"Data Validation\" dialog: type/operator/value, list source, input message, error alert, apply range; validates min/max literals on save |\r\n| `data-validation-dropdown.vue` | In-cell list dropdown: virtual list, search box, full keyboard nav (↑ ↓ / Home / End / PageUp / PageDown / Enter / Esc) |\r\n| `data-validation-alert.vue` | Stop / Warning / Information alert box |\r\n| `data-validation-input-message.vue` | Hover tooltip showing the rule's input message |\r\n\r\n### Persistence & Undo\r\n\r\nRules persist through the sheet v-model (`dataValidations` field), round-trip through save/load/dup-sheet, and integrate with the undo/redo stack like any other sheet mutation.\r\n\r\n---\r\n\r\n## Row / Column Grouping & Collapsing\r\n\r\nExcel-style row/column grouping and collapsing (`spreader/core/outline-core.ts` pure engine + `composables/core-state.ts` state layer + `composables/interactions.ts` canvas rendering layer).\r\n\r\n### Data Model\r\n\r\nGroups are stored per-sheet and per-axis in `SheetState.rowOutlines` / `columnOutlines` (`DimensionOutline[]`, serialized with v-model). Each group carries a stable `id`, `start` / `end` (0-based inclusive range), `level` (always 1), and `collapsed`.\r\n\r\n### Validation Rules\r\n\r\n`validateGroup` checks before creation: at least 2 consecutive rows/columns; fully disjoint from existing groups (partial overlap reports \"group range crosses existing groups\"); nesting is rejected (`MAX_OUTLINE_LEVEL = 1`). Ungrouping requires the selection to fully cover at least one group, otherwise a hint is shown.\r\n\r\n### Rendering & Collapse\r\n\r\nGroup ranges get alternating background colors in the row/column header band; ± collapse buttons (~9px) float inside the header band without reserving a separate gutter. Collapsed rows/columns are skipped during content, border, and header-text rendering (0-size guard against ghost stripes), compatible with scrolling and frozen panes.\r\n\r\n### Entry Points\r\n\r\n- Toolbar \"Group\" dropdown (between Sort and Filter): enabled only when whole rows or columns are selected; menu items (Add Group / Ungroup / Clear Outline / Expand All / Collapse All) act directly on the selected axis\r\n- Row/column context menu \"Group\" submenu: dispatches the same items for the right-clicked axis\r\n\r\n### Propagation & Undo\r\n\r\nInserting/deleting rows or columns shifts group ranges via `addOutlineForInsert` / `addOutlineForDelete`; fully-emptied groups are auto-removed. Group create / ungroup / clear / collapse each produce one undo step. Validation failures prefer the host-injected in-app alert (`showOutlineAlert` hook), falling back to `window.alert`. Unit tests live in `test/outline-core.test.ts`.\r\n\r\n---\r\n\r\n## Cell Notes\r\n\r\nExcel-style cell notes (comments), fully independent from cell values and styles. The engine lives in `spreader/core/notes.ts` - pure-logic, zero Vue/Canvas deps; the UI overlay is `components/note-overlay.vue`.\r\n\r\n### Data Model\r\n\r\nNotes use a **Note Pool** storage pattern: each sheet maintains a `notes` pool keyed by stable `id`, and cells only store a `noteId` reference.\r\n\r\n``\typescript\r\ninterface CellNote {\r\n  id: string;           // Stable unique ID\r\n  text: string;         // Note body (multi-line text)\r\n  author?: string;      // Optional author name\r\n  createdAt: number;    // Creation time (epoch ms)\r\n  updatedAt: number;    // Last modification time (epoch ms)\r\n}\r\n``\r\n\r\n- **`CellData.noteId`**: Per-cell reference pointing into `SheetState.notes`\r\n- **`SheetModelData.notes`**: v-model serialized note pool, keyed by noteId\r\n\r\nThe Note Pool design ensures that sort, insert/delete row/column, and other cell-moving operations carry `noteId` together with the cell data - notes never get orphaned.\r\n\r\n### Entry Points\r\n\r\n- **Context menu**: Cell right-click menu offers *New Note / Edit Note / Delete Note*; edit/delete are hidden when no note exists, new is hidden when one does\r\n- **Shift+F2**: Toggle the edit overlay on a note-bearing cell\r\n- **Hover preview**: A read-only view overlay pops up when the cursor hovers over a cell with a note\r\n\r\n### Rendering\r\n\r\n- Cells with a note show a 6px red triangle indicator in the top-right corner, drawn on Canvas (zero DOM cost)\r\n- The `note-overlay.vue` component is a Vue DOM overlay with `position: absolute` mounted inside `.spreadsheet-wrapper`, constrained by `overflow: hidden` to the table area - it never spills over the toolbar, row/column headers, frozen panes, or scrollbars\r\n- Z-index layering: non-frozen overlays sit *below* the freeze canvas (z-index: 0 vs 1), frozen-region overlays sit *above* it (z-index: 2); scrollbars (z-index: 3) always stay on top for interactivity\r\n\r\n### Author Name\r\n\r\nSet the current author via the `noteAuthor` prop. When empty, saved notes store an empty `author` field, and display falls back to an i18n placeholder (`Unnamed`).\r\n\r\n### Persistence & Undo\r\n\r\n- Notes persist through the sheet v-model (`notes` field), round-tripping correctly through save / load / duplicate-sheet\r\n- Creating / editing / deleting a note each produces one undo step, sharing the same undo stack as cell values, styles, and borders\r\n\r\n---\r\n## Auto Fill\r\n\r\nAn Excel-style fill-handle mechanism (`spreader/core/autofill.ts` pure engine + `composables/interactions.ts` canvas/interaction layer). Drag the small square at the bottom-right corner of the active selection to fill cells: no DOM handles, all drawn on Canvas.\r\n\r\n### Fill Patterns\r\n\r\n| Source values | Fill behavior | Example |\r\n|---------------|---------------|---------|\r\n| Single number | Copy | `42 → 42, 42, 42` |\r\n| Single text | Copy | `foo → foo, foo, foo` |\r\n| Single date | +1 day | `2026-01-01 → 2026-01-02, 2026-01-03` |\r\n| Two+ numbers, constant diff | Linear series | `1,2 → 3,4,5` · `2,4 → 6,8,10` |\r\n| Two+ dates, constant diff | Date series | `2026-01-01, 2026-01-03 → 2026-01-05, 2026-01-07` |\r\n| Text + number, same prefix | Text-number series | `Item1,Item2 → Item3,Item4` |\r\n| Two single letters | Alpha series | `A,B → C,D,E` |\r\n| Formula | Reference translation | `=A1*2` → `=A2*2, =A3*2` |\r\n| Multi-column / multi-row block | Per-column pattern inference | `A1:B2=[[1,10],[2,20]] → [[3,30],[4,40]]` |\r\n\r\n### Formula Reference Rules\r\n\r\nFill-handle translation reuses the existing `shiftFormulaRefs()`: no second formula engine:\r\n\r\n| Reference type | Syntax | Fill behavior |\r\n|----------------|--------|---------------|\r\n| Relative | `=A1` | Row/col offset with the target cell |\r\n| Absolute | `=$A$1` | Stays unchanged |\r\n| Mixed (col absolute) | `=$A1` | Row adjusts, column locked |\r\n| Mixed (row absolute) | `=A$1` | Column adjusts, row locked |\r\n| Composite | `=B1*$F$1` | `B1` adjusts, `$F$1` locked |\r\n\r\n### Interaction\r\n\r\n- **Fill handle**: 6px square at the selection's bottom-right corner, theme primary color; turns grey when the selection partially intersects a merge (fill disabled).\r\n- **Hit-test**: independent `isFillHandleHit()` runs after resize handles and before cell click; hover shows `crosshair` cursor.\r\n- **State machine**: a dedicated `autofilling` state prevents selection drag / editor / resize from starting; ESC cancels mid-drag.\r\n- **Live preview**: the target range renders as a semi-transparent dashed rectangle during drag; the source selection stays put; no cell data is mutated until `mouseup`.\r\n- **Edge auto-scroll**: dragging within 30px of the viewport edge starts a single `requestAnimationFrame` loop that scrolls and updates the target range; stopped on `mouseup` / ESC / pointercancel.\r\n- **Dynamic expansion**: fills beyond the current `rowCount`/`colCount` trigger `ensureCapacity()` first, folded into the same undo step.\r\n- **Selection after fill**: the selection updates to the union of source + target range.\r\n- **Freeze panes**: all coordinates flow through `cellToScreenRect` / `screenToCell`, so the handle, hit-test, preview, and final fill work across frozen and body regions alike.\r\n- **Merge compatibility**: partially intersecting merges disable the fill handle (conservative first version); whole-block merges fill correctly.\r\n- **Touch**: shares the same `autoFillState` and `applyAutoFill` path as mouse: no separate implementation.\r\n\r\n### Architecture\r\n\r\n```\r\nFill Handle UI (drawFillHandle)\r\n       ↓\r\nUnified Hit-Test (isFillHandleHit)\r\n       ↓\r\nAutoFill Drag State (autoFillState)\r\n       ↓\r\nTarget Range Calculation (computeTargetRange)\r\n       ↓\r\nPure AutoFill Pattern Engine (core/autofill.ts)\r\n       ↓\r\nFormula Translation (shiftFormulaRefs)\r\n       ↓\r\nStyle / Border / Cell Mutation (applyAutoFill)\r\n       ↓\r\nUndo Snapshot (saveUndo, one step per drag)\r\n       ↓\r\nscheduleRender()\r\n```\r\n\r\nThe pure engine (`core/autofill.ts`) has zero Vue/Canvas dependencies and is fully unit-tested in `test/autofill.test.ts` (54 cases), making it reusable for `Ctrl+D`/`Ctrl+R`, paste-fill, right-click fill, and programmatic auto-fill.\r\n\r\n---\r\n\r\n## Auto Filter (AutoFilter)\r\n\r\nAn Excel-style auto filter on a normal range: filtering is a **Sheet-level feature bound to a data Range**, not a per-column-header filter. The header arrows are drawn on the Canvas (no DOM); the filter panel uses Vue DOM.\r\n\r\n### Enable & toggle\r\n\r\n- Toolbar **Data → Filter** or `Ctrl+Shift+L` invokes `toggleAutoFilter()`.\r\n- **Not enabled → create**: select a data cell or a single-row multi-column range, then the filter is created by probing the contiguous data region **downward** from that header row; a completely empty sheet creates no invalid filter.\r\n- **Enabled → remove entirely**: restores hidden rows, clears all column criteria, and removes header arrows. The toolbar button's highlighted state exactly matches its click behavior (highlight = enabled, click = turn off).\r\n- Selecting a single merged cell (a multi-cell merge) with no active filter disables the filter button (a merged cell cannot serve as a valid data-region header).\r\n\r\n### Header arrow\r\n\r\n- Shown only on the header row of the Filter Range and only for columns inside the range; not shown when disabled or outside the range.\r\n- Styled as a \"drop-down button with background on the right border\": grey background + dark arrow when not filtered, blue background + white arrow when filtered (distinguishes \"enabled\" from \"this column filtered\").\r\n- Clicking the arrow opens only the filter panel, never a normal selection; with frozen panes the arrow renders correctly on the frozen header.\r\n\r\n### Filter panel\r\n\r\nReuses the existing engine: the title shows the column's header text (not the column letter); unchecking items takes effect only on **OK**, never immediately. Supports value / text / number / date filters, search, blanks, and multi-column AND; candidate values come from the corresponding column inside the Filter Range, generated from already-filtered rows when other columns are filtered (Excel cascading behavior).\r\n\r\n### Compatibility\r\n\r\n- Hidden rows use the existing `filteredOutRows` + visible-row mapping; rows are **never deleted or copied**.\r\n- Row/column insert/delete adjust the range via `adjustFilterRows` / `adjustFilterCols`; deleting the entire filter region auto-cancels the filter.\r\n- After sorting, filtered rows are recomputed; original row indices are preserved.\r\n- Persisted through v-model, fully retaining range, arrows, criteria, and hidden rows.\r\n\r\n---\r\n\r\n## Border System\r\n\r\nA dedicated border storage & rendering mechanism (`spreader/core/border-pool.ts` + `border-resolve.ts`).\r\n\r\n- **Dedicated border pool**: each sheet maintains a `borders: BorderStyle[]` pool (`borders[0]` is always the empty border `{}`); styles reference borders by index (`borderId`), and identical borders are deduplicated.\r\n- **Shared-border resolution**: adjacent cells' shared border is resolved at render time via `resolveSharedBorder()`: wider wins, then the first side on equal width; when exactly one side carries an `owner` flag (set by an explicit border or selection operation) that side wins the shared edge regardless of width, so a freshly applied selection-boundary edge takes priority over a pre-existing neighbor edge. Setting a border no longer mutates neighboring cells.\r\n- **Merged cells**: merged-region borders are stored at the anchor (top-left); internal borders are masked, outer boundaries are resolved segment-wise against neighbors, and the four corners fill in corner blocks.\r\n- **Legacy compatibility**: legacy inline border props (`borderTopWidth`, etc., deprecated) are auto-migrated via `migrateBordersInStyles()` on load.\r\n- **Per-side color & line type (decoupled)**: both live on each `BorderSide` (`{ width; color; style }`). Color is a standard HEX string; `''` / omitted means \"auto\" and renders as the default `#444`. Line `style` is one of `solid` / `dashed` / `dotted`; legacy data with no `style` defaults to `solid`, and a `solid` side stores no `style` key so its dedup key matches historical empty-border data. Changing the color only touches `color` and keeps `width`/`style`; changing the line type only touches `style` and keeps `width`/`color`. The border picker exposes two submenus: a color selector (reuses the text-color palette with an **Automatic** entry, colors only existing borders) and a **line-type** selector (solid / dashed / dotted previews, sets the active pen line type, then applies it to subsequent border operations and to the selection's existing edges, never creating a border that isn't there). Pure logic lives in `core/border-color.ts` (`withBorderColor` / `withBorderWidth` / `planBorderColorChanges` / `resolveSelectionBorderColor`) and `core/border-style.ts` (`normalizeBorderLineStyle` / `borderLineDash`), fully decoupled from Vue/Canvas and unit-tested. The renderer draws dashed/dotted via `paintBorderEdge` (solid keeps the original `fillRect` path so grid lines and the selection frame stay untouched).\r\n\r\n---\r\n\r\n## Theming\r\n\r\n### Built-in Themes\r\n\r\n```typescript\r\nimport type { ThemeColors } from 'xiaodao-spreader';\r\n\r\nconst lightTheme: ThemeColors = { /* 50+ color fields */ };\r\nconst darkTheme: ThemeColors = { /* 50+ color fields */ };\r\n```\r\n\r\n### Theme Variables (`--sp-*`) and Scope\r\n\r\nTheme colors are injected via CSS custom properties (`--sp-*`), declared centrally in the component stylesheet `theme.css`:\r\n\r\n```css\r\n--sp-bg, --sp-gridBg, --sp-gridLine, --sp-selectionBg,\r\n--sp-headerBg, --sp-headerBorder, --sp-headerText,\r\n--sp-formulaBarBg, --sp-formulaBarInputBorder,\r\n--sp-wrapperBg, --sp-cellEditorBorder,\r\n/* ... and many more (new variables must ship both light and dark values) */\r\n```\r\n\r\nVariable scope is confined to the component subtree so the host page is never polluted:\r\n\r\n- **light**: declared on `.spreadsheet-outer, .sp-spreader-overlay`\r\n- **dark**: declared on `.spreadsheet-outer.dark, .sp-spreader-overlay.dark`; when `theme=\"dark\"` the component root and every teleported overlay root get a `.dark` class automatically - `<html>` globals are never touched\r\n\r\nBecause dropdowns / dialogs / context menus are teleported to `<body>` (outside the component DOM tree, so they cannot inherit variables from component ancestors), the stylesheet declares the same variable set on both `.spreadsheet-outer` (component body) and `.sp-spreader-overlay` (overlay roots). **Consumers must import the stylesheet**, otherwise every component style (including overlays) loses its theme variables:\r\n\r\n```ts\r\nimport 'xiaodao-spreader/style.css';\r\n```\r\n\r\nNote: colors painted on the Canvas (grid, headers, selection) do not depend on CSS variables; they come from `ThemeColors` (`lightTheme` / `darkTheme`) picked by the `theme` prop.\r\n\r\n### Custom Theme\r\n\r\nPass `theme=\"dark\"` for dark mode, or override `--sp-*` variables for full customization. The variables live on the `.spreadsheet-outer` scope, so a wrapper component can override the component body via descendant inheritance, but to cover teleported overlays as well you must also target `.sp-spreader-overlay` (overlays leave the component tree and do not inherit from the wrapper):\r\n\r\n```vue\r\n<template>\r\n  <div style=\"--sp-bg: #1a1a2e; --sp-cellText: #e0e0e0;\">\r\n    <Spreader v-model:data=\"myData\" />\r\n  </div>\r\n</template>\r\n```\r\n\r\n```css\r\n/* Needed to restyle teleported overlays (dropdowns/dialogs/context menus); overriding only the component root is not enough */\r\n.sp-spreader-overlay {\r\n  --sp-bg: #1a1a2e;\r\n  --sp-cellText: #e0e0e0;\r\n}\r\n```\r\n\r\n### Internationalization\r\n\r\nBuilt-in languages: `'zh-CN'`, `'en-US'`. Pass via `locale` prop. Right-click menus and toolbar labels are automatically localized.\r\n\r\n---\r\n\r\n## Development\r\n\r\n```bash\r\n# Install dependencies\r\npnpm install\r\n\r\n# Start dev server (with auto-reload)\r\npnpm dev\r\n\r\n# Type check only\r\npnpm type-check\r\n```\r\n\r\nThe dev server runs on `http://localhost:5173` by default.\r\n\r\n---\r\n\r\n## Building\r\n\r\n```bash\r\n# Production build (type-check + vite build)\r\npnpm build\r\n\r\n# Preview production build\r\npnpm preview\r\n\r\n# Build for demo/testing purposes\r\npnpm build:demo\r\n```\r\n\r\n### Build Output\r\n\r\n| File | Description |\r\n|------|-------------|\r\n| `dist/xiaodao-spreader.es.js` | ES module (for bundlers) |\r\n| `dist/xiaodao-spreader.umd.js` | UMD bundle (for direct `<script>` usage) |\r\n| `dist/style.css` | Extracted stylesheet |\r\n| `dist/types/` | TypeScript declaration files |\r\n\r\n### CI/CD\r\n\r\nThe project includes a GitHub Actions workflow (`.github/workflows/publish.yml`) for automated publishing to npm.\r\n\r\n---\r\n\r\n## Touch & Mobile Interaction\r\n\r\nx-spreader is touch-first: every mouse interaction has a symmetric touch path, verified on real mobile devices.\r\n\r\n- **Tap to select / long-press for context menu**: tap a cell, row header, column header, or the corner select-all button to select; long-press (450ms) inside the current selection opens the right-click context menu (cell / row / column / corner). Long-press outside the selection falls back to range selection / header drag-multi-select, so gestures never conflict.\r\n- **Header filter arrow**: tap the arrow on the header cell to open the AutoFilter panel (`onTouchStart` now hit-tests the filter button).\r\n- **Resize columns / rows**: touch the right edge of a column header or bottom edge of a row header (8px hot zone, widened on touch) to drag width / height.\r\n- **Range selection**: long-press a cell (450ms) then drag to draw a rectangular selection; long-press a row/column header then drag to expand the selection. A clear drag (>8px) switches to scrolling; a light tap keeps the single selection.\r\n- **Format brush**: after copying a style from a source cell, tap the target range on touch to apply it (mirrors mouse `onMouseUp`).\r\n- **Commit edit by tapping outside**: tapping empty canvas or outside the formula bar commits an in-progress cell / formula-bar edit (mirrors mouse `onMouseDown`).\r\n- **Tab bar**: long-press a tab button or the empty tab-bar area (450ms) opens the tab right-click menu.\r\n- **Popups close on outside tap**: the context menu and the row-height / column-width editor panel (`dimPanel`) close on outside tap. They listen on `touchstart` because `onTouchStart` calls `preventDefault()`, which suppresses the synthetic `click`/`mousedown` that desktop close-listeners rely on. All other pickers already use `pointerdown` and close correctly on touch.\r\n\r\n## Roadmap\r\n\r\n### Near-term\r\n\r\n- [x] More formulas: `COUNT`, `IF`, `VLOOKUP`, `CONCATENATE`\r\n- [x] Cell background color picker\r\n- [x] Number format (currency, percentage, date, number of decimals): *see [Number Format](#number-format)*\r\n- [x] Conditional Formatting: preset rules (highlight cells / duplicate / unique / blank / not blank), formula-based conditions, formula ref adjustment on insert/delete, manage & clear rules dialogs. *see [Conditional Formatting](#conditional-formatting)*\r\n- [x] Auto-fill drag handle: *see [Auto Fill](#auto-fill)*\r\n- [x] Find & Replace: *see [Find & Replace](#find--replace)*\r\n\r\n### Mid-term\r\n\r\n- [x] Frozen panes (freeze rows/columns): *see [Freeze Panes](#features)*\r\n- [x] Data Validation: dropdown lists, input constraints (any value / list / whole number / decimal / date / time / text length / custom formula), list dropdown with search & keyboard nav, input message and error alert (Stop/Warning/Information), atomic paste/auto-fill validation, undo/redo and persistence; see [Data Validation](#data-validation)\r\n- [x] Column / row grouping and collapsing: *see [Row / Column Grouping & Collapsing](#row--column-grouping--collapsing)*\r\n- [x] Sort & filter: sort by displayed content with Excel-style Sort Warning dialog (expand selection / current selection only); see [Sorting & Sort Warning](#features)\r\n- [x] Auto Filter (AutoFilter): toolbar \"Filter\" / `Ctrl+Shift+L` to enable, header drop-down arrows, intelligent downward data probing, value/text/number/date multi-type filters, separate clear-column vs remove-all; see [Auto Filter (AutoFilter)](#auto-filter-autofilter)\r\n- [x] Touch & mobile interaction: symmetric touch paths for select / context menu / filter / resize / range select / format brush / tab menu; popups close on outside tap; see [Touch & Mobile Interaction](#touch--mobile-interaction)\r\n- [x] Cell comments / notes: Note Pool storage, context-menu CRUD, hover preview, edit overlay, persistence & undo; see [Cell Notes](#cell-notes)\r\n- [x] Read-only Mode: `editable` prop with layered guards, UI and logic both covered; see [Read-only Mode](#read-only-mode)\r\n- [ ] Print layout\r\n\r\n### Long-term\r\n\r\n- [ ] OffscreenCanvas + Web Worker for multi-threaded rendering\r\n- [ ] Shared worker for cross-tab collaboration\r\n- [ ] Plugin system for custom cell renderers\r\n- [ ] Excel / CSV import & export\r\n- [ ] Chart engine (embedded mini-charts)\r\n\r\n---\r\n\r\n## Tech Stack\r\n\r\n| Layer | Technology | Version |\r\n|-------|-----------|---------|\r\n| Framework | Vue 3 (Composition API + `<script setup>`) | ^3.4 |\r\n| Build | Vite | ^5.0 |\r\n| Language | TypeScript (strict) | ~5.4 |\r\n| Rendering | Canvas 2D API | - |\r\n| Type Checker | vue-tsc | ^2.2 |\r\n| Package Manager | pnpm | - |\r\n| CSS | Scoped CSS + CSS Custom Properties | - |\r\n\r\n---\r\n\r\n## License\r\n\r\nThis project is licensed under the MIT License: see the [LICENSE](LICENSE) file for details.\r\n","readmeFilename":""}