├── .gitignore ├── LICENSE ├── README.md ├── index.html ├── index.ts ├── package-lock.json ├── package.json ├── src ├── App.vue ├── components │ └── Test.vue ├── main.ts ├── usePaginator.ts └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | .vscode 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Markus Appel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue-use-paginator 2 | 3 | Vue 3 composition API hook function to reactively paginate data and arrange paginator buttons. Completely renderless. 4 | 5 | ## Demo 6 | 7 | * [Live demo](https://demo-vue-use-paginator.netlify.app/) 8 | * [Demo code](https://github.com/Sun0fABeach/demo-vue-use-paginator/blob/master/src/components/Demo.vue) 9 | 10 | ## Installation 11 | 12 | ```shell 13 | $ npm install vue-use-paginator 14 | ``` 15 | 16 | ## Basic Setup 17 | 18 | ```html 19 | 42 | ``` 43 | 44 | ## Details 45 | 46 | ### Hook API 47 | 48 | Function `usePaginator` returns an object of type [`IPagination`](<#user-content-definitions> "IPagination") which contains the following reactive data plus some convenience functions. You can initialize `page`, `pageSize`, `numItems` and `numButtons` by passing an object of type [`IOptions`](<#user-content-definitions> "IOptions"). Otherwise, default initial values will be used. 49 | 50 | | Name | Type | Description 51 | | -------------- | ---------------------------------- | ----------- 52 | | `page` | `Ref` | Current active page (default initial value: 1) 53 | | `pageSize` | `Ref` | Size of each page (default initial value: 5) 54 | | `numItems` | `Ref` | Total number of items to paginate (default initial value: 0) 55 | | `numButtons` | `Ref` | Number of paginator buttons to display (default initial value: 5) 56 | | `numPages` | `ComputedRef` | Total number of pages 57 | | `slice` | `ComputedRef<[number, number]>` | Tuple containing start and end index delimiting the currently active page (0 based, end index is exclusive). For example, given you are on page 2, `pageSize` is 10 and `numItems` is greater than or equal to 20, `slice` will be `[10, 20]`. 58 | | `buttons` | `ComputedRef` | Array of objects usable for displaying paginator buttons (details below) 59 | | `hasPrev` | `ComputedRef` | Whether the currently active page is the first page 60 | | `hasNext` | `ComputedRef` | Whether the currently active page is the last page 61 | | `goPrev` | `() => number` | Go to next page 62 | | `goNext` | `() => number` | Go to previous page 63 | | `goStart` | `() => 1` | Go to first page 64 | | `goEnd` | `() => number` | Go to last page 65 | 66 | * `page`, `pageSize`, `numItems`, as well as `numButtons` are writable refs that will cause the other reactive properties to adjust when changed. Once you know how many items to paginate, you need to set `numItems` at least. 67 | * You can move to another page by either calling `goPrev`, `goNext`, `goStart`, `goEnd`, or by assigning to `page` directly. Note that assigning a value outside of 1 and `numPages` will be ignored. 68 | 69 | ### Paginator buttons 70 | 71 | When displaying paginator buttons, you often don't have enough slots for each page and therefore need to use a placeholder like '...'. Calculating the positions of these placeholders is not trivial. Fortunately, `buttons` is an array of [`IPaginatorButton`](<#user-content-definitions> "IPaginatorButton") where each item contains the following properties to help you out. 72 | 73 | | Name | Type | Description 74 | | ---------- | ---------- | ----------- 75 | | `page` | `number` | The page to navigate to when clicking this button 76 | | `active` | `boolean` | Whether this button shows the currently active page 77 | | `ellipsis` | `boolean` | Whether this button is a placeholder for omitted pages 78 | 79 | #### Template example 80 | 81 | Here is a minimal example how you could write your paginator markup. 82 | 83 | ```vue 84 |
    85 |
  1. 86 | {{ '<<' }} 87 |
  2. 88 |
  3. 89 | {{ '<' }} 90 |
  4. 91 |
  5. 97 | {{ button.ellipsis ? '...' : button.page }} 98 |
  6. 99 |
  7. 100 | {{ '>' }} 101 |
  8. 102 |
  9. 103 | {{ '>>' }} 104 |
  10. 105 |
106 | ``` 107 | 108 | Notice how certain classes and texts are set based on the values of `hasPrev`, `hasNext`, `button.active` and `button.ellipsis`. How you style these elements is completely up to you. 109 | 110 | ### API integration 111 | 112 | This library doesn't make any assumptions about whether you paginate in the frontend or call a paginated endpoint. 113 | 114 | If you paginate in the frontend, just assign the length of your collection to `numItems` and use the values from `slice` to slice out the items to display for your current page. 115 | 116 | If you call a paginated endpoint, it needs to tell you the total number of items in order to set `numItems`. You can then use `slice` or `page`/`pageSize` to fetch a page. You will normally want to set up a watcher in order to fetch a new page when `page` or `pageSize` changes. 117 | 118 | ```typescript 119 | watch([page, pageSize], ([newPage, newPageSize]) => { 120 | fetchPage(newPage, newPageSize); 121 | }) 122 | ``` 123 | 124 | ### Types 125 | 126 | #### Definitions 127 | 128 | ```typescript 129 | interface IOptions { 130 | page?: number | Ref 131 | pageSize?: number | Ref 132 | numItems?: number | Ref 133 | numButtons?: number | Ref 134 | } 135 | 136 | interface IPagination { 137 | page: Ref 138 | pageSize: Ref 139 | numItems: Ref 140 | numButtons: Ref 141 | numPages: ComputedRef 142 | slice: ComputedRef<[number, number]> 143 | buttons: ComputedRef 144 | hasPrev: ComputedRef 145 | hasNext: ComputedRef 146 | goPrev: () => number 147 | goNext: () => number 148 | goStart: () => 1 149 | goEnd: () => number 150 | } 151 | 152 | interface IButton { 153 | page: number 154 | } 155 | 156 | interface IPageButton extends IButton { 157 | active: boolean 158 | ellipsis: false 159 | } 160 | 161 | interface IEllipsisButton extends IButton { 162 | active: false 163 | ellipsis: true 164 | } 165 | 166 | type IPaginatorButton = IPageButton | IEllipsisButton 167 | ``` 168 | 169 | #### Importing Types 170 | 171 | ```typescript 172 | import type { IOptions, IPagination, IPaginatorButton } from 'vue-use-paginator' 173 | ``` 174 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vite + Vue + TS 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './src/usePaginator' 2 | export * from './src/usePaginator' -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-use-paginator", 3 | "version": "0.4.2", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "vue-use-paginator", 9 | "version": "0.4.2", 10 | "license": "MIT", 11 | "dependencies": { 12 | "vue": "^3.5.13" 13 | }, 14 | "devDependencies": { 15 | "@babel/types": "^7.26.5", 16 | "@types/node": "^22.10.7", 17 | "@vitejs/plugin-vue": "^5.2.1", 18 | "typescript": "^5.7.3", 19 | "vite": "^6.0.8", 20 | "vue-tsc": "^2.2.0" 21 | } 22 | }, 23 | "node_modules/@babel/helper-string-parser": { 24 | "version": "7.25.9", 25 | "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", 26 | "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", 27 | "license": "MIT", 28 | "engines": { 29 | "node": ">=6.9.0" 30 | } 31 | }, 32 | "node_modules/@babel/helper-validator-identifier": { 33 | "version": "7.25.9", 34 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", 35 | "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", 36 | "license": "MIT", 37 | "engines": { 38 | "node": ">=6.9.0" 39 | } 40 | }, 41 | "node_modules/@babel/parser": { 42 | "version": "7.26.5", 43 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.5.tgz", 44 | "integrity": "sha512-SRJ4jYmXRqV1/Xc+TIVG84WjHBXKlxO9sHQnA2Pf12QQEAp1LOh6kDzNHXcUnbH1QI0FDoPPVOt+vyUDucxpaw==", 45 | "license": "MIT", 46 | "dependencies": { 47 | "@babel/types": "^7.26.5" 48 | }, 49 | "bin": { 50 | "parser": "bin/babel-parser.js" 51 | }, 52 | "engines": { 53 | "node": ">=6.0.0" 54 | } 55 | }, 56 | "node_modules/@babel/types": { 57 | "version": "7.26.5", 58 | "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", 59 | "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", 60 | "license": "MIT", 61 | "dependencies": { 62 | "@babel/helper-string-parser": "^7.25.9", 63 | "@babel/helper-validator-identifier": "^7.25.9" 64 | }, 65 | "engines": { 66 | "node": ">=6.9.0" 67 | } 68 | }, 69 | "node_modules/@esbuild/aix-ppc64": { 70 | "version": "0.24.2", 71 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz", 72 | "integrity": "sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==", 73 | "cpu": [ 74 | "ppc64" 75 | ], 76 | "dev": true, 77 | "license": "MIT", 78 | "optional": true, 79 | "os": [ 80 | "aix" 81 | ], 82 | "engines": { 83 | "node": ">=18" 84 | } 85 | }, 86 | "node_modules/@esbuild/android-arm": { 87 | "version": "0.24.2", 88 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.24.2.tgz", 89 | "integrity": "sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==", 90 | "cpu": [ 91 | "arm" 92 | ], 93 | "dev": true, 94 | "license": "MIT", 95 | "optional": true, 96 | "os": [ 97 | "android" 98 | ], 99 | "engines": { 100 | "node": ">=18" 101 | } 102 | }, 103 | "node_modules/@esbuild/android-arm64": { 104 | "version": "0.24.2", 105 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz", 106 | "integrity": "sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==", 107 | "cpu": [ 108 | "arm64" 109 | ], 110 | "dev": true, 111 | "license": "MIT", 112 | "optional": true, 113 | "os": [ 114 | "android" 115 | ], 116 | "engines": { 117 | "node": ">=18" 118 | } 119 | }, 120 | "node_modules/@esbuild/android-x64": { 121 | "version": "0.24.2", 122 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.24.2.tgz", 123 | "integrity": "sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==", 124 | "cpu": [ 125 | "x64" 126 | ], 127 | "dev": true, 128 | "license": "MIT", 129 | "optional": true, 130 | "os": [ 131 | "android" 132 | ], 133 | "engines": { 134 | "node": ">=18" 135 | } 136 | }, 137 | "node_modules/@esbuild/darwin-arm64": { 138 | "version": "0.24.2", 139 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz", 140 | "integrity": "sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==", 141 | "cpu": [ 142 | "arm64" 143 | ], 144 | "dev": true, 145 | "license": "MIT", 146 | "optional": true, 147 | "os": [ 148 | "darwin" 149 | ], 150 | "engines": { 151 | "node": ">=18" 152 | } 153 | }, 154 | "node_modules/@esbuild/darwin-x64": { 155 | "version": "0.24.2", 156 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz", 157 | "integrity": "sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==", 158 | "cpu": [ 159 | "x64" 160 | ], 161 | "dev": true, 162 | "license": "MIT", 163 | "optional": true, 164 | "os": [ 165 | "darwin" 166 | ], 167 | "engines": { 168 | "node": ">=18" 169 | } 170 | }, 171 | "node_modules/@esbuild/freebsd-arm64": { 172 | "version": "0.24.2", 173 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz", 174 | "integrity": "sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==", 175 | "cpu": [ 176 | "arm64" 177 | ], 178 | "dev": true, 179 | "license": "MIT", 180 | "optional": true, 181 | "os": [ 182 | "freebsd" 183 | ], 184 | "engines": { 185 | "node": ">=18" 186 | } 187 | }, 188 | "node_modules/@esbuild/freebsd-x64": { 189 | "version": "0.24.2", 190 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz", 191 | "integrity": "sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==", 192 | "cpu": [ 193 | "x64" 194 | ], 195 | "dev": true, 196 | "license": "MIT", 197 | "optional": true, 198 | "os": [ 199 | "freebsd" 200 | ], 201 | "engines": { 202 | "node": ">=18" 203 | } 204 | }, 205 | "node_modules/@esbuild/linux-arm": { 206 | "version": "0.24.2", 207 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz", 208 | "integrity": "sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==", 209 | "cpu": [ 210 | "arm" 211 | ], 212 | "dev": true, 213 | "license": "MIT", 214 | "optional": true, 215 | "os": [ 216 | "linux" 217 | ], 218 | "engines": { 219 | "node": ">=18" 220 | } 221 | }, 222 | "node_modules/@esbuild/linux-arm64": { 223 | "version": "0.24.2", 224 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz", 225 | "integrity": "sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==", 226 | "cpu": [ 227 | "arm64" 228 | ], 229 | "dev": true, 230 | "license": "MIT", 231 | "optional": true, 232 | "os": [ 233 | "linux" 234 | ], 235 | "engines": { 236 | "node": ">=18" 237 | } 238 | }, 239 | "node_modules/@esbuild/linux-ia32": { 240 | "version": "0.24.2", 241 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz", 242 | "integrity": "sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==", 243 | "cpu": [ 244 | "ia32" 245 | ], 246 | "dev": true, 247 | "license": "MIT", 248 | "optional": true, 249 | "os": [ 250 | "linux" 251 | ], 252 | "engines": { 253 | "node": ">=18" 254 | } 255 | }, 256 | "node_modules/@esbuild/linux-loong64": { 257 | "version": "0.24.2", 258 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz", 259 | "integrity": "sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==", 260 | "cpu": [ 261 | "loong64" 262 | ], 263 | "dev": true, 264 | "license": "MIT", 265 | "optional": true, 266 | "os": [ 267 | "linux" 268 | ], 269 | "engines": { 270 | "node": ">=18" 271 | } 272 | }, 273 | "node_modules/@esbuild/linux-mips64el": { 274 | "version": "0.24.2", 275 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz", 276 | "integrity": "sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==", 277 | "cpu": [ 278 | "mips64el" 279 | ], 280 | "dev": true, 281 | "license": "MIT", 282 | "optional": true, 283 | "os": [ 284 | "linux" 285 | ], 286 | "engines": { 287 | "node": ">=18" 288 | } 289 | }, 290 | "node_modules/@esbuild/linux-ppc64": { 291 | "version": "0.24.2", 292 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz", 293 | "integrity": "sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==", 294 | "cpu": [ 295 | "ppc64" 296 | ], 297 | "dev": true, 298 | "license": "MIT", 299 | "optional": true, 300 | "os": [ 301 | "linux" 302 | ], 303 | "engines": { 304 | "node": ">=18" 305 | } 306 | }, 307 | "node_modules/@esbuild/linux-riscv64": { 308 | "version": "0.24.2", 309 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz", 310 | "integrity": "sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==", 311 | "cpu": [ 312 | "riscv64" 313 | ], 314 | "dev": true, 315 | "license": "MIT", 316 | "optional": true, 317 | "os": [ 318 | "linux" 319 | ], 320 | "engines": { 321 | "node": ">=18" 322 | } 323 | }, 324 | "node_modules/@esbuild/linux-s390x": { 325 | "version": "0.24.2", 326 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz", 327 | "integrity": "sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==", 328 | "cpu": [ 329 | "s390x" 330 | ], 331 | "dev": true, 332 | "license": "MIT", 333 | "optional": true, 334 | "os": [ 335 | "linux" 336 | ], 337 | "engines": { 338 | "node": ">=18" 339 | } 340 | }, 341 | "node_modules/@esbuild/linux-x64": { 342 | "version": "0.24.2", 343 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz", 344 | "integrity": "sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==", 345 | "cpu": [ 346 | "x64" 347 | ], 348 | "dev": true, 349 | "license": "MIT", 350 | "optional": true, 351 | "os": [ 352 | "linux" 353 | ], 354 | "engines": { 355 | "node": ">=18" 356 | } 357 | }, 358 | "node_modules/@esbuild/netbsd-arm64": { 359 | "version": "0.24.2", 360 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz", 361 | "integrity": "sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==", 362 | "cpu": [ 363 | "arm64" 364 | ], 365 | "dev": true, 366 | "license": "MIT", 367 | "optional": true, 368 | "os": [ 369 | "netbsd" 370 | ], 371 | "engines": { 372 | "node": ">=18" 373 | } 374 | }, 375 | "node_modules/@esbuild/netbsd-x64": { 376 | "version": "0.24.2", 377 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz", 378 | "integrity": "sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==", 379 | "cpu": [ 380 | "x64" 381 | ], 382 | "dev": true, 383 | "license": "MIT", 384 | "optional": true, 385 | "os": [ 386 | "netbsd" 387 | ], 388 | "engines": { 389 | "node": ">=18" 390 | } 391 | }, 392 | "node_modules/@esbuild/openbsd-arm64": { 393 | "version": "0.24.2", 394 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz", 395 | "integrity": "sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==", 396 | "cpu": [ 397 | "arm64" 398 | ], 399 | "dev": true, 400 | "license": "MIT", 401 | "optional": true, 402 | "os": [ 403 | "openbsd" 404 | ], 405 | "engines": { 406 | "node": ">=18" 407 | } 408 | }, 409 | "node_modules/@esbuild/openbsd-x64": { 410 | "version": "0.24.2", 411 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz", 412 | "integrity": "sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==", 413 | "cpu": [ 414 | "x64" 415 | ], 416 | "dev": true, 417 | "license": "MIT", 418 | "optional": true, 419 | "os": [ 420 | "openbsd" 421 | ], 422 | "engines": { 423 | "node": ">=18" 424 | } 425 | }, 426 | "node_modules/@esbuild/sunos-x64": { 427 | "version": "0.24.2", 428 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", 429 | "integrity": "sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==", 430 | "cpu": [ 431 | "x64" 432 | ], 433 | "dev": true, 434 | "license": "MIT", 435 | "optional": true, 436 | "os": [ 437 | "sunos" 438 | ], 439 | "engines": { 440 | "node": ">=18" 441 | } 442 | }, 443 | "node_modules/@esbuild/win32-arm64": { 444 | "version": "0.24.2", 445 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz", 446 | "integrity": "sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==", 447 | "cpu": [ 448 | "arm64" 449 | ], 450 | "dev": true, 451 | "license": "MIT", 452 | "optional": true, 453 | "os": [ 454 | "win32" 455 | ], 456 | "engines": { 457 | "node": ">=18" 458 | } 459 | }, 460 | "node_modules/@esbuild/win32-ia32": { 461 | "version": "0.24.2", 462 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz", 463 | "integrity": "sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==", 464 | "cpu": [ 465 | "ia32" 466 | ], 467 | "dev": true, 468 | "license": "MIT", 469 | "optional": true, 470 | "os": [ 471 | "win32" 472 | ], 473 | "engines": { 474 | "node": ">=18" 475 | } 476 | }, 477 | "node_modules/@esbuild/win32-x64": { 478 | "version": "0.24.2", 479 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz", 480 | "integrity": "sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==", 481 | "cpu": [ 482 | "x64" 483 | ], 484 | "dev": true, 485 | "license": "MIT", 486 | "optional": true, 487 | "os": [ 488 | "win32" 489 | ], 490 | "engines": { 491 | "node": ">=18" 492 | } 493 | }, 494 | "node_modules/@jridgewell/sourcemap-codec": { 495 | "version": "1.5.0", 496 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 497 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 498 | "license": "MIT" 499 | }, 500 | "node_modules/@rollup/rollup-android-arm-eabi": { 501 | "version": "4.31.0", 502 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.31.0.tgz", 503 | "integrity": "sha512-9NrR4033uCbUBRgvLcBrJofa2KY9DzxL2UKZ1/4xA/mnTNyhZCWBuD8X3tPm1n4KxcgaraOYgrFKSgwjASfmlA==", 504 | "cpu": [ 505 | "arm" 506 | ], 507 | "dev": true, 508 | "license": "MIT", 509 | "optional": true, 510 | "os": [ 511 | "android" 512 | ] 513 | }, 514 | "node_modules/@rollup/rollup-android-arm64": { 515 | "version": "4.31.0", 516 | "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.31.0.tgz", 517 | "integrity": "sha512-iBbODqT86YBFHajxxF8ebj2hwKm1k8PTBQSojSt3d1FFt1gN+xf4CowE47iN0vOSdnd+5ierMHBbu/rHc7nq5g==", 518 | "cpu": [ 519 | "arm64" 520 | ], 521 | "dev": true, 522 | "license": "MIT", 523 | "optional": true, 524 | "os": [ 525 | "android" 526 | ] 527 | }, 528 | "node_modules/@rollup/rollup-darwin-arm64": { 529 | "version": "4.31.0", 530 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.31.0.tgz", 531 | "integrity": "sha512-WHIZfXgVBX30SWuTMhlHPXTyN20AXrLH4TEeH/D0Bolvx9PjgZnn4H677PlSGvU6MKNsjCQJYczkpvBbrBnG6g==", 532 | "cpu": [ 533 | "arm64" 534 | ], 535 | "dev": true, 536 | "license": "MIT", 537 | "optional": true, 538 | "os": [ 539 | "darwin" 540 | ] 541 | }, 542 | "node_modules/@rollup/rollup-darwin-x64": { 543 | "version": "4.31.0", 544 | "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.31.0.tgz", 545 | "integrity": "sha512-hrWL7uQacTEF8gdrQAqcDy9xllQ0w0zuL1wk1HV8wKGSGbKPVjVUv/DEwT2+Asabf8Dh/As+IvfdU+H8hhzrQQ==", 546 | "cpu": [ 547 | "x64" 548 | ], 549 | "dev": true, 550 | "license": "MIT", 551 | "optional": true, 552 | "os": [ 553 | "darwin" 554 | ] 555 | }, 556 | "node_modules/@rollup/rollup-freebsd-arm64": { 557 | "version": "4.31.0", 558 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.31.0.tgz", 559 | "integrity": "sha512-S2oCsZ4hJviG1QjPY1h6sVJLBI6ekBeAEssYKad1soRFv3SocsQCzX6cwnk6fID6UQQACTjeIMB+hyYrFacRew==", 560 | "cpu": [ 561 | "arm64" 562 | ], 563 | "dev": true, 564 | "license": "MIT", 565 | "optional": true, 566 | "os": [ 567 | "freebsd" 568 | ] 569 | }, 570 | "node_modules/@rollup/rollup-freebsd-x64": { 571 | "version": "4.31.0", 572 | "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.31.0.tgz", 573 | "integrity": "sha512-pCANqpynRS4Jirn4IKZH4tnm2+2CqCNLKD7gAdEjzdLGbH1iO0zouHz4mxqg0uEMpO030ejJ0aA6e1PJo2xrPA==", 574 | "cpu": [ 575 | "x64" 576 | ], 577 | "dev": true, 578 | "license": "MIT", 579 | "optional": true, 580 | "os": [ 581 | "freebsd" 582 | ] 583 | }, 584 | "node_modules/@rollup/rollup-linux-arm-gnueabihf": { 585 | "version": "4.31.0", 586 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.31.0.tgz", 587 | "integrity": "sha512-0O8ViX+QcBd3ZmGlcFTnYXZKGbFu09EhgD27tgTdGnkcYXLat4KIsBBQeKLR2xZDCXdIBAlWLkiXE1+rJpCxFw==", 588 | "cpu": [ 589 | "arm" 590 | ], 591 | "dev": true, 592 | "license": "MIT", 593 | "optional": true, 594 | "os": [ 595 | "linux" 596 | ] 597 | }, 598 | "node_modules/@rollup/rollup-linux-arm-musleabihf": { 599 | "version": "4.31.0", 600 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.31.0.tgz", 601 | "integrity": "sha512-w5IzG0wTVv7B0/SwDnMYmbr2uERQp999q8FMkKG1I+j8hpPX2BYFjWe69xbhbP6J9h2gId/7ogesl9hwblFwwg==", 602 | "cpu": [ 603 | "arm" 604 | ], 605 | "dev": true, 606 | "license": "MIT", 607 | "optional": true, 608 | "os": [ 609 | "linux" 610 | ] 611 | }, 612 | "node_modules/@rollup/rollup-linux-arm64-gnu": { 613 | "version": "4.31.0", 614 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.31.0.tgz", 615 | "integrity": "sha512-JyFFshbN5xwy6fulZ8B/8qOqENRmDdEkcIMF0Zz+RsfamEW+Zabl5jAb0IozP/8UKnJ7g2FtZZPEUIAlUSX8cA==", 616 | "cpu": [ 617 | "arm64" 618 | ], 619 | "dev": true, 620 | "license": "MIT", 621 | "optional": true, 622 | "os": [ 623 | "linux" 624 | ] 625 | }, 626 | "node_modules/@rollup/rollup-linux-arm64-musl": { 627 | "version": "4.31.0", 628 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.31.0.tgz", 629 | "integrity": "sha512-kpQXQ0UPFeMPmPYksiBL9WS/BDiQEjRGMfklVIsA0Sng347H8W2iexch+IEwaR7OVSKtr2ZFxggt11zVIlZ25g==", 630 | "cpu": [ 631 | "arm64" 632 | ], 633 | "dev": true, 634 | "license": "MIT", 635 | "optional": true, 636 | "os": [ 637 | "linux" 638 | ] 639 | }, 640 | "node_modules/@rollup/rollup-linux-loongarch64-gnu": { 641 | "version": "4.31.0", 642 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.31.0.tgz", 643 | "integrity": "sha512-pMlxLjt60iQTzt9iBb3jZphFIl55a70wexvo8p+vVFK+7ifTRookdoXX3bOsRdmfD+OKnMozKO6XM4zR0sHRrQ==", 644 | "cpu": [ 645 | "loong64" 646 | ], 647 | "dev": true, 648 | "license": "MIT", 649 | "optional": true, 650 | "os": [ 651 | "linux" 652 | ] 653 | }, 654 | "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { 655 | "version": "4.31.0", 656 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.31.0.tgz", 657 | "integrity": "sha512-D7TXT7I/uKEuWiRkEFbed1UUYZwcJDU4vZQdPTcepK7ecPhzKOYk4Er2YR4uHKme4qDeIh6N3XrLfpuM7vzRWQ==", 658 | "cpu": [ 659 | "ppc64" 660 | ], 661 | "dev": true, 662 | "license": "MIT", 663 | "optional": true, 664 | "os": [ 665 | "linux" 666 | ] 667 | }, 668 | "node_modules/@rollup/rollup-linux-riscv64-gnu": { 669 | "version": "4.31.0", 670 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.31.0.tgz", 671 | "integrity": "sha512-wal2Tc8O5lMBtoePLBYRKj2CImUCJ4UNGJlLwspx7QApYny7K1cUYlzQ/4IGQBLmm+y0RS7dwc3TDO/pmcneTw==", 672 | "cpu": [ 673 | "riscv64" 674 | ], 675 | "dev": true, 676 | "license": "MIT", 677 | "optional": true, 678 | "os": [ 679 | "linux" 680 | ] 681 | }, 682 | "node_modules/@rollup/rollup-linux-s390x-gnu": { 683 | "version": "4.31.0", 684 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.31.0.tgz", 685 | "integrity": "sha512-O1o5EUI0+RRMkK9wiTVpk2tyzXdXefHtRTIjBbmFREmNMy7pFeYXCFGbhKFwISA3UOExlo5GGUuuj3oMKdK6JQ==", 686 | "cpu": [ 687 | "s390x" 688 | ], 689 | "dev": true, 690 | "license": "MIT", 691 | "optional": true, 692 | "os": [ 693 | "linux" 694 | ] 695 | }, 696 | "node_modules/@rollup/rollup-linux-x64-gnu": { 697 | "version": "4.31.0", 698 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.31.0.tgz", 699 | "integrity": "sha512-zSoHl356vKnNxwOWnLd60ixHNPRBglxpv2g7q0Cd3Pmr561gf0HiAcUBRL3S1vPqRC17Zo2CX/9cPkqTIiai1g==", 700 | "cpu": [ 701 | "x64" 702 | ], 703 | "dev": true, 704 | "license": "MIT", 705 | "optional": true, 706 | "os": [ 707 | "linux" 708 | ] 709 | }, 710 | "node_modules/@rollup/rollup-linux-x64-musl": { 711 | "version": "4.31.0", 712 | "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.31.0.tgz", 713 | "integrity": "sha512-ypB/HMtcSGhKUQNiFwqgdclWNRrAYDH8iMYH4etw/ZlGwiTVxBz2tDrGRrPlfZu6QjXwtd+C3Zib5pFqID97ZA==", 714 | "cpu": [ 715 | "x64" 716 | ], 717 | "dev": true, 718 | "license": "MIT", 719 | "optional": true, 720 | "os": [ 721 | "linux" 722 | ] 723 | }, 724 | "node_modules/@rollup/rollup-win32-arm64-msvc": { 725 | "version": "4.31.0", 726 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.31.0.tgz", 727 | "integrity": "sha512-JuhN2xdI/m8Hr+aVO3vspO7OQfUFO6bKLIRTAy0U15vmWjnZDLrEgCZ2s6+scAYaQVpYSh9tZtRijApw9IXyMw==", 728 | "cpu": [ 729 | "arm64" 730 | ], 731 | "dev": true, 732 | "license": "MIT", 733 | "optional": true, 734 | "os": [ 735 | "win32" 736 | ] 737 | }, 738 | "node_modules/@rollup/rollup-win32-ia32-msvc": { 739 | "version": "4.31.0", 740 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.31.0.tgz", 741 | "integrity": "sha512-U1xZZXYkvdf5MIWmftU8wrM5PPXzyaY1nGCI4KI4BFfoZxHamsIe+BtnPLIvvPykvQWlVbqUXdLa4aJUuilwLQ==", 742 | "cpu": [ 743 | "ia32" 744 | ], 745 | "dev": true, 746 | "license": "MIT", 747 | "optional": true, 748 | "os": [ 749 | "win32" 750 | ] 751 | }, 752 | "node_modules/@rollup/rollup-win32-x64-msvc": { 753 | "version": "4.31.0", 754 | "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.31.0.tgz", 755 | "integrity": "sha512-ul8rnCsUumNln5YWwz0ted2ZHFhzhRRnkpBZ+YRuHoRAlUji9KChpOUOndY7uykrPEPXVbHLlsdo6v5yXo/TXw==", 756 | "cpu": [ 757 | "x64" 758 | ], 759 | "dev": true, 760 | "license": "MIT", 761 | "optional": true, 762 | "os": [ 763 | "win32" 764 | ] 765 | }, 766 | "node_modules/@types/estree": { 767 | "version": "1.0.6", 768 | "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", 769 | "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", 770 | "dev": true, 771 | "license": "MIT" 772 | }, 773 | "node_modules/@types/node": { 774 | "version": "22.10.7", 775 | "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.7.tgz", 776 | "integrity": "sha512-V09KvXxFiutGp6B7XkpaDXlNadZxrzajcY50EuoLIpQ6WWYCSvf19lVIazzfIzQvhUN2HjX12spLojTnhuKlGg==", 777 | "dev": true, 778 | "license": "MIT", 779 | "dependencies": { 780 | "undici-types": "~6.20.0" 781 | } 782 | }, 783 | "node_modules/@vitejs/plugin-vue": { 784 | "version": "5.2.1", 785 | "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz", 786 | "integrity": "sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==", 787 | "dev": true, 788 | "license": "MIT", 789 | "engines": { 790 | "node": "^18.0.0 || >=20.0.0" 791 | }, 792 | "peerDependencies": { 793 | "vite": "^5.0.0 || ^6.0.0", 794 | "vue": "^3.2.25" 795 | } 796 | }, 797 | "node_modules/@volar/language-core": { 798 | "version": "2.4.11", 799 | "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.11.tgz", 800 | "integrity": "sha512-lN2C1+ByfW9/JRPpqScuZt/4OrUUse57GLI6TbLgTIqBVemdl1wNcZ1qYGEo2+Gw8coYLgCy7SuKqn6IrQcQgg==", 801 | "dev": true, 802 | "license": "MIT", 803 | "dependencies": { 804 | "@volar/source-map": "2.4.11" 805 | } 806 | }, 807 | "node_modules/@volar/source-map": { 808 | "version": "2.4.11", 809 | "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.11.tgz", 810 | "integrity": "sha512-ZQpmafIGvaZMn/8iuvCFGrW3smeqkq/IIh9F1SdSx9aUl0J4Iurzd6/FhmjNO5g2ejF3rT45dKskgXWiofqlZQ==", 811 | "dev": true, 812 | "license": "MIT" 813 | }, 814 | "node_modules/@volar/typescript": { 815 | "version": "2.4.11", 816 | "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.11.tgz", 817 | "integrity": "sha512-2DT+Tdh88Spp5PyPbqhyoYavYCPDsqbHLFwcUI9K1NlY1YgUJvujGdrqUp0zWxnW7KWNTr3xSpMuv2WnaTKDAw==", 818 | "dev": true, 819 | "license": "MIT", 820 | "dependencies": { 821 | "@volar/language-core": "2.4.11", 822 | "path-browserify": "^1.0.1", 823 | "vscode-uri": "^3.0.8" 824 | } 825 | }, 826 | "node_modules/@vue/compiler-core": { 827 | "version": "3.5.13", 828 | "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", 829 | "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", 830 | "license": "MIT", 831 | "dependencies": { 832 | "@babel/parser": "^7.25.3", 833 | "@vue/shared": "3.5.13", 834 | "entities": "^4.5.0", 835 | "estree-walker": "^2.0.2", 836 | "source-map-js": "^1.2.0" 837 | } 838 | }, 839 | "node_modules/@vue/compiler-dom": { 840 | "version": "3.5.13", 841 | "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", 842 | "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", 843 | "license": "MIT", 844 | "dependencies": { 845 | "@vue/compiler-core": "3.5.13", 846 | "@vue/shared": "3.5.13" 847 | } 848 | }, 849 | "node_modules/@vue/compiler-sfc": { 850 | "version": "3.5.13", 851 | "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", 852 | "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", 853 | "license": "MIT", 854 | "dependencies": { 855 | "@babel/parser": "^7.25.3", 856 | "@vue/compiler-core": "3.5.13", 857 | "@vue/compiler-dom": "3.5.13", 858 | "@vue/compiler-ssr": "3.5.13", 859 | "@vue/shared": "3.5.13", 860 | "estree-walker": "^2.0.2", 861 | "magic-string": "^0.30.11", 862 | "postcss": "^8.4.48", 863 | "source-map-js": "^1.2.0" 864 | } 865 | }, 866 | "node_modules/@vue/compiler-ssr": { 867 | "version": "3.5.13", 868 | "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", 869 | "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", 870 | "license": "MIT", 871 | "dependencies": { 872 | "@vue/compiler-dom": "3.5.13", 873 | "@vue/shared": "3.5.13" 874 | } 875 | }, 876 | "node_modules/@vue/compiler-vue2": { 877 | "version": "2.7.16", 878 | "resolved": "https://registry.npmjs.org/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz", 879 | "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==", 880 | "dev": true, 881 | "license": "MIT", 882 | "dependencies": { 883 | "de-indent": "^1.0.2", 884 | "he": "^1.2.0" 885 | } 886 | }, 887 | "node_modules/@vue/language-core": { 888 | "version": "2.2.0", 889 | "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.2.0.tgz", 890 | "integrity": "sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==", 891 | "dev": true, 892 | "license": "MIT", 893 | "dependencies": { 894 | "@volar/language-core": "~2.4.11", 895 | "@vue/compiler-dom": "^3.5.0", 896 | "@vue/compiler-vue2": "^2.7.16", 897 | "@vue/shared": "^3.5.0", 898 | "alien-signals": "^0.4.9", 899 | "minimatch": "^9.0.3", 900 | "muggle-string": "^0.4.1", 901 | "path-browserify": "^1.0.1" 902 | }, 903 | "peerDependencies": { 904 | "typescript": "*" 905 | }, 906 | "peerDependenciesMeta": { 907 | "typescript": { 908 | "optional": true 909 | } 910 | } 911 | }, 912 | "node_modules/@vue/reactivity": { 913 | "version": "3.5.13", 914 | "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.13.tgz", 915 | "integrity": "sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==", 916 | "license": "MIT", 917 | "dependencies": { 918 | "@vue/shared": "3.5.13" 919 | } 920 | }, 921 | "node_modules/@vue/runtime-core": { 922 | "version": "3.5.13", 923 | "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.13.tgz", 924 | "integrity": "sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==", 925 | "license": "MIT", 926 | "dependencies": { 927 | "@vue/reactivity": "3.5.13", 928 | "@vue/shared": "3.5.13" 929 | } 930 | }, 931 | "node_modules/@vue/runtime-dom": { 932 | "version": "3.5.13", 933 | "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz", 934 | "integrity": "sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==", 935 | "license": "MIT", 936 | "dependencies": { 937 | "@vue/reactivity": "3.5.13", 938 | "@vue/runtime-core": "3.5.13", 939 | "@vue/shared": "3.5.13", 940 | "csstype": "^3.1.3" 941 | } 942 | }, 943 | "node_modules/@vue/server-renderer": { 944 | "version": "3.5.13", 945 | "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.13.tgz", 946 | "integrity": "sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==", 947 | "license": "MIT", 948 | "dependencies": { 949 | "@vue/compiler-ssr": "3.5.13", 950 | "@vue/shared": "3.5.13" 951 | }, 952 | "peerDependencies": { 953 | "vue": "3.5.13" 954 | } 955 | }, 956 | "node_modules/@vue/shared": { 957 | "version": "3.5.13", 958 | "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", 959 | "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", 960 | "license": "MIT" 961 | }, 962 | "node_modules/alien-signals": { 963 | "version": "0.4.14", 964 | "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-0.4.14.tgz", 965 | "integrity": "sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==", 966 | "dev": true, 967 | "license": "MIT" 968 | }, 969 | "node_modules/balanced-match": { 970 | "version": "1.0.2", 971 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 972 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 973 | "dev": true, 974 | "license": "MIT" 975 | }, 976 | "node_modules/brace-expansion": { 977 | "version": "2.0.1", 978 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 979 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 980 | "dev": true, 981 | "license": "MIT", 982 | "dependencies": { 983 | "balanced-match": "^1.0.0" 984 | } 985 | }, 986 | "node_modules/csstype": { 987 | "version": "3.1.3", 988 | "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", 989 | "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", 990 | "license": "MIT" 991 | }, 992 | "node_modules/de-indent": { 993 | "version": "1.0.2", 994 | "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", 995 | "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", 996 | "dev": true, 997 | "license": "MIT" 998 | }, 999 | "node_modules/entities": { 1000 | "version": "4.5.0", 1001 | "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", 1002 | "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", 1003 | "license": "BSD-2-Clause", 1004 | "engines": { 1005 | "node": ">=0.12" 1006 | }, 1007 | "funding": { 1008 | "url": "https://github.com/fb55/entities?sponsor=1" 1009 | } 1010 | }, 1011 | "node_modules/esbuild": { 1012 | "version": "0.24.2", 1013 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.24.2.tgz", 1014 | "integrity": "sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==", 1015 | "dev": true, 1016 | "hasInstallScript": true, 1017 | "license": "MIT", 1018 | "bin": { 1019 | "esbuild": "bin/esbuild" 1020 | }, 1021 | "engines": { 1022 | "node": ">=18" 1023 | }, 1024 | "optionalDependencies": { 1025 | "@esbuild/aix-ppc64": "0.24.2", 1026 | "@esbuild/android-arm": "0.24.2", 1027 | "@esbuild/android-arm64": "0.24.2", 1028 | "@esbuild/android-x64": "0.24.2", 1029 | "@esbuild/darwin-arm64": "0.24.2", 1030 | "@esbuild/darwin-x64": "0.24.2", 1031 | "@esbuild/freebsd-arm64": "0.24.2", 1032 | "@esbuild/freebsd-x64": "0.24.2", 1033 | "@esbuild/linux-arm": "0.24.2", 1034 | "@esbuild/linux-arm64": "0.24.2", 1035 | "@esbuild/linux-ia32": "0.24.2", 1036 | "@esbuild/linux-loong64": "0.24.2", 1037 | "@esbuild/linux-mips64el": "0.24.2", 1038 | "@esbuild/linux-ppc64": "0.24.2", 1039 | "@esbuild/linux-riscv64": "0.24.2", 1040 | "@esbuild/linux-s390x": "0.24.2", 1041 | "@esbuild/linux-x64": "0.24.2", 1042 | "@esbuild/netbsd-arm64": "0.24.2", 1043 | "@esbuild/netbsd-x64": "0.24.2", 1044 | "@esbuild/openbsd-arm64": "0.24.2", 1045 | "@esbuild/openbsd-x64": "0.24.2", 1046 | "@esbuild/sunos-x64": "0.24.2", 1047 | "@esbuild/win32-arm64": "0.24.2", 1048 | "@esbuild/win32-ia32": "0.24.2", 1049 | "@esbuild/win32-x64": "0.24.2" 1050 | } 1051 | }, 1052 | "node_modules/estree-walker": { 1053 | "version": "2.0.2", 1054 | "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", 1055 | "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", 1056 | "license": "MIT" 1057 | }, 1058 | "node_modules/fsevents": { 1059 | "version": "2.3.3", 1060 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1061 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1062 | "dev": true, 1063 | "hasInstallScript": true, 1064 | "license": "MIT", 1065 | "optional": true, 1066 | "os": [ 1067 | "darwin" 1068 | ], 1069 | "engines": { 1070 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1071 | } 1072 | }, 1073 | "node_modules/he": { 1074 | "version": "1.2.0", 1075 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 1076 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 1077 | "dev": true, 1078 | "license": "MIT", 1079 | "bin": { 1080 | "he": "bin/he" 1081 | } 1082 | }, 1083 | "node_modules/magic-string": { 1084 | "version": "0.30.17", 1085 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", 1086 | "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", 1087 | "license": "MIT", 1088 | "dependencies": { 1089 | "@jridgewell/sourcemap-codec": "^1.5.0" 1090 | } 1091 | }, 1092 | "node_modules/minimatch": { 1093 | "version": "9.0.5", 1094 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", 1095 | "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", 1096 | "dev": true, 1097 | "license": "ISC", 1098 | "dependencies": { 1099 | "brace-expansion": "^2.0.1" 1100 | }, 1101 | "engines": { 1102 | "node": ">=16 || 14 >=14.17" 1103 | }, 1104 | "funding": { 1105 | "url": "https://github.com/sponsors/isaacs" 1106 | } 1107 | }, 1108 | "node_modules/muggle-string": { 1109 | "version": "0.4.1", 1110 | "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", 1111 | "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", 1112 | "dev": true, 1113 | "license": "MIT" 1114 | }, 1115 | "node_modules/nanoid": { 1116 | "version": "3.3.8", 1117 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", 1118 | "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", 1119 | "funding": [ 1120 | { 1121 | "type": "github", 1122 | "url": "https://github.com/sponsors/ai" 1123 | } 1124 | ], 1125 | "license": "MIT", 1126 | "bin": { 1127 | "nanoid": "bin/nanoid.cjs" 1128 | }, 1129 | "engines": { 1130 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" 1131 | } 1132 | }, 1133 | "node_modules/path-browserify": { 1134 | "version": "1.0.1", 1135 | "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", 1136 | "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", 1137 | "dev": true, 1138 | "license": "MIT" 1139 | }, 1140 | "node_modules/picocolors": { 1141 | "version": "1.1.1", 1142 | "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", 1143 | "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1144 | "license": "ISC" 1145 | }, 1146 | "node_modules/postcss": { 1147 | "version": "8.5.1", 1148 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", 1149 | "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", 1150 | "funding": [ 1151 | { 1152 | "type": "opencollective", 1153 | "url": "https://opencollective.com/postcss/" 1154 | }, 1155 | { 1156 | "type": "tidelift", 1157 | "url": "https://tidelift.com/funding/github/npm/postcss" 1158 | }, 1159 | { 1160 | "type": "github", 1161 | "url": "https://github.com/sponsors/ai" 1162 | } 1163 | ], 1164 | "license": "MIT", 1165 | "dependencies": { 1166 | "nanoid": "^3.3.8", 1167 | "picocolors": "^1.1.1", 1168 | "source-map-js": "^1.2.1" 1169 | }, 1170 | "engines": { 1171 | "node": "^10 || ^12 || >=14" 1172 | } 1173 | }, 1174 | "node_modules/rollup": { 1175 | "version": "4.31.0", 1176 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.31.0.tgz", 1177 | "integrity": "sha512-9cCE8P4rZLx9+PjoyqHLs31V9a9Vpvfo4qNcs6JCiGWYhw2gijSetFbH6SSy1whnkgcefnUwr8sad7tgqsGvnw==", 1178 | "dev": true, 1179 | "license": "MIT", 1180 | "dependencies": { 1181 | "@types/estree": "1.0.6" 1182 | }, 1183 | "bin": { 1184 | "rollup": "dist/bin/rollup" 1185 | }, 1186 | "engines": { 1187 | "node": ">=18.0.0", 1188 | "npm": ">=8.0.0" 1189 | }, 1190 | "optionalDependencies": { 1191 | "@rollup/rollup-android-arm-eabi": "4.31.0", 1192 | "@rollup/rollup-android-arm64": "4.31.0", 1193 | "@rollup/rollup-darwin-arm64": "4.31.0", 1194 | "@rollup/rollup-darwin-x64": "4.31.0", 1195 | "@rollup/rollup-freebsd-arm64": "4.31.0", 1196 | "@rollup/rollup-freebsd-x64": "4.31.0", 1197 | "@rollup/rollup-linux-arm-gnueabihf": "4.31.0", 1198 | "@rollup/rollup-linux-arm-musleabihf": "4.31.0", 1199 | "@rollup/rollup-linux-arm64-gnu": "4.31.0", 1200 | "@rollup/rollup-linux-arm64-musl": "4.31.0", 1201 | "@rollup/rollup-linux-loongarch64-gnu": "4.31.0", 1202 | "@rollup/rollup-linux-powerpc64le-gnu": "4.31.0", 1203 | "@rollup/rollup-linux-riscv64-gnu": "4.31.0", 1204 | "@rollup/rollup-linux-s390x-gnu": "4.31.0", 1205 | "@rollup/rollup-linux-x64-gnu": "4.31.0", 1206 | "@rollup/rollup-linux-x64-musl": "4.31.0", 1207 | "@rollup/rollup-win32-arm64-msvc": "4.31.0", 1208 | "@rollup/rollup-win32-ia32-msvc": "4.31.0", 1209 | "@rollup/rollup-win32-x64-msvc": "4.31.0", 1210 | "fsevents": "~2.3.2" 1211 | } 1212 | }, 1213 | "node_modules/source-map-js": { 1214 | "version": "1.2.1", 1215 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", 1216 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", 1217 | "license": "BSD-3-Clause", 1218 | "engines": { 1219 | "node": ">=0.10.0" 1220 | } 1221 | }, 1222 | "node_modules/typescript": { 1223 | "version": "5.7.3", 1224 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", 1225 | "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", 1226 | "devOptional": true, 1227 | "license": "Apache-2.0", 1228 | "bin": { 1229 | "tsc": "bin/tsc", 1230 | "tsserver": "bin/tsserver" 1231 | }, 1232 | "engines": { 1233 | "node": ">=14.17" 1234 | } 1235 | }, 1236 | "node_modules/undici-types": { 1237 | "version": "6.20.0", 1238 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", 1239 | "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", 1240 | "dev": true, 1241 | "license": "MIT" 1242 | }, 1243 | "node_modules/vite": { 1244 | "version": "6.0.8", 1245 | "resolved": "https://registry.npmjs.org/vite/-/vite-6.0.8.tgz", 1246 | "integrity": "sha512-rJmB+6m3Qmo5nssFmm6hbSvaCS+5tH/iuTJYeHEOHMwqu/DPrjjBs1rlecCo4D0qy5xq506hMpkKx6pKaudUxA==", 1247 | "dev": true, 1248 | "license": "MIT", 1249 | "dependencies": { 1250 | "esbuild": "^0.24.2", 1251 | "postcss": "^8.4.49", 1252 | "rollup": "^4.23.0" 1253 | }, 1254 | "bin": { 1255 | "vite": "bin/vite.js" 1256 | }, 1257 | "engines": { 1258 | "node": "^18.0.0 || ^20.0.0 || >=22.0.0" 1259 | }, 1260 | "funding": { 1261 | "url": "https://github.com/vitejs/vite?sponsor=1" 1262 | }, 1263 | "optionalDependencies": { 1264 | "fsevents": "~2.3.3" 1265 | }, 1266 | "peerDependencies": { 1267 | "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", 1268 | "jiti": ">=1.21.0", 1269 | "less": "*", 1270 | "lightningcss": "^1.21.0", 1271 | "sass": "*", 1272 | "sass-embedded": "*", 1273 | "stylus": "*", 1274 | "sugarss": "*", 1275 | "terser": "^5.16.0", 1276 | "tsx": "^4.8.1", 1277 | "yaml": "^2.4.2" 1278 | }, 1279 | "peerDependenciesMeta": { 1280 | "@types/node": { 1281 | "optional": true 1282 | }, 1283 | "jiti": { 1284 | "optional": true 1285 | }, 1286 | "less": { 1287 | "optional": true 1288 | }, 1289 | "lightningcss": { 1290 | "optional": true 1291 | }, 1292 | "sass": { 1293 | "optional": true 1294 | }, 1295 | "sass-embedded": { 1296 | "optional": true 1297 | }, 1298 | "stylus": { 1299 | "optional": true 1300 | }, 1301 | "sugarss": { 1302 | "optional": true 1303 | }, 1304 | "terser": { 1305 | "optional": true 1306 | }, 1307 | "tsx": { 1308 | "optional": true 1309 | }, 1310 | "yaml": { 1311 | "optional": true 1312 | } 1313 | } 1314 | }, 1315 | "node_modules/vscode-uri": { 1316 | "version": "3.0.8", 1317 | "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.8.tgz", 1318 | "integrity": "sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==", 1319 | "dev": true, 1320 | "license": "MIT" 1321 | }, 1322 | "node_modules/vue": { 1323 | "version": "3.5.13", 1324 | "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.13.tgz", 1325 | "integrity": "sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==", 1326 | "license": "MIT", 1327 | "dependencies": { 1328 | "@vue/compiler-dom": "3.5.13", 1329 | "@vue/compiler-sfc": "3.5.13", 1330 | "@vue/runtime-dom": "3.5.13", 1331 | "@vue/server-renderer": "3.5.13", 1332 | "@vue/shared": "3.5.13" 1333 | }, 1334 | "peerDependencies": { 1335 | "typescript": "*" 1336 | }, 1337 | "peerDependenciesMeta": { 1338 | "typescript": { 1339 | "optional": true 1340 | } 1341 | } 1342 | }, 1343 | "node_modules/vue-tsc": { 1344 | "version": "2.2.0", 1345 | "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.0.tgz", 1346 | "integrity": "sha512-gtmM1sUuJ8aSb0KoAFmK9yMxb8TxjewmxqTJ1aKphD5Cbu0rULFY6+UQT51zW7SpUcenfPUuflKyVwyx9Qdnxg==", 1347 | "dev": true, 1348 | "license": "MIT", 1349 | "dependencies": { 1350 | "@volar/typescript": "~2.4.11", 1351 | "@vue/language-core": "2.2.0" 1352 | }, 1353 | "bin": { 1354 | "vue-tsc": "bin/vue-tsc.js" 1355 | }, 1356 | "peerDependencies": { 1357 | "typescript": ">=5.0.0" 1358 | } 1359 | } 1360 | } 1361 | } 1362 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-use-paginator", 3 | "version": "0.4.2", 4 | "description": "Vue use-hook for renderless pagination logic", 5 | "author": "Markus Appel ", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "npm run build:bundle && npm run build:declarations", 9 | "build:bundle": "vite build", 10 | "build:declarations": "vue-tsc src/usePaginator.ts --declaration --emitDeclarationOnly --outDir dist", 11 | "publishPackage": "npm run build && npm publish" 12 | }, 13 | "type": "module", 14 | "main": "./dist/vue-use-paginator.umd.js", 15 | "module": "./dist/vue-use-paginator.es.js", 16 | "files": [ 17 | "dist" 18 | ], 19 | "types": "dist/usePaginator.d.ts", 20 | "exports": { 21 | ".": { 22 | "import": { 23 | "types": "./dist/usePaginator.d.ts", 24 | "default": "./dist/vue-use-paginator.es.js" 25 | }, 26 | "require": { 27 | "types": "./dist/usePaginator.d.ts", 28 | "default": "./dist/vue-use-paginator.umd.js" 29 | } 30 | } 31 | }, 32 | "dependencies": { 33 | "vue": "^3.5.13" 34 | }, 35 | "devDependencies": { 36 | "@babel/types": "^7.26.5", 37 | "@types/node": "^22.10.7", 38 | "@vitejs/plugin-vue": "^5.2.1", 39 | "typescript": "^5.7.3", 40 | "vite": "^6.0.8", 41 | "vue-tsc": "^2.2.0" 42 | }, 43 | "keywords": [ 44 | "vue", 45 | "hooks", 46 | "use-hooks", 47 | "vue-use", 48 | "composition api", 49 | "pagination", 50 | "paginator", 51 | "renderless" 52 | ], 53 | "license": "MIT", 54 | "repository": { 55 | "type": "git", 56 | "url": "https://github.com/Sun0fABeach/vue-use-paginator.git" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 15 | -------------------------------------------------------------------------------- /src/components/Test.vue: -------------------------------------------------------------------------------- 1 | 77 | 78 | 106 | 107 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /src/usePaginator.ts: -------------------------------------------------------------------------------- 1 | import { ref, computed, watch } from 'vue' 2 | import type { Ref, ComputedRef } from 'vue' 3 | 4 | type MaybeRef = T | Ref 5 | 6 | export interface IOptions { 7 | page?: MaybeRef 8 | pageSize?: MaybeRef 9 | numItems?: MaybeRef 10 | numButtons?: MaybeRef 11 | } 12 | 13 | export interface IPagination { 14 | page: Ref 15 | pageSize: Ref 16 | numItems: Ref 17 | numButtons: Ref 18 | numPages: ComputedRef 19 | slice: ComputedRef<[number, number]> 20 | buttons: ComputedRef 21 | hasPrev: ComputedRef 22 | hasNext: ComputedRef 23 | goPrev: () => number 24 | goNext: () => number 25 | goStart: () => 1 26 | goEnd: () => number 27 | } 28 | 29 | interface IButton { 30 | page: number 31 | } 32 | 33 | export interface IPageButton extends IButton { 34 | active: boolean 35 | ellipsis: false 36 | } 37 | 38 | export interface IEllipsisButton extends IButton { 39 | active: false 40 | ellipsis: true 41 | } 42 | 43 | export type IPaginatorButton = IPageButton | IEllipsisButton 44 | 45 | const defaultOptions: Required = { 46 | page: 1, 47 | pageSize: 5, 48 | numItems: 0, 49 | numButtons: 5, 50 | }; 51 | 52 | 53 | export default (userOptions: IOptions): IPagination => { 54 | const options: Required = { ...defaultOptions, ...userOptions } 55 | 56 | const _page = ref(options.page) 57 | const pageSize = ref(options.pageSize) 58 | const numItems = ref(options.numItems) 59 | const numButtons = ref(options.numButtons) 60 | 61 | const page = computed({ 62 | get: () => _page.value, 63 | set: val => { 64 | if (val <= 0) { 65 | _page.value = 1 66 | } else if (val > numPages.value) { 67 | _page.value = numPages.value || 1 68 | } else { 69 | _page.value = val 70 | } 71 | } 72 | }) 73 | 74 | const numPages = computed(() => Math.ceil(numItems.value / pageSize.value)) 75 | 76 | watch(numPages, () => { 77 | if (page.value > numPages.value) { 78 | page.value = numPages.value 79 | } 80 | }) 81 | 82 | const slice = computed((): [number, number] => { 83 | const start = (page.value - 1) * pageSize.value 84 | const end = Math.min(start + pageSize.value, numItems.value) 85 | return [start, end] 86 | }) 87 | 88 | const hasPrev = computed(() => page.value > 1) 89 | const hasNext = computed(() => page.value < numPages.value) 90 | 91 | const goPrev = () => { 92 | if (hasPrev.value) { 93 | page.value-- 94 | } 95 | return page.value 96 | } 97 | const goNext = () => { 98 | if (hasNext.value) { 99 | page.value++ 100 | } 101 | return page.value 102 | } 103 | const goStart = (): 1 => { 104 | page.value = 1 105 | return 1 106 | } 107 | const goEnd = () => { 108 | page.value = numPages.value 109 | return numPages.value 110 | } 111 | 112 | const buttons = computed>(() => { 113 | if (numPages.value <= numButtons.value) { 114 | return fullButtons(page.value, numPages.value) 115 | } else { 116 | return partialButtons(page.value, numPages.value, numButtons.value) 117 | } 118 | }) 119 | 120 | return { 121 | page, 122 | pageSize, 123 | numItems, 124 | numButtons, 125 | numPages, 126 | slice, 127 | hasPrev, 128 | hasNext, 129 | goPrev, 130 | goNext, 131 | goStart, 132 | goEnd, 133 | buttons, 134 | } 135 | } 136 | 137 | 138 | function fullButtons(page: number, numPages: number): Array { 139 | return consecutiveSlots(1, page) 140 | .concat({ page, active: true, ellipsis: false }) 141 | .concat(consecutiveSlots(page + 1, numPages + 1)) 142 | } 143 | 144 | 145 | function partialButtons( 146 | page: number, numPages: number, numButtons: number 147 | ): Array { 148 | let slotsLeft = 0, slotsRight = 0 149 | const halvedButtons = Math.floor(numButtons / 2) 150 | 151 | // check if either side can be filled with pages up to active page 152 | if (page <= halvedButtons) { 153 | slotsLeft = page - 1 154 | slotsRight = numButtons - slotsLeft - 1 155 | 156 | } else if (page >= numPages - halvedButtons) { 157 | slotsRight = numPages - page 158 | slotsLeft = numButtons - slotsRight - 1 159 | 160 | // page sits in center and has 1 or 2 adjacent ellipsis 161 | } else if (numButtons % 2 === 0) { 162 | slotsLeft = halvedButtons - 1 163 | slotsRight = halvedButtons 164 | } else { 165 | slotsLeft = halvedButtons 166 | slotsRight = halvedButtons 167 | } 168 | 169 | const pagesPrev = page - 1 170 | const pagesNext = numPages - page 171 | 172 | let list: Array = [] 173 | 174 | if (pagesPrev <= slotsLeft) { 175 | list = consecutiveSlots(1, pagesPrev + 1) 176 | 177 | } else if (slotsLeft > 0) { 178 | const ellipsis = slotsLeft === 2 ? 2 : Math.ceil(slotsLeft / 2) 179 | const remaining = slotsLeft - ellipsis 180 | let ellipsisPage = Math.ceil(pagesPrev / 2) 181 | if (pagesPrev % 2 === 0) { 182 | ellipsisPage++ 183 | } 184 | 185 | list = (consecutiveSlots(1, ellipsis) as Array) 186 | .concat({ page: ellipsisPage, active: false, ellipsis: true }) 187 | .concat(consecutiveSlots(page - remaining, page)) 188 | } 189 | 190 | list.push({ page, active: true, ellipsis: false }) 191 | 192 | if (pagesNext <= slotsRight) { 193 | list = list.concat(consecutiveSlots(page + 1, numPages + 1)) 194 | 195 | } else if (slotsRight > 0) { 196 | const ellipsis = slotsRight === 2 ? 1 : Math.floor(slotsRight / 2) + 1 197 | const remaining = slotsRight - ellipsis 198 | const ellipsisPage = page + Math.ceil(pagesNext / 2) 199 | 200 | list = list.concat(consecutiveSlots(page + 1, page + ellipsis)) 201 | .concat({ page: ellipsisPage, active: false, ellipsis: true }) 202 | .concat(consecutiveSlots(numPages - remaining + 1, numPages + 1)) 203 | } 204 | 205 | return list 206 | } 207 | 208 | function consecutiveSlots(startIdx: number, endIdx: number): Array { 209 | const result: Array = [] 210 | for (let idx = startIdx; idx < endIdx; idx++) { 211 | result.push({ page: idx, active: false, ellipsis: false }) 212 | } 213 | return result 214 | } 215 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import type { DefineComponent } from 'vue' 5 | const component: DefineComponent<{}, {}, any> 6 | export default component 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "sourceMap": true, 10 | "resolveJsonModule": true, 11 | "isolatedModules": true, 12 | "esModuleInterop": true, 13 | "lib": ["ESNext", "DOM"], 14 | "skipLibCheck": true 15 | }, 16 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "index.ts"], 17 | "references": [{ "path": "./tsconfig.node.json" }] 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | 2 | import { fileURLToPath } from 'node:url' 3 | import { defineConfig } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [vue()], 9 | resolve: { 10 | alias: { 11 | '@': '/src' 12 | } 13 | }, 14 | build: { 15 | lib: { 16 | entry: fileURLToPath(new URL('./index.ts', import.meta.url)), 17 | name: 'VueUsePaginator', 18 | fileName: (format) => `vue-use-paginator.${format}.js` 19 | }, 20 | rollupOptions: { 21 | // make sure to externalize deps that shouldn't be bundled 22 | // into your library 23 | external: ['vue'], 24 | output: { 25 | // Provide global variables to use in the UMD build 26 | // for externalized deps 27 | globals: { 28 | vue: 'Vue' 29 | } 30 | } 31 | } 32 | } 33 | }) 34 | --------------------------------------------------------------------------------