a reactive (signals based) hypermedia web framework (wip) stormlightlabs.github.io/volt/
hypermedia frontend signals

refactor: clean up duplicated code

* fix pnpm workspace setup
* added basic examples
* fix dependency tracking

-2894
dev/pnpm-lock.yaml
··· 1 - lockfileVersion: '9.0' 2 - 3 - settings: 4 - autoInstallPeers: true 5 - excludeLinksFromLockfile: false 6 - 7 - importers: 8 - 9 - .: 10 - dependencies: 11 - chalk: 12 - specifier: ^5.6.2 13 - version: 5.6.2 14 - commander: 15 - specifier: ^14.0.1 16 - version: 14.0.1 17 - terser: 18 - specifier: ^5.44.0 19 - version: 5.44.0 20 - typescript: 21 - specifier: ^5.9.3 22 - version: 5.9.3 23 - devDependencies: 24 - '@eslint/compat': 25 - specifier: ^1.4.0 26 - version: 1.4.0(eslint@9.38.0(jiti@2.6.1)) 27 - '@eslint/js': 28 - specifier: ^9.38.0 29 - version: 9.38.0 30 - '@types/node': 31 - specifier: ^24.7.2 32 - version: 24.8.1 33 - bumpp: 34 - specifier: ^10.3.1 35 - version: 10.3.1 36 - eslint: 37 - specifier: ^9.38.0 38 - version: 9.38.0(jiti@2.6.1) 39 - eslint-plugin-unicorn: 40 - specifier: ^61.0.2 41 - version: 61.0.2(eslint@9.38.0(jiti@2.6.1)) 42 - globals: 43 - specifier: ^16.4.0 44 - version: 16.4.0 45 - tsdown: 46 - specifier: ^0.15.6 47 - version: 0.15.7(typescript@5.9.3) 48 - typescript-eslint: 49 - specifier: ^8.46.1 50 - version: 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) 51 - vitest: 52 - specifier: ^3.2.4 53 - version: 3.2.4(@types/node@24.8.1)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1) 54 - 55 - packages: 56 - 57 - '@babel/generator@7.28.3': 58 - resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} 59 - engines: {node: '>=6.9.0'} 60 - 61 - '@babel/helper-string-parser@7.27.1': 62 - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} 63 - engines: {node: '>=6.9.0'} 64 - 65 - '@babel/helper-validator-identifier@7.27.1': 66 - resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} 67 - engines: {node: '>=6.9.0'} 68 - 69 - '@babel/parser@7.28.4': 70 - resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} 71 - engines: {node: '>=6.0.0'} 72 - hasBin: true 73 - 74 - '@babel/types@7.28.4': 75 - resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} 76 - engines: {node: '>=6.9.0'} 77 - 78 - '@emnapi/core@1.5.0': 79 - resolution: {integrity: sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg==} 80 - 81 - '@emnapi/runtime@1.5.0': 82 - resolution: {integrity: sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==} 83 - 84 - '@emnapi/wasi-threads@1.1.0': 85 - resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} 86 - 87 - '@esbuild/aix-ppc64@0.25.11': 88 - resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} 89 - engines: {node: '>=18'} 90 - cpu: [ppc64] 91 - os: [aix] 92 - 93 - '@esbuild/android-arm64@0.25.11': 94 - resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} 95 - engines: {node: '>=18'} 96 - cpu: [arm64] 97 - os: [android] 98 - 99 - '@esbuild/android-arm@0.25.11': 100 - resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} 101 - engines: {node: '>=18'} 102 - cpu: [arm] 103 - os: [android] 104 - 105 - '@esbuild/android-x64@0.25.11': 106 - resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} 107 - engines: {node: '>=18'} 108 - cpu: [x64] 109 - os: [android] 110 - 111 - '@esbuild/darwin-arm64@0.25.11': 112 - resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} 113 - engines: {node: '>=18'} 114 - cpu: [arm64] 115 - os: [darwin] 116 - 117 - '@esbuild/darwin-x64@0.25.11': 118 - resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} 119 - engines: {node: '>=18'} 120 - cpu: [x64] 121 - os: [darwin] 122 - 123 - '@esbuild/freebsd-arm64@0.25.11': 124 - resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} 125 - engines: {node: '>=18'} 126 - cpu: [arm64] 127 - os: [freebsd] 128 - 129 - '@esbuild/freebsd-x64@0.25.11': 130 - resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} 131 - engines: {node: '>=18'} 132 - cpu: [x64] 133 - os: [freebsd] 134 - 135 - '@esbuild/linux-arm64@0.25.11': 136 - resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} 137 - engines: {node: '>=18'} 138 - cpu: [arm64] 139 - os: [linux] 140 - 141 - '@esbuild/linux-arm@0.25.11': 142 - resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} 143 - engines: {node: '>=18'} 144 - cpu: [arm] 145 - os: [linux] 146 - 147 - '@esbuild/linux-ia32@0.25.11': 148 - resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} 149 - engines: {node: '>=18'} 150 - cpu: [ia32] 151 - os: [linux] 152 - 153 - '@esbuild/linux-loong64@0.25.11': 154 - resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} 155 - engines: {node: '>=18'} 156 - cpu: [loong64] 157 - os: [linux] 158 - 159 - '@esbuild/linux-mips64el@0.25.11': 160 - resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} 161 - engines: {node: '>=18'} 162 - cpu: [mips64el] 163 - os: [linux] 164 - 165 - '@esbuild/linux-ppc64@0.25.11': 166 - resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} 167 - engines: {node: '>=18'} 168 - cpu: [ppc64] 169 - os: [linux] 170 - 171 - '@esbuild/linux-riscv64@0.25.11': 172 - resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} 173 - engines: {node: '>=18'} 174 - cpu: [riscv64] 175 - os: [linux] 176 - 177 - '@esbuild/linux-s390x@0.25.11': 178 - resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} 179 - engines: {node: '>=18'} 180 - cpu: [s390x] 181 - os: [linux] 182 - 183 - '@esbuild/linux-x64@0.25.11': 184 - resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} 185 - engines: {node: '>=18'} 186 - cpu: [x64] 187 - os: [linux] 188 - 189 - '@esbuild/netbsd-arm64@0.25.11': 190 - resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} 191 - engines: {node: '>=18'} 192 - cpu: [arm64] 193 - os: [netbsd] 194 - 195 - '@esbuild/netbsd-x64@0.25.11': 196 - resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} 197 - engines: {node: '>=18'} 198 - cpu: [x64] 199 - os: [netbsd] 200 - 201 - '@esbuild/openbsd-arm64@0.25.11': 202 - resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} 203 - engines: {node: '>=18'} 204 - cpu: [arm64] 205 - os: [openbsd] 206 - 207 - '@esbuild/openbsd-x64@0.25.11': 208 - resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} 209 - engines: {node: '>=18'} 210 - cpu: [x64] 211 - os: [openbsd] 212 - 213 - '@esbuild/openharmony-arm64@0.25.11': 214 - resolution: {integrity: sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==} 215 - engines: {node: '>=18'} 216 - cpu: [arm64] 217 - os: [openharmony] 218 - 219 - '@esbuild/sunos-x64@0.25.11': 220 - resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} 221 - engines: {node: '>=18'} 222 - cpu: [x64] 223 - os: [sunos] 224 - 225 - '@esbuild/win32-arm64@0.25.11': 226 - resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} 227 - engines: {node: '>=18'} 228 - cpu: [arm64] 229 - os: [win32] 230 - 231 - '@esbuild/win32-ia32@0.25.11': 232 - resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} 233 - engines: {node: '>=18'} 234 - cpu: [ia32] 235 - os: [win32] 236 - 237 - '@esbuild/win32-x64@0.25.11': 238 - resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} 239 - engines: {node: '>=18'} 240 - cpu: [x64] 241 - os: [win32] 242 - 243 - '@eslint-community/eslint-utils@4.9.0': 244 - resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} 245 - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 246 - peerDependencies: 247 - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 248 - 249 - '@eslint-community/regexpp@4.12.1': 250 - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} 251 - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} 252 - 253 - '@eslint/compat@1.4.0': 254 - resolution: {integrity: sha512-DEzm5dKeDBPm3r08Ixli/0cmxr8LkRdwxMRUIJBlSCpAwSrvFEJpVBzV+66JhDxiaqKxnRzCXhtiMiczF7Hglg==} 255 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 256 - peerDependencies: 257 - eslint: ^8.40 || 9 258 - peerDependenciesMeta: 259 - eslint: 260 - optional: true 261 - 262 - '@eslint/config-array@0.21.1': 263 - resolution: {integrity: sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==} 264 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 265 - 266 - '@eslint/config-helpers@0.4.1': 267 - resolution: {integrity: sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==} 268 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 269 - 270 - '@eslint/core@0.15.2': 271 - resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} 272 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 273 - 274 - '@eslint/core@0.16.0': 275 - resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==} 276 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 277 - 278 - '@eslint/eslintrc@3.3.1': 279 - resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} 280 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 281 - 282 - '@eslint/js@9.38.0': 283 - resolution: {integrity: sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==} 284 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 285 - 286 - '@eslint/object-schema@2.1.7': 287 - resolution: {integrity: sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==} 288 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 289 - 290 - '@eslint/plugin-kit@0.3.5': 291 - resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} 292 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 293 - 294 - '@eslint/plugin-kit@0.4.0': 295 - resolution: {integrity: sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==} 296 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 297 - 298 - '@humanfs/core@0.19.1': 299 - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} 300 - engines: {node: '>=18.18.0'} 301 - 302 - '@humanfs/node@0.16.7': 303 - resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} 304 - engines: {node: '>=18.18.0'} 305 - 306 - '@humanwhocodes/module-importer@1.0.1': 307 - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} 308 - engines: {node: '>=12.22'} 309 - 310 - '@humanwhocodes/retry@0.4.3': 311 - resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} 312 - engines: {node: '>=18.18'} 313 - 314 - '@jridgewell/gen-mapping@0.3.13': 315 - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} 316 - 317 - '@jridgewell/resolve-uri@3.1.2': 318 - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} 319 - engines: {node: '>=6.0.0'} 320 - 321 - '@jridgewell/source-map@0.3.11': 322 - resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} 323 - 324 - '@jridgewell/sourcemap-codec@1.5.5': 325 - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} 326 - 327 - '@jridgewell/trace-mapping@0.3.31': 328 - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} 329 - 330 - '@napi-rs/wasm-runtime@1.0.7': 331 - resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} 332 - 333 - '@nodelib/fs.scandir@2.1.5': 334 - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} 335 - engines: {node: '>= 8'} 336 - 337 - '@nodelib/fs.stat@2.0.5': 338 - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} 339 - engines: {node: '>= 8'} 340 - 341 - '@nodelib/fs.walk@1.2.8': 342 - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} 343 - engines: {node: '>= 8'} 344 - 345 - '@oxc-project/types@0.94.0': 346 - resolution: {integrity: sha512-+UgQT/4o59cZfH6Cp7G0hwmqEQ0wE+AdIwhikdwnhWI9Dp8CgSY081+Q3O67/wq3VJu8mgUEB93J9EHHn70fOw==} 347 - 348 - '@quansync/fs@0.1.5': 349 - resolution: {integrity: sha512-lNS9hL2aS2NZgNW7BBj+6EBl4rOf8l+tQ0eRY6JWCI8jI2kc53gSoqbjojU0OnAWhzoXiOjFyGsHcDGePB3lhA==} 350 - 351 - '@rolldown/binding-android-arm64@1.0.0-beta.43': 352 - resolution: {integrity: sha512-TP8bcPOb1s6UmY5syhXrDn9k0XkYcw+XaoylTN4cJxf0JOVS2j682I3aTcpfT51hOFGr2bRwNKN9RZ19XxeQbA==} 353 - engines: {node: ^20.19.0 || >=22.12.0} 354 - cpu: [arm64] 355 - os: [android] 356 - 357 - '@rolldown/binding-darwin-arm64@1.0.0-beta.43': 358 - resolution: {integrity: sha512-kuVWnZsE4vEjMF/10SbSUyzucIW2zmdsqFghYMqy+fsjXnRHg0luTU6qWF8IqJf4Cbpm9NEZRnjIEPpAbdiSNQ==} 359 - engines: {node: ^20.19.0 || >=22.12.0} 360 - cpu: [arm64] 361 - os: [darwin] 362 - 363 - '@rolldown/binding-darwin-x64@1.0.0-beta.43': 364 - resolution: {integrity: sha512-u9Ps4sh6lcmJ3vgLtyEg/x4jlhI64U0mM93Ew+tlfFdLDe7yKyA+Fe80cpr2n1mNCeZXrvTSbZluKpXQ0GxLjw==} 365 - engines: {node: ^20.19.0 || >=22.12.0} 366 - cpu: [x64] 367 - os: [darwin] 368 - 369 - '@rolldown/binding-freebsd-x64@1.0.0-beta.43': 370 - resolution: {integrity: sha512-h9lUtVtXgfbk/tnicMpbFfZ3DJvk5Zn2IvmlC1/e0+nUfwoc/TFqpfrRRqcNBXk/e+xiWMSKv6b0MF8N+Rtvlg==} 371 - engines: {node: ^20.19.0 || >=22.12.0} 372 - cpu: [x64] 373 - os: [freebsd] 374 - 375 - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.43': 376 - resolution: {integrity: sha512-IX2C6bA6wM2rX/RvD75ko+ix9yxPKjKGGq7pOhB8wGI4Z4fqX5B1nDHga/qMDmAdCAR1m9ymzxkmqhm/AFYf7A==} 377 - engines: {node: ^20.19.0 || >=22.12.0} 378 - cpu: [arm] 379 - os: [linux] 380 - 381 - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.43': 382 - resolution: {integrity: sha512-mcjd57vEj+CEQbZAzUiaxNzNgwwgOpFtZBWcINm8DNscvkXl5b/s622Z1dqGNWSdrZmdjdC6LWMvu8iHM6v9sQ==} 383 - engines: {node: ^20.19.0 || >=22.12.0} 384 - cpu: [arm64] 385 - os: [linux] 386 - 387 - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.43': 388 - resolution: {integrity: sha512-Pa8QMwlkrztTo/1mVjZmPIQ44tCSci10TBqxzVBvXVA5CFh5EpiEi99fPSll2dHG2uT4dCOMeC6fIhyDdb0zXA==} 389 - engines: {node: ^20.19.0 || >=22.12.0} 390 - cpu: [arm64] 391 - os: [linux] 392 - 393 - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.43': 394 - resolution: {integrity: sha512-BgynXKMjeaX4AfWLARhOKDetBOOghnSiVRjAHVvhiAaDXgdQN8e65mSmXRiVoVtD3cHXx/cfU8Gw0p0K+qYKVQ==} 395 - engines: {node: ^20.19.0 || >=22.12.0} 396 - cpu: [x64] 397 - os: [linux] 398 - 399 - '@rolldown/binding-linux-x64-musl@1.0.0-beta.43': 400 - resolution: {integrity: sha512-VIsoPlOB/tDSAw9CySckBYysoIBqLeps1/umNSYUD8pMtalJyzMTneAVI1HrUdf4ceFmQ5vARoLIXSsPwVFxNg==} 401 - engines: {node: ^20.19.0 || >=22.12.0} 402 - cpu: [x64] 403 - os: [linux] 404 - 405 - '@rolldown/binding-openharmony-arm64@1.0.0-beta.43': 406 - resolution: {integrity: sha512-YDXTxVJG67PqTQMKyjVJSddoPbSWJ4yRz/E3xzTLHqNrTDGY0UuhG8EMr8zsYnfH/0cPFJ3wjQd/hJWHuR6nkA==} 407 - engines: {node: ^20.19.0 || >=22.12.0} 408 - cpu: [arm64] 409 - os: [openharmony] 410 - 411 - '@rolldown/binding-wasm32-wasi@1.0.0-beta.43': 412 - resolution: {integrity: sha512-3M+2DmorXvDuAIGYQ9Z93Oy1G9ETkejLwdXXb1uRTgKN9pMcu7N+KG2zDrJwqyxeeLIFE22AZGtSJm3PJbNu9Q==} 413 - engines: {node: '>=14.0.0'} 414 - cpu: [wasm32] 415 - 416 - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.43': 417 - resolution: {integrity: sha512-/B1j1pJs33y9ywtslOMxryUPHq8zIGu/OGEc2gyed0slimJ8fX2uR/SaJVhB4+NEgCFIeYDR4CX6jynAkeRuCA==} 418 - engines: {node: ^20.19.0 || >=22.12.0} 419 - cpu: [arm64] 420 - os: [win32] 421 - 422 - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.43': 423 - resolution: {integrity: sha512-29oG1swCz7hNP+CQYrsM4EtylsKwuYzM8ljqbqC5TsQwmKat7P8ouDpImsqg/GZxFSXcPP9ezQm0Q0wQwGM3JA==} 424 - engines: {node: ^20.19.0 || >=22.12.0} 425 - cpu: [ia32] 426 - os: [win32] 427 - 428 - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.43': 429 - resolution: {integrity: sha512-eWBV1Ef3gfGNehxVGCyXs7wLayRIgCmyItuCZwYYXW5bsk4EvR4n2GP5m3ohjnx7wdiY3nLmwQfH2Knb5gbNZw==} 430 - engines: {node: ^20.19.0 || >=22.12.0} 431 - cpu: [x64] 432 - os: [win32] 433 - 434 - '@rolldown/pluginutils@1.0.0-beta.43': 435 - resolution: {integrity: sha512-5Uxg7fQUCmfhax7FJke2+8B6cqgeUJUD9o2uXIKXhD+mG0mL6NObmVoi9wXEU1tY89mZKgAYA6fTbftx3q2ZPQ==} 436 - 437 - '@rollup/rollup-android-arm-eabi@4.52.4': 438 - resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} 439 - cpu: [arm] 440 - os: [android] 441 - 442 - '@rollup/rollup-android-arm64@4.52.4': 443 - resolution: {integrity: sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==} 444 - cpu: [arm64] 445 - os: [android] 446 - 447 - '@rollup/rollup-darwin-arm64@4.52.4': 448 - resolution: {integrity: sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==} 449 - cpu: [arm64] 450 - os: [darwin] 451 - 452 - '@rollup/rollup-darwin-x64@4.52.4': 453 - resolution: {integrity: sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==} 454 - cpu: [x64] 455 - os: [darwin] 456 - 457 - '@rollup/rollup-freebsd-arm64@4.52.4': 458 - resolution: {integrity: sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==} 459 - cpu: [arm64] 460 - os: [freebsd] 461 - 462 - '@rollup/rollup-freebsd-x64@4.52.4': 463 - resolution: {integrity: sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==} 464 - cpu: [x64] 465 - os: [freebsd] 466 - 467 - '@rollup/rollup-linux-arm-gnueabihf@4.52.4': 468 - resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==} 469 - cpu: [arm] 470 - os: [linux] 471 - 472 - '@rollup/rollup-linux-arm-musleabihf@4.52.4': 473 - resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==} 474 - cpu: [arm] 475 - os: [linux] 476 - 477 - '@rollup/rollup-linux-arm64-gnu@4.52.4': 478 - resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==} 479 - cpu: [arm64] 480 - os: [linux] 481 - 482 - '@rollup/rollup-linux-arm64-musl@4.52.4': 483 - resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==} 484 - cpu: [arm64] 485 - os: [linux] 486 - 487 - '@rollup/rollup-linux-loong64-gnu@4.52.4': 488 - resolution: {integrity: sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==} 489 - cpu: [loong64] 490 - os: [linux] 491 - 492 - '@rollup/rollup-linux-ppc64-gnu@4.52.4': 493 - resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==} 494 - cpu: [ppc64] 495 - os: [linux] 496 - 497 - '@rollup/rollup-linux-riscv64-gnu@4.52.4': 498 - resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==} 499 - cpu: [riscv64] 500 - os: [linux] 501 - 502 - '@rollup/rollup-linux-riscv64-musl@4.52.4': 503 - resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==} 504 - cpu: [riscv64] 505 - os: [linux] 506 - 507 - '@rollup/rollup-linux-s390x-gnu@4.52.4': 508 - resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==} 509 - cpu: [s390x] 510 - os: [linux] 511 - 512 - '@rollup/rollup-linux-x64-gnu@4.52.4': 513 - resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==} 514 - cpu: [x64] 515 - os: [linux] 516 - 517 - '@rollup/rollup-linux-x64-musl@4.52.4': 518 - resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==} 519 - cpu: [x64] 520 - os: [linux] 521 - 522 - '@rollup/rollup-openharmony-arm64@4.52.4': 523 - resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==} 524 - cpu: [arm64] 525 - os: [openharmony] 526 - 527 - '@rollup/rollup-win32-arm64-msvc@4.52.4': 528 - resolution: {integrity: sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==} 529 - cpu: [arm64] 530 - os: [win32] 531 - 532 - '@rollup/rollup-win32-ia32-msvc@4.52.4': 533 - resolution: {integrity: sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==} 534 - cpu: [ia32] 535 - os: [win32] 536 - 537 - '@rollup/rollup-win32-x64-gnu@4.52.4': 538 - resolution: {integrity: sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==} 539 - cpu: [x64] 540 - os: [win32] 541 - 542 - '@rollup/rollup-win32-x64-msvc@4.52.4': 543 - resolution: {integrity: sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==} 544 - cpu: [x64] 545 - os: [win32] 546 - 547 - '@tybys/wasm-util@0.10.1': 548 - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} 549 - 550 - '@types/chai@5.2.2': 551 - resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} 552 - 553 - '@types/deep-eql@4.0.2': 554 - resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} 555 - 556 - '@types/estree@1.0.8': 557 - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} 558 - 559 - '@types/json-schema@7.0.15': 560 - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} 561 - 562 - '@types/node@24.8.1': 563 - resolution: {integrity: sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q==} 564 - 565 - '@typescript-eslint/eslint-plugin@8.46.1': 566 - resolution: {integrity: sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ==} 567 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 568 - peerDependencies: 569 - '@typescript-eslint/parser': ^8.46.1 570 - eslint: ^8.57.0 || ^9.0.0 571 - typescript: '>=4.8.4 <6.0.0' 572 - 573 - '@typescript-eslint/parser@8.46.1': 574 - resolution: {integrity: sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA==} 575 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 576 - peerDependencies: 577 - eslint: ^8.57.0 || ^9.0.0 578 - typescript: '>=4.8.4 <6.0.0' 579 - 580 - '@typescript-eslint/project-service@8.46.1': 581 - resolution: {integrity: sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg==} 582 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 583 - peerDependencies: 584 - typescript: '>=4.8.4 <6.0.0' 585 - 586 - '@typescript-eslint/scope-manager@8.46.1': 587 - resolution: {integrity: sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A==} 588 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 589 - 590 - '@typescript-eslint/tsconfig-utils@8.46.1': 591 - resolution: {integrity: sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g==} 592 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 593 - peerDependencies: 594 - typescript: '>=4.8.4 <6.0.0' 595 - 596 - '@typescript-eslint/type-utils@8.46.1': 597 - resolution: {integrity: sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw==} 598 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 599 - peerDependencies: 600 - eslint: ^8.57.0 || ^9.0.0 601 - typescript: '>=4.8.4 <6.0.0' 602 - 603 - '@typescript-eslint/types@8.46.1': 604 - resolution: {integrity: sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ==} 605 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 606 - 607 - '@typescript-eslint/typescript-estree@8.46.1': 608 - resolution: {integrity: sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg==} 609 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 610 - peerDependencies: 611 - typescript: '>=4.8.4 <6.0.0' 612 - 613 - '@typescript-eslint/utils@8.46.1': 614 - resolution: {integrity: sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ==} 615 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 616 - peerDependencies: 617 - eslint: ^8.57.0 || ^9.0.0 618 - typescript: '>=4.8.4 <6.0.0' 619 - 620 - '@typescript-eslint/visitor-keys@8.46.1': 621 - resolution: {integrity: sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA==} 622 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 623 - 624 - '@vitest/expect@3.2.4': 625 - resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} 626 - 627 - '@vitest/mocker@3.2.4': 628 - resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} 629 - peerDependencies: 630 - msw: ^2.4.9 631 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 632 - peerDependenciesMeta: 633 - msw: 634 - optional: true 635 - vite: 636 - optional: true 637 - 638 - '@vitest/pretty-format@3.2.4': 639 - resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} 640 - 641 - '@vitest/runner@3.2.4': 642 - resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} 643 - 644 - '@vitest/snapshot@3.2.4': 645 - resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} 646 - 647 - '@vitest/spy@3.2.4': 648 - resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} 649 - 650 - '@vitest/utils@3.2.4': 651 - resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} 652 - 653 - acorn-jsx@5.3.2: 654 - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} 655 - peerDependencies: 656 - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 657 - 658 - acorn@8.15.0: 659 - resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} 660 - engines: {node: '>=0.4.0'} 661 - hasBin: true 662 - 663 - ajv@6.12.6: 664 - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} 665 - 666 - ansi-styles@4.3.0: 667 - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} 668 - engines: {node: '>=8'} 669 - 670 - ansis@4.2.0: 671 - resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} 672 - engines: {node: '>=14'} 673 - 674 - argparse@2.0.1: 675 - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 676 - 677 - args-tokenizer@0.3.0: 678 - resolution: {integrity: sha512-xXAd7G2Mll5W8uo37GETpQ2VrE84M181Z7ugHFGQnJZ50M2mbOv0osSZ9VsSgPfJQ+LVG0prSi0th+ELMsno7Q==} 679 - 680 - assertion-error@2.0.1: 681 - resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} 682 - engines: {node: '>=12'} 683 - 684 - ast-kit@2.1.3: 685 - resolution: {integrity: sha512-TH+b3Lv6pUjy/Nu0m6A2JULtdzLpmqF9x1Dhj00ZoEiML8qvVA9j1flkzTKNYgdEhWrjDwtWNpyyCUbfQe514g==} 686 - engines: {node: '>=20.19.0'} 687 - 688 - balanced-match@1.0.2: 689 - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 690 - 691 - baseline-browser-mapping@2.8.17: 692 - resolution: {integrity: sha512-j5zJcx6golJYTG6c05LUZ3Z8Gi+M62zRT/ycz4Xq4iCOdpcxwg7ngEYD4KA0eWZC7U17qh/Smq8bYbACJ0ipBA==} 693 - hasBin: true 694 - 695 - birpc@2.6.1: 696 - resolution: {integrity: sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==} 697 - 698 - brace-expansion@1.1.12: 699 - resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} 700 - 701 - brace-expansion@2.0.2: 702 - resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} 703 - 704 - braces@3.0.3: 705 - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} 706 - engines: {node: '>=8'} 707 - 708 - browserslist@4.26.3: 709 - resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==} 710 - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 711 - hasBin: true 712 - 713 - buffer-from@1.1.2: 714 - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} 715 - 716 - builtin-modules@5.0.0: 717 - resolution: {integrity: sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==} 718 - engines: {node: '>=18.20'} 719 - 720 - bumpp@10.3.1: 721 - resolution: {integrity: sha512-cOKPRFCWvHcYPJQAHN6V7Jp/wAfnyqQRXQ+2fgWIL6Gao20rpu7xQ1cGGo1APOfmbQmmHngEPg9Fy7nJ3giRkQ==} 722 - engines: {node: '>=18'} 723 - hasBin: true 724 - 725 - c12@3.3.1: 726 - resolution: {integrity: sha512-LcWQ01LT9tkoUINHgpIOv3mMs+Abv7oVCrtpMRi1PaapVEpWoMga5WuT7/DqFTu7URP9ftbOmimNw1KNIGh9DQ==} 727 - peerDependencies: 728 - magicast: ^0.3.5 729 - peerDependenciesMeta: 730 - magicast: 731 - optional: true 732 - 733 - cac@6.7.14: 734 - resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} 735 - engines: {node: '>=8'} 736 - 737 - callsites@3.1.0: 738 - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} 739 - engines: {node: '>=6'} 740 - 741 - caniuse-lite@1.0.30001751: 742 - resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} 743 - 744 - chai@5.3.3: 745 - resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} 746 - engines: {node: '>=18'} 747 - 748 - chalk@4.1.2: 749 - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} 750 - engines: {node: '>=10'} 751 - 752 - chalk@5.6.2: 753 - resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} 754 - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} 755 - 756 - change-case@5.4.4: 757 - resolution: {integrity: sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==} 758 - 759 - check-error@2.1.1: 760 - resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} 761 - engines: {node: '>= 16'} 762 - 763 - chokidar@4.0.3: 764 - resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} 765 - engines: {node: '>= 14.16.0'} 766 - 767 - ci-info@4.3.1: 768 - resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} 769 - engines: {node: '>=8'} 770 - 771 - citty@0.1.6: 772 - resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==} 773 - 774 - clean-regexp@1.0.0: 775 - resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} 776 - engines: {node: '>=4'} 777 - 778 - color-convert@2.0.1: 779 - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} 780 - engines: {node: '>=7.0.0'} 781 - 782 - color-name@1.1.4: 783 - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} 784 - 785 - commander@14.0.1: 786 - resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==} 787 - engines: {node: '>=20'} 788 - 789 - commander@2.20.3: 790 - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} 791 - 792 - concat-map@0.0.1: 793 - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} 794 - 795 - confbox@0.2.2: 796 - resolution: {integrity: sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==} 797 - 798 - consola@3.4.2: 799 - resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} 800 - engines: {node: ^14.18.0 || >=16.10.0} 801 - 802 - core-js-compat@3.46.0: 803 - resolution: {integrity: sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==} 804 - 805 - cross-spawn@7.0.6: 806 - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} 807 - engines: {node: '>= 8'} 808 - 809 - debug@4.4.3: 810 - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} 811 - engines: {node: '>=6.0'} 812 - peerDependencies: 813 - supports-color: '*' 814 - peerDependenciesMeta: 815 - supports-color: 816 - optional: true 817 - 818 - deep-eql@5.0.2: 819 - resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} 820 - engines: {node: '>=6'} 821 - 822 - deep-is@0.1.4: 823 - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} 824 - 825 - defu@6.1.4: 826 - resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} 827 - 828 - destr@2.0.5: 829 - resolution: {integrity: sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==} 830 - 831 - diff@8.0.2: 832 - resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} 833 - engines: {node: '>=0.3.1'} 834 - 835 - dotenv@17.2.3: 836 - resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} 837 - engines: {node: '>=12'} 838 - 839 - dts-resolver@2.1.2: 840 - resolution: {integrity: sha512-xeXHBQkn2ISSXxbJWD828PFjtyg+/UrMDo7W4Ffcs7+YWCquxU8YjV1KoxuiL+eJ5pg3ll+bC6flVv61L3LKZg==} 841 - engines: {node: '>=20.18.0'} 842 - peerDependencies: 843 - oxc-resolver: '>=11.0.0' 844 - peerDependenciesMeta: 845 - oxc-resolver: 846 - optional: true 847 - 848 - electron-to-chromium@1.5.237: 849 - resolution: {integrity: sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==} 850 - 851 - empathic@2.0.0: 852 - resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} 853 - engines: {node: '>=14'} 854 - 855 - es-module-lexer@1.7.0: 856 - resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} 857 - 858 - esbuild@0.25.11: 859 - resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} 860 - engines: {node: '>=18'} 861 - hasBin: true 862 - 863 - escalade@3.2.0: 864 - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} 865 - engines: {node: '>=6'} 866 - 867 - escape-string-regexp@1.0.5: 868 - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} 869 - engines: {node: '>=0.8.0'} 870 - 871 - escape-string-regexp@4.0.0: 872 - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} 873 - engines: {node: '>=10'} 874 - 875 - eslint-plugin-unicorn@61.0.2: 876 - resolution: {integrity: sha512-zLihukvneYT7f74GNbVJXfWIiNQmkc/a9vYBTE4qPkQZswolWNdu+Wsp9sIXno1JOzdn6OUwLPd19ekXVkahRA==} 877 - engines: {node: ^20.10.0 || >=21.0.0} 878 - peerDependencies: 879 - eslint: '>=9.29.0' 880 - 881 - eslint-scope@8.4.0: 882 - resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} 883 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 884 - 885 - eslint-visitor-keys@3.4.3: 886 - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} 887 - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} 888 - 889 - eslint-visitor-keys@4.2.1: 890 - resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} 891 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 892 - 893 - eslint@9.38.0: 894 - resolution: {integrity: sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==} 895 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 896 - hasBin: true 897 - peerDependencies: 898 - jiti: '*' 899 - peerDependenciesMeta: 900 - jiti: 901 - optional: true 902 - 903 - espree@10.4.0: 904 - resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} 905 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 906 - 907 - esquery@1.6.0: 908 - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} 909 - engines: {node: '>=0.10'} 910 - 911 - esrecurse@4.3.0: 912 - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} 913 - engines: {node: '>=4.0'} 914 - 915 - estraverse@5.3.0: 916 - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} 917 - engines: {node: '>=4.0'} 918 - 919 - estree-walker@3.0.3: 920 - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} 921 - 922 - esutils@2.0.3: 923 - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} 924 - engines: {node: '>=0.10.0'} 925 - 926 - expect-type@1.2.2: 927 - resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} 928 - engines: {node: '>=12.0.0'} 929 - 930 - exsolve@1.0.7: 931 - resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==} 932 - 933 - fast-deep-equal@3.1.3: 934 - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} 935 - 936 - fast-glob@3.3.3: 937 - resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} 938 - engines: {node: '>=8.6.0'} 939 - 940 - fast-json-stable-stringify@2.1.0: 941 - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} 942 - 943 - fast-levenshtein@2.0.6: 944 - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} 945 - 946 - fastq@1.19.1: 947 - resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} 948 - 949 - fdir@6.5.0: 950 - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} 951 - engines: {node: '>=12.0.0'} 952 - peerDependencies: 953 - picomatch: ^3 || ^4 954 - peerDependenciesMeta: 955 - picomatch: 956 - optional: true 957 - 958 - file-entry-cache@8.0.0: 959 - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} 960 - engines: {node: '>=16.0.0'} 961 - 962 - fill-range@7.1.1: 963 - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} 964 - engines: {node: '>=8'} 965 - 966 - find-up-simple@1.0.1: 967 - resolution: {integrity: sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==} 968 - engines: {node: '>=18'} 969 - 970 - find-up@5.0.0: 971 - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} 972 - engines: {node: '>=10'} 973 - 974 - flat-cache@4.0.1: 975 - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} 976 - engines: {node: '>=16'} 977 - 978 - flatted@3.3.3: 979 - resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} 980 - 981 - fsevents@2.3.3: 982 - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 983 - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 984 - os: [darwin] 985 - 986 - get-tsconfig@4.12.0: 987 - resolution: {integrity: sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw==} 988 - 989 - giget@2.0.0: 990 - resolution: {integrity: sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==} 991 - hasBin: true 992 - 993 - glob-parent@5.1.2: 994 - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} 995 - engines: {node: '>= 6'} 996 - 997 - glob-parent@6.0.2: 998 - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} 999 - engines: {node: '>=10.13.0'} 1000 - 1001 - globals@14.0.0: 1002 - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} 1003 - engines: {node: '>=18'} 1004 - 1005 - globals@16.4.0: 1006 - resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} 1007 - engines: {node: '>=18'} 1008 - 1009 - graphemer@1.4.0: 1010 - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} 1011 - 1012 - has-flag@4.0.0: 1013 - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} 1014 - engines: {node: '>=8'} 1015 - 1016 - hookable@5.5.3: 1017 - resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} 1018 - 1019 - ignore@5.3.2: 1020 - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} 1021 - engines: {node: '>= 4'} 1022 - 1023 - ignore@7.0.5: 1024 - resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} 1025 - engines: {node: '>= 4'} 1026 - 1027 - import-fresh@3.3.1: 1028 - resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} 1029 - engines: {node: '>=6'} 1030 - 1031 - imurmurhash@0.1.4: 1032 - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} 1033 - engines: {node: '>=0.8.19'} 1034 - 1035 - indent-string@5.0.0: 1036 - resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} 1037 - engines: {node: '>=12'} 1038 - 1039 - is-builtin-module@5.0.0: 1040 - resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==} 1041 - engines: {node: '>=18.20'} 1042 - 1043 - is-extglob@2.1.1: 1044 - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} 1045 - engines: {node: '>=0.10.0'} 1046 - 1047 - is-glob@4.0.3: 1048 - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} 1049 - engines: {node: '>=0.10.0'} 1050 - 1051 - is-number@7.0.0: 1052 - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} 1053 - engines: {node: '>=0.12.0'} 1054 - 1055 - isexe@2.0.0: 1056 - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} 1057 - 1058 - jiti@2.6.1: 1059 - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} 1060 - hasBin: true 1061 - 1062 - js-tokens@9.0.1: 1063 - resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} 1064 - 1065 - js-yaml@4.1.0: 1066 - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} 1067 - hasBin: true 1068 - 1069 - jsesc@3.0.2: 1070 - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} 1071 - engines: {node: '>=6'} 1072 - hasBin: true 1073 - 1074 - jsesc@3.1.0: 1075 - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} 1076 - engines: {node: '>=6'} 1077 - hasBin: true 1078 - 1079 - json-buffer@3.0.1: 1080 - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} 1081 - 1082 - json-schema-traverse@0.4.1: 1083 - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} 1084 - 1085 - json-stable-stringify-without-jsonify@1.0.1: 1086 - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} 1087 - 1088 - jsonc-parser@3.3.1: 1089 - resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} 1090 - 1091 - keyv@4.5.4: 1092 - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} 1093 - 1094 - levn@0.4.1: 1095 - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} 1096 - engines: {node: '>= 0.8.0'} 1097 - 1098 - locate-path@6.0.0: 1099 - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} 1100 - engines: {node: '>=10'} 1101 - 1102 - lodash.merge@4.6.2: 1103 - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} 1104 - 1105 - loupe@3.2.1: 1106 - resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} 1107 - 1108 - magic-string@0.30.19: 1109 - resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} 1110 - 1111 - merge2@1.4.1: 1112 - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} 1113 - engines: {node: '>= 8'} 1114 - 1115 - micromatch@4.0.8: 1116 - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} 1117 - engines: {node: '>=8.6'} 1118 - 1119 - minimatch@3.1.2: 1120 - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} 1121 - 1122 - minimatch@9.0.5: 1123 - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} 1124 - engines: {node: '>=16 || 14 >=14.17'} 1125 - 1126 - ms@2.1.3: 1127 - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} 1128 - 1129 - nanoid@3.3.11: 1130 - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} 1131 - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 1132 - hasBin: true 1133 - 1134 - natural-compare@1.4.0: 1135 - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} 1136 - 1137 - node-fetch-native@1.6.7: 1138 - resolution: {integrity: sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==} 1139 - 1140 - node-releases@2.0.25: 1141 - resolution: {integrity: sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==} 1142 - 1143 - nypm@0.6.2: 1144 - resolution: {integrity: sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==} 1145 - engines: {node: ^14.16.0 || >=16.10.0} 1146 - hasBin: true 1147 - 1148 - ohash@2.0.11: 1149 - resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} 1150 - 1151 - optionator@0.9.4: 1152 - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} 1153 - engines: {node: '>= 0.8.0'} 1154 - 1155 - p-limit@3.1.0: 1156 - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} 1157 - engines: {node: '>=10'} 1158 - 1159 - p-locate@5.0.0: 1160 - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} 1161 - engines: {node: '>=10'} 1162 - 1163 - package-manager-detector@1.4.1: 1164 - resolution: {integrity: sha512-dSMiVLBEA4XaNJ0PRb4N5cV/SEP4BWrWZKBmfF+OUm2pQTiZ6DDkKeWaltwu3JRhLoy59ayIkJ00cx9K9CaYTg==} 1165 - 1166 - parent-module@1.0.1: 1167 - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} 1168 - engines: {node: '>=6'} 1169 - 1170 - path-exists@4.0.0: 1171 - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} 1172 - engines: {node: '>=8'} 1173 - 1174 - path-key@3.1.1: 1175 - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} 1176 - engines: {node: '>=8'} 1177 - 1178 - pathe@2.0.3: 1179 - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} 1180 - 1181 - pathval@2.0.1: 1182 - resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} 1183 - engines: {node: '>= 14.16'} 1184 - 1185 - perfect-debounce@2.0.0: 1186 - resolution: {integrity: sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==} 1187 - 1188 - picocolors@1.1.1: 1189 - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} 1190 - 1191 - picomatch@2.3.1: 1192 - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 1193 - engines: {node: '>=8.6'} 1194 - 1195 - picomatch@4.0.3: 1196 - resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} 1197 - engines: {node: '>=12'} 1198 - 1199 - pkg-types@2.3.0: 1200 - resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} 1201 - 1202 - pluralize@8.0.0: 1203 - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} 1204 - engines: {node: '>=4'} 1205 - 1206 - postcss@8.5.6: 1207 - resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} 1208 - engines: {node: ^10 || ^12 || >=14} 1209 - 1210 - prelude-ls@1.2.1: 1211 - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} 1212 - engines: {node: '>= 0.8.0'} 1213 - 1214 - punycode@2.3.1: 1215 - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} 1216 - engines: {node: '>=6'} 1217 - 1218 - quansync@0.2.11: 1219 - resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} 1220 - 1221 - queue-microtask@1.2.3: 1222 - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} 1223 - 1224 - rc9@2.1.2: 1225 - resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} 1226 - 1227 - readdirp@4.1.2: 1228 - resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} 1229 - engines: {node: '>= 14.18.0'} 1230 - 1231 - regexp-tree@0.1.27: 1232 - resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} 1233 - hasBin: true 1234 - 1235 - regjsparser@0.12.0: 1236 - resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} 1237 - hasBin: true 1238 - 1239 - resolve-from@4.0.0: 1240 - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} 1241 - engines: {node: '>=4'} 1242 - 1243 - resolve-pkg-maps@1.0.0: 1244 - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} 1245 - 1246 - reusify@1.1.0: 1247 - resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} 1248 - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} 1249 - 1250 - rolldown-plugin-dts@0.16.12: 1251 - resolution: {integrity: sha512-9dGjm5oqtKcbZNhpzyBgb8KrYiU616A7IqcFWG7Msp1RKAXQ/hapjivRg+g5IYWSiFhnk3OKYV5T4Ft1t8Cczg==} 1252 - engines: {node: '>=20.18.0'} 1253 - peerDependencies: 1254 - '@ts-macro/tsc': ^0.3.6 1255 - '@typescript/native-preview': '>=7.0.0-dev.20250601.1' 1256 - rolldown: ^1.0.0-beta.9 1257 - typescript: ^5.0.0 1258 - vue-tsc: ~3.1.0 1259 - peerDependenciesMeta: 1260 - '@ts-macro/tsc': 1261 - optional: true 1262 - '@typescript/native-preview': 1263 - optional: true 1264 - typescript: 1265 - optional: true 1266 - vue-tsc: 1267 - optional: true 1268 - 1269 - rolldown@1.0.0-beta.43: 1270 - resolution: {integrity: sha512-6RcqyRx0tY1MlRLnjXPp/849Rl/CPFhzpGGwNPEPjKwqBMqPq/Rbbkxasa8s0x+IkUk46ty4jazb5skZ/Vgdhw==} 1271 - engines: {node: ^20.19.0 || >=22.12.0} 1272 - hasBin: true 1273 - 1274 - rollup@4.52.4: 1275 - resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==} 1276 - engines: {node: '>=18.0.0', npm: '>=8.0.0'} 1277 - hasBin: true 1278 - 1279 - run-parallel@1.2.0: 1280 - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} 1281 - 1282 - semver@7.7.3: 1283 - resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} 1284 - engines: {node: '>=10'} 1285 - hasBin: true 1286 - 1287 - shebang-command@2.0.0: 1288 - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} 1289 - engines: {node: '>=8'} 1290 - 1291 - shebang-regex@3.0.0: 1292 - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} 1293 - engines: {node: '>=8'} 1294 - 1295 - siginfo@2.0.0: 1296 - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} 1297 - 1298 - source-map-js@1.2.1: 1299 - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} 1300 - engines: {node: '>=0.10.0'} 1301 - 1302 - source-map-support@0.5.21: 1303 - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} 1304 - 1305 - source-map@0.6.1: 1306 - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 1307 - engines: {node: '>=0.10.0'} 1308 - 1309 - stackback@0.0.2: 1310 - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} 1311 - 1312 - std-env@3.10.0: 1313 - resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} 1314 - 1315 - strip-indent@4.1.1: 1316 - resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==} 1317 - engines: {node: '>=12'} 1318 - 1319 - strip-json-comments@3.1.1: 1320 - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} 1321 - engines: {node: '>=8'} 1322 - 1323 - strip-literal@3.1.0: 1324 - resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} 1325 - 1326 - supports-color@7.2.0: 1327 - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} 1328 - engines: {node: '>=8'} 1329 - 1330 - terser@5.44.0: 1331 - resolution: {integrity: sha512-nIVck8DK+GM/0Frwd+nIhZ84pR/BX7rmXMfYwyg+Sri5oGVE99/E3KvXqpC2xHFxyqXyGHTKBSioxxplrO4I4w==} 1332 - engines: {node: '>=10'} 1333 - hasBin: true 1334 - 1335 - tinybench@2.9.0: 1336 - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} 1337 - 1338 - tinyexec@0.3.2: 1339 - resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} 1340 - 1341 - tinyexec@1.0.1: 1342 - resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} 1343 - 1344 - tinyglobby@0.2.15: 1345 - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} 1346 - engines: {node: '>=12.0.0'} 1347 - 1348 - tinypool@1.1.1: 1349 - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} 1350 - engines: {node: ^18.0.0 || >=20.0.0} 1351 - 1352 - tinyrainbow@2.0.0: 1353 - resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} 1354 - engines: {node: '>=14.0.0'} 1355 - 1356 - tinyspy@4.0.4: 1357 - resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} 1358 - engines: {node: '>=14.0.0'} 1359 - 1360 - to-regex-range@5.0.1: 1361 - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} 1362 - engines: {node: '>=8.0'} 1363 - 1364 - tree-kill@1.2.2: 1365 - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} 1366 - hasBin: true 1367 - 1368 - ts-api-utils@2.1.0: 1369 - resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} 1370 - engines: {node: '>=18.12'} 1371 - peerDependencies: 1372 - typescript: '>=4.8.4' 1373 - 1374 - tsdown@0.15.7: 1375 - resolution: {integrity: sha512-uFaVgWAogjOMqjY+CQwrUt3C6wzy6ynt82CIoXymnbS17ipUZ8WDXUceJjkislUahF/BZc5+W44Ue3p2oWtqUg==} 1376 - engines: {node: '>=20.19.0'} 1377 - hasBin: true 1378 - peerDependencies: 1379 - '@arethetypeswrong/core': ^0.18.1 1380 - publint: ^0.3.0 1381 - typescript: ^5.0.0 1382 - unplugin-lightningcss: ^0.4.0 1383 - unplugin-unused: ^0.5.0 1384 - peerDependenciesMeta: 1385 - '@arethetypeswrong/core': 1386 - optional: true 1387 - publint: 1388 - optional: true 1389 - typescript: 1390 - optional: true 1391 - unplugin-lightningcss: 1392 - optional: true 1393 - unplugin-unused: 1394 - optional: true 1395 - 1396 - tslib@2.8.1: 1397 - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} 1398 - 1399 - type-check@0.4.0: 1400 - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} 1401 - engines: {node: '>= 0.8.0'} 1402 - 1403 - typescript-eslint@8.46.1: 1404 - resolution: {integrity: sha512-VHgijW803JafdSsDO8I761r3SHrgk4T00IdyQ+/UsthtgPRsBWQLqoSxOolxTpxRKi1kGXK0bSz4CoAc9ObqJA==} 1405 - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} 1406 - peerDependencies: 1407 - eslint: ^8.57.0 || ^9.0.0 1408 - typescript: '>=4.8.4 <6.0.0' 1409 - 1410 - typescript@5.9.3: 1411 - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} 1412 - engines: {node: '>=14.17'} 1413 - hasBin: true 1414 - 1415 - unconfig@7.3.3: 1416 - resolution: {integrity: sha512-QCkQoOnJF8L107gxfHL0uavn7WD9b3dpBcFX6HtfQYmjw2YzWxGuFQ0N0J6tE9oguCBJn9KOvfqYDCMPHIZrBA==} 1417 - 1418 - undici-types@7.14.0: 1419 - resolution: {integrity: sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA==} 1420 - 1421 - update-browserslist-db@1.1.3: 1422 - resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} 1423 - hasBin: true 1424 - peerDependencies: 1425 - browserslist: '>= 4.21.0' 1426 - 1427 - uri-js@4.4.1: 1428 - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} 1429 - 1430 - vite-node@3.2.4: 1431 - resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} 1432 - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1433 - hasBin: true 1434 - 1435 - vite@7.1.10: 1436 - resolution: {integrity: sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==} 1437 - engines: {node: ^20.19.0 || >=22.12.0} 1438 - hasBin: true 1439 - peerDependencies: 1440 - '@types/node': ^20.19.0 || >=22.12.0 1441 - jiti: '>=1.21.0' 1442 - less: ^4.0.0 1443 - lightningcss: ^1.21.0 1444 - sass: ^1.70.0 1445 - sass-embedded: ^1.70.0 1446 - stylus: '>=0.54.8' 1447 - sugarss: ^5.0.0 1448 - terser: ^5.16.0 1449 - tsx: ^4.8.1 1450 - yaml: ^2.4.2 1451 - peerDependenciesMeta: 1452 - '@types/node': 1453 - optional: true 1454 - jiti: 1455 - optional: true 1456 - less: 1457 - optional: true 1458 - lightningcss: 1459 - optional: true 1460 - sass: 1461 - optional: true 1462 - sass-embedded: 1463 - optional: true 1464 - stylus: 1465 - optional: true 1466 - sugarss: 1467 - optional: true 1468 - terser: 1469 - optional: true 1470 - tsx: 1471 - optional: true 1472 - yaml: 1473 - optional: true 1474 - 1475 - vitest@3.2.4: 1476 - resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} 1477 - engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} 1478 - hasBin: true 1479 - peerDependencies: 1480 - '@edge-runtime/vm': '*' 1481 - '@types/debug': ^4.1.12 1482 - '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 1483 - '@vitest/browser': 3.2.4 1484 - '@vitest/ui': 3.2.4 1485 - happy-dom: '*' 1486 - jsdom: '*' 1487 - peerDependenciesMeta: 1488 - '@edge-runtime/vm': 1489 - optional: true 1490 - '@types/debug': 1491 - optional: true 1492 - '@types/node': 1493 - optional: true 1494 - '@vitest/browser': 1495 - optional: true 1496 - '@vitest/ui': 1497 - optional: true 1498 - happy-dom: 1499 - optional: true 1500 - jsdom: 1501 - optional: true 1502 - 1503 - which@2.0.2: 1504 - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} 1505 - engines: {node: '>= 8'} 1506 - hasBin: true 1507 - 1508 - why-is-node-running@2.3.0: 1509 - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} 1510 - engines: {node: '>=8'} 1511 - hasBin: true 1512 - 1513 - word-wrap@1.2.5: 1514 - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} 1515 - engines: {node: '>=0.10.0'} 1516 - 1517 - yaml@2.8.1: 1518 - resolution: {integrity: sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==} 1519 - engines: {node: '>= 14.6'} 1520 - hasBin: true 1521 - 1522 - yocto-queue@0.1.0: 1523 - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} 1524 - engines: {node: '>=10'} 1525 - 1526 - snapshots: 1527 - 1528 - '@babel/generator@7.28.3': 1529 - dependencies: 1530 - '@babel/parser': 7.28.4 1531 - '@babel/types': 7.28.4 1532 - '@jridgewell/gen-mapping': 0.3.13 1533 - '@jridgewell/trace-mapping': 0.3.31 1534 - jsesc: 3.1.0 1535 - 1536 - '@babel/helper-string-parser@7.27.1': {} 1537 - 1538 - '@babel/helper-validator-identifier@7.27.1': {} 1539 - 1540 - '@babel/parser@7.28.4': 1541 - dependencies: 1542 - '@babel/types': 7.28.4 1543 - 1544 - '@babel/types@7.28.4': 1545 - dependencies: 1546 - '@babel/helper-string-parser': 7.27.1 1547 - '@babel/helper-validator-identifier': 7.27.1 1548 - 1549 - '@emnapi/core@1.5.0': 1550 - dependencies: 1551 - '@emnapi/wasi-threads': 1.1.0 1552 - tslib: 2.8.1 1553 - optional: true 1554 - 1555 - '@emnapi/runtime@1.5.0': 1556 - dependencies: 1557 - tslib: 2.8.1 1558 - optional: true 1559 - 1560 - '@emnapi/wasi-threads@1.1.0': 1561 - dependencies: 1562 - tslib: 2.8.1 1563 - optional: true 1564 - 1565 - '@esbuild/aix-ppc64@0.25.11': 1566 - optional: true 1567 - 1568 - '@esbuild/android-arm64@0.25.11': 1569 - optional: true 1570 - 1571 - '@esbuild/android-arm@0.25.11': 1572 - optional: true 1573 - 1574 - '@esbuild/android-x64@0.25.11': 1575 - optional: true 1576 - 1577 - '@esbuild/darwin-arm64@0.25.11': 1578 - optional: true 1579 - 1580 - '@esbuild/darwin-x64@0.25.11': 1581 - optional: true 1582 - 1583 - '@esbuild/freebsd-arm64@0.25.11': 1584 - optional: true 1585 - 1586 - '@esbuild/freebsd-x64@0.25.11': 1587 - optional: true 1588 - 1589 - '@esbuild/linux-arm64@0.25.11': 1590 - optional: true 1591 - 1592 - '@esbuild/linux-arm@0.25.11': 1593 - optional: true 1594 - 1595 - '@esbuild/linux-ia32@0.25.11': 1596 - optional: true 1597 - 1598 - '@esbuild/linux-loong64@0.25.11': 1599 - optional: true 1600 - 1601 - '@esbuild/linux-mips64el@0.25.11': 1602 - optional: true 1603 - 1604 - '@esbuild/linux-ppc64@0.25.11': 1605 - optional: true 1606 - 1607 - '@esbuild/linux-riscv64@0.25.11': 1608 - optional: true 1609 - 1610 - '@esbuild/linux-s390x@0.25.11': 1611 - optional: true 1612 - 1613 - '@esbuild/linux-x64@0.25.11': 1614 - optional: true 1615 - 1616 - '@esbuild/netbsd-arm64@0.25.11': 1617 - optional: true 1618 - 1619 - '@esbuild/netbsd-x64@0.25.11': 1620 - optional: true 1621 - 1622 - '@esbuild/openbsd-arm64@0.25.11': 1623 - optional: true 1624 - 1625 - '@esbuild/openbsd-x64@0.25.11': 1626 - optional: true 1627 - 1628 - '@esbuild/openharmony-arm64@0.25.11': 1629 - optional: true 1630 - 1631 - '@esbuild/sunos-x64@0.25.11': 1632 - optional: true 1633 - 1634 - '@esbuild/win32-arm64@0.25.11': 1635 - optional: true 1636 - 1637 - '@esbuild/win32-ia32@0.25.11': 1638 - optional: true 1639 - 1640 - '@esbuild/win32-x64@0.25.11': 1641 - optional: true 1642 - 1643 - '@eslint-community/eslint-utils@4.9.0(eslint@9.38.0(jiti@2.6.1))': 1644 - dependencies: 1645 - eslint: 9.38.0(jiti@2.6.1) 1646 - eslint-visitor-keys: 3.4.3 1647 - 1648 - '@eslint-community/regexpp@4.12.1': {} 1649 - 1650 - '@eslint/compat@1.4.0(eslint@9.38.0(jiti@2.6.1))': 1651 - dependencies: 1652 - '@eslint/core': 0.16.0 1653 - optionalDependencies: 1654 - eslint: 9.38.0(jiti@2.6.1) 1655 - 1656 - '@eslint/config-array@0.21.1': 1657 - dependencies: 1658 - '@eslint/object-schema': 2.1.7 1659 - debug: 4.4.3 1660 - minimatch: 3.1.2 1661 - transitivePeerDependencies: 1662 - - supports-color 1663 - 1664 - '@eslint/config-helpers@0.4.1': 1665 - dependencies: 1666 - '@eslint/core': 0.16.0 1667 - 1668 - '@eslint/core@0.15.2': 1669 - dependencies: 1670 - '@types/json-schema': 7.0.15 1671 - 1672 - '@eslint/core@0.16.0': 1673 - dependencies: 1674 - '@types/json-schema': 7.0.15 1675 - 1676 - '@eslint/eslintrc@3.3.1': 1677 - dependencies: 1678 - ajv: 6.12.6 1679 - debug: 4.4.3 1680 - espree: 10.4.0 1681 - globals: 14.0.0 1682 - ignore: 5.3.2 1683 - import-fresh: 3.3.1 1684 - js-yaml: 4.1.0 1685 - minimatch: 3.1.2 1686 - strip-json-comments: 3.1.1 1687 - transitivePeerDependencies: 1688 - - supports-color 1689 - 1690 - '@eslint/js@9.38.0': {} 1691 - 1692 - '@eslint/object-schema@2.1.7': {} 1693 - 1694 - '@eslint/plugin-kit@0.3.5': 1695 - dependencies: 1696 - '@eslint/core': 0.15.2 1697 - levn: 0.4.1 1698 - 1699 - '@eslint/plugin-kit@0.4.0': 1700 - dependencies: 1701 - '@eslint/core': 0.16.0 1702 - levn: 0.4.1 1703 - 1704 - '@humanfs/core@0.19.1': {} 1705 - 1706 - '@humanfs/node@0.16.7': 1707 - dependencies: 1708 - '@humanfs/core': 0.19.1 1709 - '@humanwhocodes/retry': 0.4.3 1710 - 1711 - '@humanwhocodes/module-importer@1.0.1': {} 1712 - 1713 - '@humanwhocodes/retry@0.4.3': {} 1714 - 1715 - '@jridgewell/gen-mapping@0.3.13': 1716 - dependencies: 1717 - '@jridgewell/sourcemap-codec': 1.5.5 1718 - '@jridgewell/trace-mapping': 0.3.31 1719 - 1720 - '@jridgewell/resolve-uri@3.1.2': {} 1721 - 1722 - '@jridgewell/source-map@0.3.11': 1723 - dependencies: 1724 - '@jridgewell/gen-mapping': 0.3.13 1725 - '@jridgewell/trace-mapping': 0.3.31 1726 - 1727 - '@jridgewell/sourcemap-codec@1.5.5': {} 1728 - 1729 - '@jridgewell/trace-mapping@0.3.31': 1730 - dependencies: 1731 - '@jridgewell/resolve-uri': 3.1.2 1732 - '@jridgewell/sourcemap-codec': 1.5.5 1733 - 1734 - '@napi-rs/wasm-runtime@1.0.7': 1735 - dependencies: 1736 - '@emnapi/core': 1.5.0 1737 - '@emnapi/runtime': 1.5.0 1738 - '@tybys/wasm-util': 0.10.1 1739 - optional: true 1740 - 1741 - '@nodelib/fs.scandir@2.1.5': 1742 - dependencies: 1743 - '@nodelib/fs.stat': 2.0.5 1744 - run-parallel: 1.2.0 1745 - 1746 - '@nodelib/fs.stat@2.0.5': {} 1747 - 1748 - '@nodelib/fs.walk@1.2.8': 1749 - dependencies: 1750 - '@nodelib/fs.scandir': 2.1.5 1751 - fastq: 1.19.1 1752 - 1753 - '@oxc-project/types@0.94.0': {} 1754 - 1755 - '@quansync/fs@0.1.5': 1756 - dependencies: 1757 - quansync: 0.2.11 1758 - 1759 - '@rolldown/binding-android-arm64@1.0.0-beta.43': 1760 - optional: true 1761 - 1762 - '@rolldown/binding-darwin-arm64@1.0.0-beta.43': 1763 - optional: true 1764 - 1765 - '@rolldown/binding-darwin-x64@1.0.0-beta.43': 1766 - optional: true 1767 - 1768 - '@rolldown/binding-freebsd-x64@1.0.0-beta.43': 1769 - optional: true 1770 - 1771 - '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.43': 1772 - optional: true 1773 - 1774 - '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.43': 1775 - optional: true 1776 - 1777 - '@rolldown/binding-linux-arm64-musl@1.0.0-beta.43': 1778 - optional: true 1779 - 1780 - '@rolldown/binding-linux-x64-gnu@1.0.0-beta.43': 1781 - optional: true 1782 - 1783 - '@rolldown/binding-linux-x64-musl@1.0.0-beta.43': 1784 - optional: true 1785 - 1786 - '@rolldown/binding-openharmony-arm64@1.0.0-beta.43': 1787 - optional: true 1788 - 1789 - '@rolldown/binding-wasm32-wasi@1.0.0-beta.43': 1790 - dependencies: 1791 - '@napi-rs/wasm-runtime': 1.0.7 1792 - optional: true 1793 - 1794 - '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.43': 1795 - optional: true 1796 - 1797 - '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.43': 1798 - optional: true 1799 - 1800 - '@rolldown/binding-win32-x64-msvc@1.0.0-beta.43': 1801 - optional: true 1802 - 1803 - '@rolldown/pluginutils@1.0.0-beta.43': {} 1804 - 1805 - '@rollup/rollup-android-arm-eabi@4.52.4': 1806 - optional: true 1807 - 1808 - '@rollup/rollup-android-arm64@4.52.4': 1809 - optional: true 1810 - 1811 - '@rollup/rollup-darwin-arm64@4.52.4': 1812 - optional: true 1813 - 1814 - '@rollup/rollup-darwin-x64@4.52.4': 1815 - optional: true 1816 - 1817 - '@rollup/rollup-freebsd-arm64@4.52.4': 1818 - optional: true 1819 - 1820 - '@rollup/rollup-freebsd-x64@4.52.4': 1821 - optional: true 1822 - 1823 - '@rollup/rollup-linux-arm-gnueabihf@4.52.4': 1824 - optional: true 1825 - 1826 - '@rollup/rollup-linux-arm-musleabihf@4.52.4': 1827 - optional: true 1828 - 1829 - '@rollup/rollup-linux-arm64-gnu@4.52.4': 1830 - optional: true 1831 - 1832 - '@rollup/rollup-linux-arm64-musl@4.52.4': 1833 - optional: true 1834 - 1835 - '@rollup/rollup-linux-loong64-gnu@4.52.4': 1836 - optional: true 1837 - 1838 - '@rollup/rollup-linux-ppc64-gnu@4.52.4': 1839 - optional: true 1840 - 1841 - '@rollup/rollup-linux-riscv64-gnu@4.52.4': 1842 - optional: true 1843 - 1844 - '@rollup/rollup-linux-riscv64-musl@4.52.4': 1845 - optional: true 1846 - 1847 - '@rollup/rollup-linux-s390x-gnu@4.52.4': 1848 - optional: true 1849 - 1850 - '@rollup/rollup-linux-x64-gnu@4.52.4': 1851 - optional: true 1852 - 1853 - '@rollup/rollup-linux-x64-musl@4.52.4': 1854 - optional: true 1855 - 1856 - '@rollup/rollup-openharmony-arm64@4.52.4': 1857 - optional: true 1858 - 1859 - '@rollup/rollup-win32-arm64-msvc@4.52.4': 1860 - optional: true 1861 - 1862 - '@rollup/rollup-win32-ia32-msvc@4.52.4': 1863 - optional: true 1864 - 1865 - '@rollup/rollup-win32-x64-gnu@4.52.4': 1866 - optional: true 1867 - 1868 - '@rollup/rollup-win32-x64-msvc@4.52.4': 1869 - optional: true 1870 - 1871 - '@tybys/wasm-util@0.10.1': 1872 - dependencies: 1873 - tslib: 2.8.1 1874 - optional: true 1875 - 1876 - '@types/chai@5.2.2': 1877 - dependencies: 1878 - '@types/deep-eql': 4.0.2 1879 - 1880 - '@types/deep-eql@4.0.2': {} 1881 - 1882 - '@types/estree@1.0.8': {} 1883 - 1884 - '@types/json-schema@7.0.15': {} 1885 - 1886 - '@types/node@24.8.1': 1887 - dependencies: 1888 - undici-types: 7.14.0 1889 - 1890 - '@typescript-eslint/eslint-plugin@8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': 1891 - dependencies: 1892 - '@eslint-community/regexpp': 4.12.1 1893 - '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) 1894 - '@typescript-eslint/scope-manager': 8.46.1 1895 - '@typescript-eslint/type-utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) 1896 - '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) 1897 - '@typescript-eslint/visitor-keys': 8.46.1 1898 - eslint: 9.38.0(jiti@2.6.1) 1899 - graphemer: 1.4.0 1900 - ignore: 7.0.5 1901 - natural-compare: 1.4.0 1902 - ts-api-utils: 2.1.0(typescript@5.9.3) 1903 - typescript: 5.9.3 1904 - transitivePeerDependencies: 1905 - - supports-color 1906 - 1907 - '@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': 1908 - dependencies: 1909 - '@typescript-eslint/scope-manager': 8.46.1 1910 - '@typescript-eslint/types': 8.46.1 1911 - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) 1912 - '@typescript-eslint/visitor-keys': 8.46.1 1913 - debug: 4.4.3 1914 - eslint: 9.38.0(jiti@2.6.1) 1915 - typescript: 5.9.3 1916 - transitivePeerDependencies: 1917 - - supports-color 1918 - 1919 - '@typescript-eslint/project-service@8.46.1(typescript@5.9.3)': 1920 - dependencies: 1921 - '@typescript-eslint/tsconfig-utils': 8.46.1(typescript@5.9.3) 1922 - '@typescript-eslint/types': 8.46.1 1923 - debug: 4.4.3 1924 - typescript: 5.9.3 1925 - transitivePeerDependencies: 1926 - - supports-color 1927 - 1928 - '@typescript-eslint/scope-manager@8.46.1': 1929 - dependencies: 1930 - '@typescript-eslint/types': 8.46.1 1931 - '@typescript-eslint/visitor-keys': 8.46.1 1932 - 1933 - '@typescript-eslint/tsconfig-utils@8.46.1(typescript@5.9.3)': 1934 - dependencies: 1935 - typescript: 5.9.3 1936 - 1937 - '@typescript-eslint/type-utils@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': 1938 - dependencies: 1939 - '@typescript-eslint/types': 8.46.1 1940 - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) 1941 - '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) 1942 - debug: 4.4.3 1943 - eslint: 9.38.0(jiti@2.6.1) 1944 - ts-api-utils: 2.1.0(typescript@5.9.3) 1945 - typescript: 5.9.3 1946 - transitivePeerDependencies: 1947 - - supports-color 1948 - 1949 - '@typescript-eslint/types@8.46.1': {} 1950 - 1951 - '@typescript-eslint/typescript-estree@8.46.1(typescript@5.9.3)': 1952 - dependencies: 1953 - '@typescript-eslint/project-service': 8.46.1(typescript@5.9.3) 1954 - '@typescript-eslint/tsconfig-utils': 8.46.1(typescript@5.9.3) 1955 - '@typescript-eslint/types': 8.46.1 1956 - '@typescript-eslint/visitor-keys': 8.46.1 1957 - debug: 4.4.3 1958 - fast-glob: 3.3.3 1959 - is-glob: 4.0.3 1960 - minimatch: 9.0.5 1961 - semver: 7.7.3 1962 - ts-api-utils: 2.1.0(typescript@5.9.3) 1963 - typescript: 5.9.3 1964 - transitivePeerDependencies: 1965 - - supports-color 1966 - 1967 - '@typescript-eslint/utils@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3)': 1968 - dependencies: 1969 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) 1970 - '@typescript-eslint/scope-manager': 8.46.1 1971 - '@typescript-eslint/types': 8.46.1 1972 - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) 1973 - eslint: 9.38.0(jiti@2.6.1) 1974 - typescript: 5.9.3 1975 - transitivePeerDependencies: 1976 - - supports-color 1977 - 1978 - '@typescript-eslint/visitor-keys@8.46.1': 1979 - dependencies: 1980 - '@typescript-eslint/types': 8.46.1 1981 - eslint-visitor-keys: 4.2.1 1982 - 1983 - '@vitest/expect@3.2.4': 1984 - dependencies: 1985 - '@types/chai': 5.2.2 1986 - '@vitest/spy': 3.2.4 1987 - '@vitest/utils': 3.2.4 1988 - chai: 5.3.3 1989 - tinyrainbow: 2.0.0 1990 - 1991 - '@vitest/mocker@3.2.4(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1))': 1992 - dependencies: 1993 - '@vitest/spy': 3.2.4 1994 - estree-walker: 3.0.3 1995 - magic-string: 0.30.19 1996 - optionalDependencies: 1997 - vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1) 1998 - 1999 - '@vitest/pretty-format@3.2.4': 2000 - dependencies: 2001 - tinyrainbow: 2.0.0 2002 - 2003 - '@vitest/runner@3.2.4': 2004 - dependencies: 2005 - '@vitest/utils': 3.2.4 2006 - pathe: 2.0.3 2007 - strip-literal: 3.1.0 2008 - 2009 - '@vitest/snapshot@3.2.4': 2010 - dependencies: 2011 - '@vitest/pretty-format': 3.2.4 2012 - magic-string: 0.30.19 2013 - pathe: 2.0.3 2014 - 2015 - '@vitest/spy@3.2.4': 2016 - dependencies: 2017 - tinyspy: 4.0.4 2018 - 2019 - '@vitest/utils@3.2.4': 2020 - dependencies: 2021 - '@vitest/pretty-format': 3.2.4 2022 - loupe: 3.2.1 2023 - tinyrainbow: 2.0.0 2024 - 2025 - acorn-jsx@5.3.2(acorn@8.15.0): 2026 - dependencies: 2027 - acorn: 8.15.0 2028 - 2029 - acorn@8.15.0: {} 2030 - 2031 - ajv@6.12.6: 2032 - dependencies: 2033 - fast-deep-equal: 3.1.3 2034 - fast-json-stable-stringify: 2.1.0 2035 - json-schema-traverse: 0.4.1 2036 - uri-js: 4.4.1 2037 - 2038 - ansi-styles@4.3.0: 2039 - dependencies: 2040 - color-convert: 2.0.1 2041 - 2042 - ansis@4.2.0: {} 2043 - 2044 - argparse@2.0.1: {} 2045 - 2046 - args-tokenizer@0.3.0: {} 2047 - 2048 - assertion-error@2.0.1: {} 2049 - 2050 - ast-kit@2.1.3: 2051 - dependencies: 2052 - '@babel/parser': 7.28.4 2053 - pathe: 2.0.3 2054 - 2055 - balanced-match@1.0.2: {} 2056 - 2057 - baseline-browser-mapping@2.8.17: {} 2058 - 2059 - birpc@2.6.1: {} 2060 - 2061 - brace-expansion@1.1.12: 2062 - dependencies: 2063 - balanced-match: 1.0.2 2064 - concat-map: 0.0.1 2065 - 2066 - brace-expansion@2.0.2: 2067 - dependencies: 2068 - balanced-match: 1.0.2 2069 - 2070 - braces@3.0.3: 2071 - dependencies: 2072 - fill-range: 7.1.1 2073 - 2074 - browserslist@4.26.3: 2075 - dependencies: 2076 - baseline-browser-mapping: 2.8.17 2077 - caniuse-lite: 1.0.30001751 2078 - electron-to-chromium: 1.5.237 2079 - node-releases: 2.0.25 2080 - update-browserslist-db: 1.1.3(browserslist@4.26.3) 2081 - 2082 - buffer-from@1.1.2: {} 2083 - 2084 - builtin-modules@5.0.0: {} 2085 - 2086 - bumpp@10.3.1: 2087 - dependencies: 2088 - ansis: 4.2.0 2089 - args-tokenizer: 0.3.0 2090 - c12: 3.3.1 2091 - cac: 6.7.14 2092 - escalade: 3.2.0 2093 - jsonc-parser: 3.3.1 2094 - package-manager-detector: 1.4.1 2095 - semver: 7.7.3 2096 - tinyexec: 1.0.1 2097 - tinyglobby: 0.2.15 2098 - yaml: 2.8.1 2099 - transitivePeerDependencies: 2100 - - magicast 2101 - 2102 - c12@3.3.1: 2103 - dependencies: 2104 - chokidar: 4.0.3 2105 - confbox: 0.2.2 2106 - defu: 6.1.4 2107 - dotenv: 17.2.3 2108 - exsolve: 1.0.7 2109 - giget: 2.0.0 2110 - jiti: 2.6.1 2111 - ohash: 2.0.11 2112 - pathe: 2.0.3 2113 - perfect-debounce: 2.0.0 2114 - pkg-types: 2.3.0 2115 - rc9: 2.1.2 2116 - 2117 - cac@6.7.14: {} 2118 - 2119 - callsites@3.1.0: {} 2120 - 2121 - caniuse-lite@1.0.30001751: {} 2122 - 2123 - chai@5.3.3: 2124 - dependencies: 2125 - assertion-error: 2.0.1 2126 - check-error: 2.1.1 2127 - deep-eql: 5.0.2 2128 - loupe: 3.2.1 2129 - pathval: 2.0.1 2130 - 2131 - chalk@4.1.2: 2132 - dependencies: 2133 - ansi-styles: 4.3.0 2134 - supports-color: 7.2.0 2135 - 2136 - chalk@5.6.2: {} 2137 - 2138 - change-case@5.4.4: {} 2139 - 2140 - check-error@2.1.1: {} 2141 - 2142 - chokidar@4.0.3: 2143 - dependencies: 2144 - readdirp: 4.1.2 2145 - 2146 - ci-info@4.3.1: {} 2147 - 2148 - citty@0.1.6: 2149 - dependencies: 2150 - consola: 3.4.2 2151 - 2152 - clean-regexp@1.0.0: 2153 - dependencies: 2154 - escape-string-regexp: 1.0.5 2155 - 2156 - color-convert@2.0.1: 2157 - dependencies: 2158 - color-name: 1.1.4 2159 - 2160 - color-name@1.1.4: {} 2161 - 2162 - commander@14.0.1: {} 2163 - 2164 - commander@2.20.3: {} 2165 - 2166 - concat-map@0.0.1: {} 2167 - 2168 - confbox@0.2.2: {} 2169 - 2170 - consola@3.4.2: {} 2171 - 2172 - core-js-compat@3.46.0: 2173 - dependencies: 2174 - browserslist: 4.26.3 2175 - 2176 - cross-spawn@7.0.6: 2177 - dependencies: 2178 - path-key: 3.1.1 2179 - shebang-command: 2.0.0 2180 - which: 2.0.2 2181 - 2182 - debug@4.4.3: 2183 - dependencies: 2184 - ms: 2.1.3 2185 - 2186 - deep-eql@5.0.2: {} 2187 - 2188 - deep-is@0.1.4: {} 2189 - 2190 - defu@6.1.4: {} 2191 - 2192 - destr@2.0.5: {} 2193 - 2194 - diff@8.0.2: {} 2195 - 2196 - dotenv@17.2.3: {} 2197 - 2198 - dts-resolver@2.1.2: {} 2199 - 2200 - electron-to-chromium@1.5.237: {} 2201 - 2202 - empathic@2.0.0: {} 2203 - 2204 - es-module-lexer@1.7.0: {} 2205 - 2206 - esbuild@0.25.11: 2207 - optionalDependencies: 2208 - '@esbuild/aix-ppc64': 0.25.11 2209 - '@esbuild/android-arm': 0.25.11 2210 - '@esbuild/android-arm64': 0.25.11 2211 - '@esbuild/android-x64': 0.25.11 2212 - '@esbuild/darwin-arm64': 0.25.11 2213 - '@esbuild/darwin-x64': 0.25.11 2214 - '@esbuild/freebsd-arm64': 0.25.11 2215 - '@esbuild/freebsd-x64': 0.25.11 2216 - '@esbuild/linux-arm': 0.25.11 2217 - '@esbuild/linux-arm64': 0.25.11 2218 - '@esbuild/linux-ia32': 0.25.11 2219 - '@esbuild/linux-loong64': 0.25.11 2220 - '@esbuild/linux-mips64el': 0.25.11 2221 - '@esbuild/linux-ppc64': 0.25.11 2222 - '@esbuild/linux-riscv64': 0.25.11 2223 - '@esbuild/linux-s390x': 0.25.11 2224 - '@esbuild/linux-x64': 0.25.11 2225 - '@esbuild/netbsd-arm64': 0.25.11 2226 - '@esbuild/netbsd-x64': 0.25.11 2227 - '@esbuild/openbsd-arm64': 0.25.11 2228 - '@esbuild/openbsd-x64': 0.25.11 2229 - '@esbuild/openharmony-arm64': 0.25.11 2230 - '@esbuild/sunos-x64': 0.25.11 2231 - '@esbuild/win32-arm64': 0.25.11 2232 - '@esbuild/win32-ia32': 0.25.11 2233 - '@esbuild/win32-x64': 0.25.11 2234 - 2235 - escalade@3.2.0: {} 2236 - 2237 - escape-string-regexp@1.0.5: {} 2238 - 2239 - escape-string-regexp@4.0.0: {} 2240 - 2241 - eslint-plugin-unicorn@61.0.2(eslint@9.38.0(jiti@2.6.1)): 2242 - dependencies: 2243 - '@babel/helper-validator-identifier': 7.27.1 2244 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) 2245 - '@eslint/plugin-kit': 0.3.5 2246 - change-case: 5.4.4 2247 - ci-info: 4.3.1 2248 - clean-regexp: 1.0.0 2249 - core-js-compat: 3.46.0 2250 - eslint: 9.38.0(jiti@2.6.1) 2251 - esquery: 1.6.0 2252 - find-up-simple: 1.0.1 2253 - globals: 16.4.0 2254 - indent-string: 5.0.0 2255 - is-builtin-module: 5.0.0 2256 - jsesc: 3.1.0 2257 - pluralize: 8.0.0 2258 - regexp-tree: 0.1.27 2259 - regjsparser: 0.12.0 2260 - semver: 7.7.3 2261 - strip-indent: 4.1.1 2262 - 2263 - eslint-scope@8.4.0: 2264 - dependencies: 2265 - esrecurse: 4.3.0 2266 - estraverse: 5.3.0 2267 - 2268 - eslint-visitor-keys@3.4.3: {} 2269 - 2270 - eslint-visitor-keys@4.2.1: {} 2271 - 2272 - eslint@9.38.0(jiti@2.6.1): 2273 - dependencies: 2274 - '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@2.6.1)) 2275 - '@eslint-community/regexpp': 4.12.1 2276 - '@eslint/config-array': 0.21.1 2277 - '@eslint/config-helpers': 0.4.1 2278 - '@eslint/core': 0.16.0 2279 - '@eslint/eslintrc': 3.3.1 2280 - '@eslint/js': 9.38.0 2281 - '@eslint/plugin-kit': 0.4.0 2282 - '@humanfs/node': 0.16.7 2283 - '@humanwhocodes/module-importer': 1.0.1 2284 - '@humanwhocodes/retry': 0.4.3 2285 - '@types/estree': 1.0.8 2286 - ajv: 6.12.6 2287 - chalk: 4.1.2 2288 - cross-spawn: 7.0.6 2289 - debug: 4.4.3 2290 - escape-string-regexp: 4.0.0 2291 - eslint-scope: 8.4.0 2292 - eslint-visitor-keys: 4.2.1 2293 - espree: 10.4.0 2294 - esquery: 1.6.0 2295 - esutils: 2.0.3 2296 - fast-deep-equal: 3.1.3 2297 - file-entry-cache: 8.0.0 2298 - find-up: 5.0.0 2299 - glob-parent: 6.0.2 2300 - ignore: 5.3.2 2301 - imurmurhash: 0.1.4 2302 - is-glob: 4.0.3 2303 - json-stable-stringify-without-jsonify: 1.0.1 2304 - lodash.merge: 4.6.2 2305 - minimatch: 3.1.2 2306 - natural-compare: 1.4.0 2307 - optionator: 0.9.4 2308 - optionalDependencies: 2309 - jiti: 2.6.1 2310 - transitivePeerDependencies: 2311 - - supports-color 2312 - 2313 - espree@10.4.0: 2314 - dependencies: 2315 - acorn: 8.15.0 2316 - acorn-jsx: 5.3.2(acorn@8.15.0) 2317 - eslint-visitor-keys: 4.2.1 2318 - 2319 - esquery@1.6.0: 2320 - dependencies: 2321 - estraverse: 5.3.0 2322 - 2323 - esrecurse@4.3.0: 2324 - dependencies: 2325 - estraverse: 5.3.0 2326 - 2327 - estraverse@5.3.0: {} 2328 - 2329 - estree-walker@3.0.3: 2330 - dependencies: 2331 - '@types/estree': 1.0.8 2332 - 2333 - esutils@2.0.3: {} 2334 - 2335 - expect-type@1.2.2: {} 2336 - 2337 - exsolve@1.0.7: {} 2338 - 2339 - fast-deep-equal@3.1.3: {} 2340 - 2341 - fast-glob@3.3.3: 2342 - dependencies: 2343 - '@nodelib/fs.stat': 2.0.5 2344 - '@nodelib/fs.walk': 1.2.8 2345 - glob-parent: 5.1.2 2346 - merge2: 1.4.1 2347 - micromatch: 4.0.8 2348 - 2349 - fast-json-stable-stringify@2.1.0: {} 2350 - 2351 - fast-levenshtein@2.0.6: {} 2352 - 2353 - fastq@1.19.1: 2354 - dependencies: 2355 - reusify: 1.1.0 2356 - 2357 - fdir@6.5.0(picomatch@4.0.3): 2358 - optionalDependencies: 2359 - picomatch: 4.0.3 2360 - 2361 - file-entry-cache@8.0.0: 2362 - dependencies: 2363 - flat-cache: 4.0.1 2364 - 2365 - fill-range@7.1.1: 2366 - dependencies: 2367 - to-regex-range: 5.0.1 2368 - 2369 - find-up-simple@1.0.1: {} 2370 - 2371 - find-up@5.0.0: 2372 - dependencies: 2373 - locate-path: 6.0.0 2374 - path-exists: 4.0.0 2375 - 2376 - flat-cache@4.0.1: 2377 - dependencies: 2378 - flatted: 3.3.3 2379 - keyv: 4.5.4 2380 - 2381 - flatted@3.3.3: {} 2382 - 2383 - fsevents@2.3.3: 2384 - optional: true 2385 - 2386 - get-tsconfig@4.12.0: 2387 - dependencies: 2388 - resolve-pkg-maps: 1.0.0 2389 - 2390 - giget@2.0.0: 2391 - dependencies: 2392 - citty: 0.1.6 2393 - consola: 3.4.2 2394 - defu: 6.1.4 2395 - node-fetch-native: 1.6.7 2396 - nypm: 0.6.2 2397 - pathe: 2.0.3 2398 - 2399 - glob-parent@5.1.2: 2400 - dependencies: 2401 - is-glob: 4.0.3 2402 - 2403 - glob-parent@6.0.2: 2404 - dependencies: 2405 - is-glob: 4.0.3 2406 - 2407 - globals@14.0.0: {} 2408 - 2409 - globals@16.4.0: {} 2410 - 2411 - graphemer@1.4.0: {} 2412 - 2413 - has-flag@4.0.0: {} 2414 - 2415 - hookable@5.5.3: {} 2416 - 2417 - ignore@5.3.2: {} 2418 - 2419 - ignore@7.0.5: {} 2420 - 2421 - import-fresh@3.3.1: 2422 - dependencies: 2423 - parent-module: 1.0.1 2424 - resolve-from: 4.0.0 2425 - 2426 - imurmurhash@0.1.4: {} 2427 - 2428 - indent-string@5.0.0: {} 2429 - 2430 - is-builtin-module@5.0.0: 2431 - dependencies: 2432 - builtin-modules: 5.0.0 2433 - 2434 - is-extglob@2.1.1: {} 2435 - 2436 - is-glob@4.0.3: 2437 - dependencies: 2438 - is-extglob: 2.1.1 2439 - 2440 - is-number@7.0.0: {} 2441 - 2442 - isexe@2.0.0: {} 2443 - 2444 - jiti@2.6.1: {} 2445 - 2446 - js-tokens@9.0.1: {} 2447 - 2448 - js-yaml@4.1.0: 2449 - dependencies: 2450 - argparse: 2.0.1 2451 - 2452 - jsesc@3.0.2: {} 2453 - 2454 - jsesc@3.1.0: {} 2455 - 2456 - json-buffer@3.0.1: {} 2457 - 2458 - json-schema-traverse@0.4.1: {} 2459 - 2460 - json-stable-stringify-without-jsonify@1.0.1: {} 2461 - 2462 - jsonc-parser@3.3.1: {} 2463 - 2464 - keyv@4.5.4: 2465 - dependencies: 2466 - json-buffer: 3.0.1 2467 - 2468 - levn@0.4.1: 2469 - dependencies: 2470 - prelude-ls: 1.2.1 2471 - type-check: 0.4.0 2472 - 2473 - locate-path@6.0.0: 2474 - dependencies: 2475 - p-locate: 5.0.0 2476 - 2477 - lodash.merge@4.6.2: {} 2478 - 2479 - loupe@3.2.1: {} 2480 - 2481 - magic-string@0.30.19: 2482 - dependencies: 2483 - '@jridgewell/sourcemap-codec': 1.5.5 2484 - 2485 - merge2@1.4.1: {} 2486 - 2487 - micromatch@4.0.8: 2488 - dependencies: 2489 - braces: 3.0.3 2490 - picomatch: 2.3.1 2491 - 2492 - minimatch@3.1.2: 2493 - dependencies: 2494 - brace-expansion: 1.1.12 2495 - 2496 - minimatch@9.0.5: 2497 - dependencies: 2498 - brace-expansion: 2.0.2 2499 - 2500 - ms@2.1.3: {} 2501 - 2502 - nanoid@3.3.11: {} 2503 - 2504 - natural-compare@1.4.0: {} 2505 - 2506 - node-fetch-native@1.6.7: {} 2507 - 2508 - node-releases@2.0.25: {} 2509 - 2510 - nypm@0.6.2: 2511 - dependencies: 2512 - citty: 0.1.6 2513 - consola: 3.4.2 2514 - pathe: 2.0.3 2515 - pkg-types: 2.3.0 2516 - tinyexec: 1.0.1 2517 - 2518 - ohash@2.0.11: {} 2519 - 2520 - optionator@0.9.4: 2521 - dependencies: 2522 - deep-is: 0.1.4 2523 - fast-levenshtein: 2.0.6 2524 - levn: 0.4.1 2525 - prelude-ls: 1.2.1 2526 - type-check: 0.4.0 2527 - word-wrap: 1.2.5 2528 - 2529 - p-limit@3.1.0: 2530 - dependencies: 2531 - yocto-queue: 0.1.0 2532 - 2533 - p-locate@5.0.0: 2534 - dependencies: 2535 - p-limit: 3.1.0 2536 - 2537 - package-manager-detector@1.4.1: {} 2538 - 2539 - parent-module@1.0.1: 2540 - dependencies: 2541 - callsites: 3.1.0 2542 - 2543 - path-exists@4.0.0: {} 2544 - 2545 - path-key@3.1.1: {} 2546 - 2547 - pathe@2.0.3: {} 2548 - 2549 - pathval@2.0.1: {} 2550 - 2551 - perfect-debounce@2.0.0: {} 2552 - 2553 - picocolors@1.1.1: {} 2554 - 2555 - picomatch@2.3.1: {} 2556 - 2557 - picomatch@4.0.3: {} 2558 - 2559 - pkg-types@2.3.0: 2560 - dependencies: 2561 - confbox: 0.2.2 2562 - exsolve: 1.0.7 2563 - pathe: 2.0.3 2564 - 2565 - pluralize@8.0.0: {} 2566 - 2567 - postcss@8.5.6: 2568 - dependencies: 2569 - nanoid: 3.3.11 2570 - picocolors: 1.1.1 2571 - source-map-js: 1.2.1 2572 - 2573 - prelude-ls@1.2.1: {} 2574 - 2575 - punycode@2.3.1: {} 2576 - 2577 - quansync@0.2.11: {} 2578 - 2579 - queue-microtask@1.2.3: {} 2580 - 2581 - rc9@2.1.2: 2582 - dependencies: 2583 - defu: 6.1.4 2584 - destr: 2.0.5 2585 - 2586 - readdirp@4.1.2: {} 2587 - 2588 - regexp-tree@0.1.27: {} 2589 - 2590 - regjsparser@0.12.0: 2591 - dependencies: 2592 - jsesc: 3.0.2 2593 - 2594 - resolve-from@4.0.0: {} 2595 - 2596 - resolve-pkg-maps@1.0.0: {} 2597 - 2598 - reusify@1.1.0: {} 2599 - 2600 - rolldown-plugin-dts@0.16.12(rolldown@1.0.0-beta.43)(typescript@5.9.3): 2601 - dependencies: 2602 - '@babel/generator': 7.28.3 2603 - '@babel/parser': 7.28.4 2604 - '@babel/types': 7.28.4 2605 - ast-kit: 2.1.3 2606 - birpc: 2.6.1 2607 - debug: 4.4.3 2608 - dts-resolver: 2.1.2 2609 - get-tsconfig: 4.12.0 2610 - magic-string: 0.30.19 2611 - rolldown: 1.0.0-beta.43 2612 - optionalDependencies: 2613 - typescript: 5.9.3 2614 - transitivePeerDependencies: 2615 - - oxc-resolver 2616 - - supports-color 2617 - 2618 - rolldown@1.0.0-beta.43: 2619 - dependencies: 2620 - '@oxc-project/types': 0.94.0 2621 - '@rolldown/pluginutils': 1.0.0-beta.43 2622 - ansis: 4.2.0 2623 - optionalDependencies: 2624 - '@rolldown/binding-android-arm64': 1.0.0-beta.43 2625 - '@rolldown/binding-darwin-arm64': 1.0.0-beta.43 2626 - '@rolldown/binding-darwin-x64': 1.0.0-beta.43 2627 - '@rolldown/binding-freebsd-x64': 1.0.0-beta.43 2628 - '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.43 2629 - '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.43 2630 - '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.43 2631 - '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.43 2632 - '@rolldown/binding-linux-x64-musl': 1.0.0-beta.43 2633 - '@rolldown/binding-openharmony-arm64': 1.0.0-beta.43 2634 - '@rolldown/binding-wasm32-wasi': 1.0.0-beta.43 2635 - '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.43 2636 - '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.43 2637 - '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.43 2638 - 2639 - rollup@4.52.4: 2640 - dependencies: 2641 - '@types/estree': 1.0.8 2642 - optionalDependencies: 2643 - '@rollup/rollup-android-arm-eabi': 4.52.4 2644 - '@rollup/rollup-android-arm64': 4.52.4 2645 - '@rollup/rollup-darwin-arm64': 4.52.4 2646 - '@rollup/rollup-darwin-x64': 4.52.4 2647 - '@rollup/rollup-freebsd-arm64': 4.52.4 2648 - '@rollup/rollup-freebsd-x64': 4.52.4 2649 - '@rollup/rollup-linux-arm-gnueabihf': 4.52.4 2650 - '@rollup/rollup-linux-arm-musleabihf': 4.52.4 2651 - '@rollup/rollup-linux-arm64-gnu': 4.52.4 2652 - '@rollup/rollup-linux-arm64-musl': 4.52.4 2653 - '@rollup/rollup-linux-loong64-gnu': 4.52.4 2654 - '@rollup/rollup-linux-ppc64-gnu': 4.52.4 2655 - '@rollup/rollup-linux-riscv64-gnu': 4.52.4 2656 - '@rollup/rollup-linux-riscv64-musl': 4.52.4 2657 - '@rollup/rollup-linux-s390x-gnu': 4.52.4 2658 - '@rollup/rollup-linux-x64-gnu': 4.52.4 2659 - '@rollup/rollup-linux-x64-musl': 4.52.4 2660 - '@rollup/rollup-openharmony-arm64': 4.52.4 2661 - '@rollup/rollup-win32-arm64-msvc': 4.52.4 2662 - '@rollup/rollup-win32-ia32-msvc': 4.52.4 2663 - '@rollup/rollup-win32-x64-gnu': 4.52.4 2664 - '@rollup/rollup-win32-x64-msvc': 4.52.4 2665 - fsevents: 2.3.3 2666 - 2667 - run-parallel@1.2.0: 2668 - dependencies: 2669 - queue-microtask: 1.2.3 2670 - 2671 - semver@7.7.3: {} 2672 - 2673 - shebang-command@2.0.0: 2674 - dependencies: 2675 - shebang-regex: 3.0.0 2676 - 2677 - shebang-regex@3.0.0: {} 2678 - 2679 - siginfo@2.0.0: {} 2680 - 2681 - source-map-js@1.2.1: {} 2682 - 2683 - source-map-support@0.5.21: 2684 - dependencies: 2685 - buffer-from: 1.1.2 2686 - source-map: 0.6.1 2687 - 2688 - source-map@0.6.1: {} 2689 - 2690 - stackback@0.0.2: {} 2691 - 2692 - std-env@3.10.0: {} 2693 - 2694 - strip-indent@4.1.1: {} 2695 - 2696 - strip-json-comments@3.1.1: {} 2697 - 2698 - strip-literal@3.1.0: 2699 - dependencies: 2700 - js-tokens: 9.0.1 2701 - 2702 - supports-color@7.2.0: 2703 - dependencies: 2704 - has-flag: 4.0.0 2705 - 2706 - terser@5.44.0: 2707 - dependencies: 2708 - '@jridgewell/source-map': 0.3.11 2709 - acorn: 8.15.0 2710 - commander: 2.20.3 2711 - source-map-support: 0.5.21 2712 - 2713 - tinybench@2.9.0: {} 2714 - 2715 - tinyexec@0.3.2: {} 2716 - 2717 - tinyexec@1.0.1: {} 2718 - 2719 - tinyglobby@0.2.15: 2720 - dependencies: 2721 - fdir: 6.5.0(picomatch@4.0.3) 2722 - picomatch: 4.0.3 2723 - 2724 - tinypool@1.1.1: {} 2725 - 2726 - tinyrainbow@2.0.0: {} 2727 - 2728 - tinyspy@4.0.4: {} 2729 - 2730 - to-regex-range@5.0.1: 2731 - dependencies: 2732 - is-number: 7.0.0 2733 - 2734 - tree-kill@1.2.2: {} 2735 - 2736 - ts-api-utils@2.1.0(typescript@5.9.3): 2737 - dependencies: 2738 - typescript: 5.9.3 2739 - 2740 - tsdown@0.15.7(typescript@5.9.3): 2741 - dependencies: 2742 - ansis: 4.2.0 2743 - cac: 6.7.14 2744 - chokidar: 4.0.3 2745 - debug: 4.4.3 2746 - diff: 8.0.2 2747 - empathic: 2.0.0 2748 - hookable: 5.5.3 2749 - rolldown: 1.0.0-beta.43 2750 - rolldown-plugin-dts: 0.16.12(rolldown@1.0.0-beta.43)(typescript@5.9.3) 2751 - semver: 7.7.3 2752 - tinyexec: 1.0.1 2753 - tinyglobby: 0.2.15 2754 - tree-kill: 1.2.2 2755 - unconfig: 7.3.3 2756 - optionalDependencies: 2757 - typescript: 5.9.3 2758 - transitivePeerDependencies: 2759 - - '@ts-macro/tsc' 2760 - - '@typescript/native-preview' 2761 - - oxc-resolver 2762 - - supports-color 2763 - - vue-tsc 2764 - 2765 - tslib@2.8.1: 2766 - optional: true 2767 - 2768 - type-check@0.4.0: 2769 - dependencies: 2770 - prelude-ls: 1.2.1 2771 - 2772 - typescript-eslint@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3): 2773 - dependencies: 2774 - '@typescript-eslint/eslint-plugin': 8.46.1(@typescript-eslint/parser@8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) 2775 - '@typescript-eslint/parser': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) 2776 - '@typescript-eslint/typescript-estree': 8.46.1(typescript@5.9.3) 2777 - '@typescript-eslint/utils': 8.46.1(eslint@9.38.0(jiti@2.6.1))(typescript@5.9.3) 2778 - eslint: 9.38.0(jiti@2.6.1) 2779 - typescript: 5.9.3 2780 - transitivePeerDependencies: 2781 - - supports-color 2782 - 2783 - typescript@5.9.3: {} 2784 - 2785 - unconfig@7.3.3: 2786 - dependencies: 2787 - '@quansync/fs': 0.1.5 2788 - defu: 6.1.4 2789 - jiti: 2.6.1 2790 - quansync: 0.2.11 2791 - 2792 - undici-types@7.14.0: {} 2793 - 2794 - update-browserslist-db@1.1.3(browserslist@4.26.3): 2795 - dependencies: 2796 - browserslist: 4.26.3 2797 - escalade: 3.2.0 2798 - picocolors: 1.1.1 2799 - 2800 - uri-js@4.4.1: 2801 - dependencies: 2802 - punycode: 2.3.1 2803 - 2804 - vite-node@3.2.4(@types/node@24.8.1)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1): 2805 - dependencies: 2806 - cac: 6.7.14 2807 - debug: 4.4.3 2808 - es-module-lexer: 1.7.0 2809 - pathe: 2.0.3 2810 - vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1) 2811 - transitivePeerDependencies: 2812 - - '@types/node' 2813 - - jiti 2814 - - less 2815 - - lightningcss 2816 - - sass 2817 - - sass-embedded 2818 - - stylus 2819 - - sugarss 2820 - - supports-color 2821 - - terser 2822 - - tsx 2823 - - yaml 2824 - 2825 - vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1): 2826 - dependencies: 2827 - esbuild: 0.25.11 2828 - fdir: 6.5.0(picomatch@4.0.3) 2829 - picomatch: 4.0.3 2830 - postcss: 8.5.6 2831 - rollup: 4.52.4 2832 - tinyglobby: 0.2.15 2833 - optionalDependencies: 2834 - '@types/node': 24.8.1 2835 - fsevents: 2.3.3 2836 - jiti: 2.6.1 2837 - terser: 5.44.0 2838 - yaml: 2.8.1 2839 - 2840 - vitest@3.2.4(@types/node@24.8.1)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1): 2841 - dependencies: 2842 - '@types/chai': 5.2.2 2843 - '@vitest/expect': 3.2.4 2844 - '@vitest/mocker': 3.2.4(vite@7.1.10(@types/node@24.8.1)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1)) 2845 - '@vitest/pretty-format': 3.2.4 2846 - '@vitest/runner': 3.2.4 2847 - '@vitest/snapshot': 3.2.4 2848 - '@vitest/spy': 3.2.4 2849 - '@vitest/utils': 3.2.4 2850 - chai: 5.3.3 2851 - debug: 4.4.3 2852 - expect-type: 1.2.2 2853 - magic-string: 0.30.19 2854 - pathe: 2.0.3 2855 - picomatch: 4.0.3 2856 - std-env: 3.10.0 2857 - tinybench: 2.9.0 2858 - tinyexec: 0.3.2 2859 - tinyglobby: 0.2.15 2860 - tinypool: 1.1.1 2861 - tinyrainbow: 2.0.0 2862 - vite: 7.1.10(@types/node@24.8.1)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1) 2863 - vite-node: 3.2.4(@types/node@24.8.1)(jiti@2.6.1)(terser@5.44.0)(yaml@2.8.1) 2864 - why-is-node-running: 2.3.0 2865 - optionalDependencies: 2866 - '@types/node': 24.8.1 2867 - transitivePeerDependencies: 2868 - - jiti 2869 - - less 2870 - - lightningcss 2871 - - msw 2872 - - sass 2873 - - sass-embedded 2874 - - stylus 2875 - - sugarss 2876 - - supports-color 2877 - - terser 2878 - - tsx 2879 - - yaml 2880 - 2881 - which@2.0.2: 2882 - dependencies: 2883 - isexe: 2.0.0 2884 - 2885 - why-is-node-running@2.3.0: 2886 - dependencies: 2887 - siginfo: 2.0.0 2888 - stackback: 0.0.2 2889 - 2890 - word-wrap@1.2.5: {} 2891 - 2892 - yaml@2.8.1: {} 2893 - 2894 - yocto-queue@0.1.0: {}
-2
dev/pnpm-workspace.yaml
··· 1 - onlyBuiltDependencies: 2 - - esbuild
examples/.gitkeep

This is a binary file and will not be displayed.

+89
examples/counter/index.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8"> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 + <title>Counter - Volt.js Example</title> 7 + <link rel="stylesheet" href="../dist/volt.min.css"> 8 + <style> 9 + .counter-display { 10 + font-size: 4rem; 11 + font-weight: bold; 12 + text-align: center; 13 + margin: var(--space-2xl) 0; 14 + transition: color var(--transition-base); 15 + } 16 + .counter-display.negative { color: var(--color-error); } 17 + .counter-display.zero { color: var(--color-text-muted); } 18 + .counter-display.positive { color: var(--color-success); } 19 + 20 + .button-group { 21 + display: flex; 22 + gap: var(--space-sm); 23 + justify-content: center; 24 + flex-wrap: wrap; 25 + } 26 + 27 + .stats { 28 + display: grid; 29 + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); 30 + gap: var(--space-md); 31 + margin-top: var(--space-xl); 32 + padding-top: var(--space-xl); 33 + border-top: 1px solid var(--color-border); 34 + } 35 + 36 + .stat { 37 + text-align: center; 38 + padding: var(--space-md); 39 + background: var(--color-bg-alt); 40 + border-radius: var(--radius-md); 41 + } 42 + </style> 43 + </head> 44 + <body> 45 + <article 46 + data-volt 47 + data-volt-state='{"count": 0}' 48 + data-volt-computed:doubled="count * 2" 49 + data-volt-computed:is-negative="count < 0" 50 + data-volt-computed:is-zero="count === 0" 51 + data-volt-computed:is-positive="count > 0" 52 + > 53 + <h1>Interactive Counter</h1> 54 + <p>A simple demonstration of Volt.js reactivity with inline state, computed values, and conditional styling.</p> 55 + 56 + <div class="counter-display" data-volt-class="{negative: isNegative, zero: isZero, positive: isPositive}"> 57 + <span data-volt-text="count">0</span> 58 + </div> 59 + 60 + <div class="button-group"> 61 + <button data-volt-on-click="count.set(count.get() - 10)">-10</button> 62 + <button data-volt-on-click="count.set(count.get() - 1)">-1</button> 63 + <input type="reset" value="Reset" data-volt-on-click="count.set(0)"> 64 + <button data-volt-on-click="count.set(count.get() + 1)">+1</button> 65 + <button data-volt-on-click="count.set(count.get() + 10)">+10</button> 66 + </div> 67 + 68 + <div class="stats"> 69 + <div class="stat"> 70 + <h6>Current Value</h6> 71 + <p data-volt-text="count">0</p> 72 + </div> 73 + <div class="stat"> 74 + <h6>Doubled</h6> 75 + <p data-volt-text="doubled">0</p> 76 + </div> 77 + <div class="stat"> 78 + <h6>Status</h6> 79 + <p data-volt-text="isNegative ? 'negative' : (isZero ? 'zero' : 'positive')">zero</p> 80 + </div> 81 + </div> 82 + </article> 83 + 84 + <script type="module"> 85 + import { charge } from './../dist/volt.min.js'; 86 + charge(); 87 + </script> 88 + </body> 89 + </html>
+144
examples/form-validation/index.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8"> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 + <title>Form Validation - Volt.js Example</title> 7 + <link rel="stylesheet" href="../dist/volt.min.css"> 8 + <style> 9 + .error { 10 + color: var(--color-error); 11 + font-size: var(--font-size-sm); 12 + margin-top: calc(-1 * var(--space-sm)); 13 + margin-bottom: var(--space-md); 14 + } 15 + 16 + .success { 17 + padding: var(--space-md); 18 + background: var(--color-bg-alt); 19 + border-left: 4px solid var(--color-success); 20 + border-radius: var(--radius-md); 21 + margin: var(--space-lg) 0; 22 + } 23 + 24 + .form-group { 25 + margin-bottom: var(--space-md); 26 + } 27 + 28 + input.invalid { 29 + border-color: var(--color-error); 30 + } 31 + 32 + input.valid { 33 + border-color: var(--color-success); 34 + } 35 + </style> 36 + </head> 37 + <body> 38 + <article 39 + data-volt 40 + data-volt-state='{"email": "", "password": "", "confirmPassword": "", "agreedToTerms": false, "submitted": false}' 41 + data-volt-computed:email-valid="email.length > 0 && email.includes('@') && email.includes('.')" 42 + data-volt-computed:password-valid="password.length >= 8" 43 + data-volt-computed:passwords-match="password === confirmPassword && confirmPassword.length > 0" 44 + data-volt-computed:form-valid="emailValid && passwordValid && passwordsMatch && agreedToTerms"> 45 + <h1>Sign Up</h1> 46 + <p> 47 + Create your account with real-time validation. All validation rules are defined in HTML using computed 48 + expressions. 49 + </p> 50 + 51 + <form data-volt-on-submit="submitted.set(true); $event.preventDefault()"> 52 + <div class="form-group"> 53 + <label for="email">Email Address</label> 54 + <input 55 + type="email" 56 + id="email" 57 + required 58 + data-volt-model="email" 59 + data-volt-class="{valid: email.length > 0 && emailValid, invalid: email.length > 0 && !emailValid}" 60 + placeholder="you@example.com"> 61 + <div class="error" data-volt-if="email.length > 0 && !emailValid"> 62 + Please enter a valid email address. 63 + </div> 64 + </div> 65 + 66 + <div class="form-group"> 67 + <label for="password">Password</label> 68 + <input 69 + type="password" 70 + id="password" 71 + required 72 + data-volt-model="password" 73 + data-volt-class="{valid: passwordValid, invalid: password.length > 0 && !passwordValid}" 74 + placeholder="At least 8 characters"> 75 + <div class="error" data-volt-if="password.length > 0 && !passwordValid"> 76 + Password must be at least 8 characters long. 77 + </div> 78 + </div> 79 + 80 + <div class="form-group"> 81 + <label for="confirmPassword">Confirm Password</label> 82 + <input 83 + type="password" 84 + id="confirmPassword" 85 + required 86 + data-volt-model="confirmPassword" 87 + data-volt-class="{valid: passwordsMatch, invalid: confirmPassword.length > 0 && !passwordsMatch}" 88 + placeholder="Re-enter your password"> 89 + <div class="error" data-volt-if="confirmPassword.length > 0 && !passwordsMatch"> 90 + Passwords do not match. 91 + </div> 92 + </div> 93 + 94 + <div class="form-group"> 95 + <label> 96 + <input type="checkbox" data-volt-model="agreedToTerms" required> 97 + I agree to the terms and conditions 98 + </label> 99 + </div> 100 + 101 + <button type="submit" data-volt-bind:disabled="!formValid"> 102 + Create Account 103 + </button> 104 + </form> 105 + 106 + <div class="success" data-volt-if="submitted && formValid"> 107 + <strong>Success!</strong> Your account has been created. 108 + <details> 109 + <summary>Form Data</summary> 110 + <dl> 111 + <dt>Email</dt> 112 + <dd data-volt-text="email"></dd> 113 + <dt>Password</dt> 114 + <dd>••••••••</dd> 115 + <dt>Terms Accepted</dt> 116 + <dd data-volt-text="agreedToTerms ? 'Yes' : 'No'"></dd> 117 + </dl> 118 + </details> 119 + </div> 120 + 121 + <details style="margin-top: var(--space-xs);"> 122 + <summary>View Current State</summary> 123 + <pre> 124 + <code>{ 125 + "email": "<span data-volt-text="email"></span>", 126 + "password": "<span data-volt-text="password"></span>", 127 + "confirmPassword": "<span data-volt-text="confirmPassword"></span>", 128 + "agreedToTerms": <span data-volt-text="agreedToTerms"></span>, 129 + "submitted": <span data-volt-text="submitted"></span>, 130 + "emailValid": <span data-volt-text="emailValid"></span>, 131 + "passwordValid": <span data-volt-text="passwordValid"></span>, 132 + "passwordsMatch": <span data-volt-text="passwordsMatch"></span>, 133 + "formValid": <span data-volt-text="formValid"></span> 134 + }</code> 135 + </pre> 136 + </details> 137 + </article> 138 + 139 + <script type="module"> 140 + import { charge } from "./../dist/volt.min.js"; 141 + charge(); 142 + </script> 143 + </body> 144 + </html>
+10 -13
lib/src/core/asyncEffect.ts
··· 9 9 * Creates an async side effect that runs when dependencies change. 10 10 * Supports abort signals, race protection, debouncing, throttling, and error handling. 11 11 * 12 - * @param effectFunction - Async function to run as a side effect 13 - * @param dependencies - Array of signals this effect depends on 14 - * @param options - Configuration options for async behavior 12 + * @param effectFn - Async function to run as a side effect 13 + * @param deps - Array of signals this effect depends on 14 + * @param opts - Configuration options for async behavior 15 15 * @returns Cleanup function to stop the effect 16 16 * 17 17 * @example ··· 46 46 * }); 47 47 */ 48 48 export function asyncEffect( 49 - effectFunction: AsyncEffectFunction, 50 - dependencies: Array<Signal<unknown> | ComputedSignal<unknown>>, 51 - options: AsyncEffectOptions = {}, 49 + effectFn: AsyncEffectFunction, 50 + deps: Array<Signal<unknown> | ComputedSignal<unknown>>, 51 + opts: AsyncEffectOptions = {}, 52 52 ): () => void { 53 - const { abortable = false, debounce, throttle, onError, retries = 0, retryDelay = 0 } = options; 53 + const { abortable = false, debounce, throttle, onError, retries = 0, retryDelay = 0 } = opts; 54 54 55 55 let cleanup: (() => void) | void; 56 56 let abortController: Optional<AbortController>; ··· 83 83 } 84 84 85 85 try { 86 - const result = await effectFunction(abortController?.signal); 86 + const result = await effectFn(abortController?.signal); 87 87 88 88 if (currentExecutionId !== executionId) { 89 89 return; ··· 128 128 } 129 129 }; 130 130 131 - /** 132 - * Schedule effect execution with debounce/throttle logic 133 - */ 134 131 const scheduleExecution = () => { 135 132 const currentExecutionId = ++executionId; 136 133 ··· 173 170 174 171 scheduleExecution(); 175 172 176 - const unsubscribers = dependencies.map((dependency) => 177 - dependency.subscribe(() => { 173 + const unsubscribers = deps.map((dep) => 174 + dep.subscribe(() => { 178 175 scheduleExecution(); 179 176 }) 180 177 );
+116 -181
lib/src/core/binder.ts
··· 4 4 5 5 import type { Optional } from "$types/helpers"; 6 6 import type { BindingContext, CleanupFunction, PluginContext, Scope, Signal } from "$types/volt"; 7 - import { getVoltAttributes, parseClassBinding, setHTML, setText, toggleClass, walkDOM } from "./dom"; 8 - import { evaluate, extractDependencies, isSignal } from "./evaluator"; 7 + import { getVoltAttrs, parseClassBinding, setHTML, setText, toggleClass, walkDOM } from "./dom"; 8 + import { evaluate, extractDeps } from "./evaluator"; 9 9 import { bindDelete, bindGet, bindPatch, bindPost, bindPut } from "./http"; 10 - import { executeGlobalHooks, notifyBindingCreated, notifyElementMounted, notifyElementUnmounted } from "./lifecycle"; 10 + import { execGlobalHooks, notifyBindingCreated, notifyElementMounted, notifyElementUnmounted } from "./lifecycle"; 11 11 import { getPlugin } from "./plugin"; 12 + import { findScopedSignal } from "./shared"; 12 13 13 14 /** 14 15 * Mount Volt.js on a root element and its descendants and binds all data-volt-* attributes to the provided scope. 15 - * Returns a cleanup function to unmount and dispose all bindings. 16 16 * 17 17 * @param root - Root element to mount on 18 18 * @param scope - Scope object containing signals and data 19 - * @returns Cleanup function to unmount 19 + * @returns Cleanup function to unmount and dispose all bindings. 20 20 */ 21 21 export function mount(root: Element, scope: Scope): CleanupFunction { 22 - executeGlobalHooks("beforeMount", root, scope); 22 + execGlobalHooks("beforeMount", root, scope); 23 23 24 24 const elements = walkDOM(root); 25 25 const allCleanups: CleanupFunction[] = []; 26 26 const mountedElements: Element[] = []; 27 27 28 28 for (const element of elements) { 29 - const attributes = getVoltAttributes(element); 29 + const attributes = getVoltAttrs(element); 30 30 const context: BindingContext = { element, scope, cleanups: [] }; 31 31 32 32 if (attributes.has("for")) { ··· 49 49 allCleanups.push(...context.cleanups); 50 50 } 51 51 52 - executeGlobalHooks("afterMount", root, scope); 52 + execGlobalHooks("afterMount", root, scope); 53 53 54 54 return () => { 55 - executeGlobalHooks("beforeUnmount", root); 55 + execGlobalHooks("beforeUnmount", root); 56 56 57 57 for (const element of mountedElements) { 58 58 notifyElementUnmounted(element); ··· 66 66 } 67 67 } 68 68 69 - executeGlobalHooks("afterUnmount", root); 69 + execGlobalHooks("afterUnmount", root); 70 70 }; 71 71 } 72 72 73 73 /** 74 74 * Bind a single data-volt-* attribute to an element. 75 75 * Routes to the appropriate binding handler. 76 - * 77 - * @param context - Binding context 78 - * @param name - Attribute name (without data-volt- prefix) 79 - * @param value - Attribute value (expression) 80 76 */ 81 - function bindAttribute(context: BindingContext, name: string, value: string): void { 77 + function bindAttribute(ctx: BindingContext, name: string, value: string): void { 82 78 if (name.startsWith("on-")) { 83 79 const eventName = name.slice(3); 84 - bindEvent(context, eventName, value); 80 + bindEvent(ctx, eventName, value); 85 81 return; 86 82 } 87 83 88 84 if (name.startsWith("bind:")) { 89 85 const attrName = name.slice(5); 90 - bindAttr(context, attrName, value); 86 + bindAttr(ctx, attrName, value); 91 87 return; 92 88 } 93 89 94 90 switch (name) { 95 91 case "text": { 96 - bindText(context, value); 92 + bindText(ctx, value); 97 93 break; 98 94 } 99 95 case "html": { 100 - bindHTML(context, value); 96 + bindHTML(ctx, value); 101 97 break; 102 98 } 103 99 case "class": { 104 - bindClass(context, value); 100 + bindClass(ctx, value); 105 101 break; 106 102 } 107 103 case "model": { 108 - bindModel(context, value); 104 + bindModel(ctx, value); 109 105 break; 110 106 } 111 107 case "for": { 112 - bindFor(context, value); 108 + bindFor(ctx, value); 113 109 break; 114 110 } 115 111 case "get": { 116 - bindGet(context, value); 112 + bindGet(ctx, value); 117 113 break; 118 114 } 119 115 case "post": { 120 - bindPost(context, value); 116 + bindPost(ctx, value); 121 117 break; 122 118 } 123 119 case "put": { 124 - bindPut(context, value); 120 + bindPut(ctx, value); 125 121 break; 126 122 } 127 123 case "patch": { 128 - bindPatch(context, value); 124 + bindPatch(ctx, value); 129 125 break; 130 126 } 131 127 case "delete": { 132 - bindDelete(context, value); 128 + bindDelete(ctx, value); 133 129 break; 134 130 } 135 131 default: { 136 132 const plugin = getPlugin(name); 137 133 if (plugin) { 138 - const pluginContext = createPluginContext(context); 134 + const pluginContext = createPluginCtx(ctx); 139 135 try { 140 136 plugin(pluginContext, value); 141 137 } catch (error) { ··· 151 147 /** 152 148 * Bind data-volt-text to update element's text content. 153 149 * Subscribes to signals in the expression and updates on change. 154 - * 155 - * @param context - Binding context 156 - * @param expression - Expression to evaluate 157 150 */ 158 - function bindText(context: BindingContext, expression: string): void { 151 + function bindText(ctx: BindingContext, expr: string): void { 159 152 const update = () => { 160 - const value = evaluate(expression, context.scope); 161 - setText(context.element, value); 153 + const value = evaluate(expr, ctx.scope); 154 + setText(ctx.element, value); 162 155 }; 163 156 164 157 update(); 165 158 166 - const signal = findSignalInScope(context.scope, expression); 167 - if (signal) { 168 - const unsubscribe = signal.subscribe(update); 169 - context.cleanups.push(unsubscribe); 159 + const deps = extractDeps(expr, ctx.scope); 160 + for (const dep of deps) { 161 + const unsubscribe = dep.subscribe(update); 162 + ctx.cleanups.push(unsubscribe); 170 163 } 171 164 } 172 165 173 166 /** 174 167 * Bind data-volt-html to update element's HTML content. 175 - * 176 168 * Subscribes to signals in the expression and updates on change. 177 169 */ 178 - function bindHTML(context: BindingContext, expression: string): void { 170 + function bindHTML(ctx: BindingContext, expr: string): void { 179 171 const update = () => { 180 - const value = evaluate(expression, context.scope); 181 - setHTML(context.element, String(value ?? "")); 172 + const value = evaluate(expr, ctx.scope); 173 + setHTML(ctx.element, String(value ?? "")); 182 174 }; 183 175 184 176 update(); 185 177 186 - const signal = findSignalInScope(context.scope, expression); 187 - if (signal) { 188 - const unsubscribe = signal.subscribe(update); 189 - context.cleanups.push(unsubscribe); 178 + const dependencies = extractDeps(expr, ctx.scope); 179 + for (const dependency of dependencies) { 180 + const unsubscribe = dependency.subscribe(update); 181 + ctx.cleanups.push(unsubscribe); 190 182 } 191 183 } 192 184 193 185 /** 194 - * Bind data-volt-class to toggle CSS classes. 195 - * Supports both string and object notation. 186 + * Bind data-volt-class to toggle CSS classes. Supports both string and object notation. 196 187 * Subscribes to signals in the expression and updates on change. 197 - * 198 - * @param context - Binding context 199 - * @param expression - Expression to evaluate 200 188 */ 201 - function bindClass(context: BindingContext, expression: string): void { 202 - let previousClasses = new Map<string, boolean>(); 189 + function bindClass(ctx: BindingContext, expr: string): void { 190 + let prevClasses = new Map<string, boolean>(); 203 191 204 192 const update = () => { 205 - const value = evaluate(expression, context.scope); 193 + const value = evaluate(expr, ctx.scope); 206 194 const classes = parseClassBinding(value); 207 195 208 - for (const [className] of previousClasses) { 196 + for (const [className] of prevClasses) { 209 197 if (!classes.has(className)) { 210 - toggleClass(context.element, className, false); 198 + toggleClass(ctx.element, className, false); 211 199 } 212 200 } 213 201 214 202 for (const [className, shouldAdd] of classes) { 215 - toggleClass(context.element, className, shouldAdd); 203 + toggleClass(ctx.element, className, shouldAdd); 216 204 } 217 205 218 - previousClasses = classes; 206 + prevClasses = classes; 219 207 }; 220 208 221 209 update(); 222 210 223 - const signal = findSignalInScope(context.scope, expression); 224 - if (signal) { 225 - const unsubscribe = signal.subscribe(update); 226 - context.cleanups.push(unsubscribe); 211 + const deps = extractDeps(expr, ctx.scope); 212 + for (const dep of deps) { 213 + const unsubscribe = dep.subscribe(update); 214 + ctx.cleanups.push(unsubscribe); 227 215 } 228 216 } 229 217 230 218 /** 231 219 * Bind data-volt-on-* to attach event listeners. 232 220 * Provides $el and $event in the scope for the event handler. 233 - * 234 - * @param context - Binding context 235 - * @param eventName - Event name (e.g., "click", "input") 236 - * @param expression - Expression to evaluate when event fires 237 221 */ 238 - function bindEvent(context: BindingContext, eventName: string, expression: string): void { 222 + function bindEvent(ctx: BindingContext, eventName: string, expr: string): void { 239 223 const handler = (event: Event) => { 240 - const eventScope: Scope = { ...context.scope, $el: context.element, $event: event }; 224 + const eventScope: Scope = { ...ctx.scope, $el: ctx.element, $event: event }; 241 225 242 226 try { 243 - const result = evaluate(expression, eventScope); 227 + const result = evaluate(expr, eventScope); 244 228 if (typeof result === "function") { 245 229 result(event); 246 230 } ··· 249 233 } 250 234 }; 251 235 252 - context.element.addEventListener(eventName, handler); 236 + ctx.element.addEventListener(eventName, handler); 253 237 254 - context.cleanups.push(() => { 255 - context.element.removeEventListener(eventName, handler); 238 + ctx.cleanups.push(() => { 239 + ctx.element.removeEventListener(eventName, handler); 256 240 }); 257 241 } 258 242 259 243 /** 260 244 * Bind data-volt-model for two-way data binding on form elements. 261 245 * Syncs the signal value with the input value bidirectionally. 262 - * 263 - * @param context - Binding context 264 - * @param signalPath - Path to the signal in scope 265 246 */ 266 247 function bindModel(context: BindingContext, signalPath: string): void { 267 - const signal = findSignalInScope(context.scope, signalPath); 248 + const signal = findScopedSignal(context.scope, signalPath); 268 249 if (!signal) { 269 250 console.error(`Signal "${signalPath}" not found for data-volt-model`); 270 251 return; ··· 294 275 }); 295 276 } 296 277 297 - /** 298 - * Set element value based on type 299 - */ 300 278 function setElementValue( 301 - element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, 279 + el: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, 302 280 value: unknown, 303 281 type: string | null, 304 282 ): void { 305 - if (element instanceof HTMLInputElement) { 283 + if (el instanceof HTMLInputElement) { 306 284 switch (type) { 307 285 case "checkbox": { 308 - element.checked = Boolean(value); 286 + el.checked = Boolean(value); 309 287 310 288 break; 311 289 } 312 290 case "radio": { 313 - element.checked = element.value === String(value); 291 + el.checked = el.value === String(value); 314 292 break; 315 293 } 316 294 case "number": { 317 - element.value = String(value ?? ""); 295 + el.value = String(value ?? ""); 318 296 break; 319 297 } 320 298 default: { 321 - element.value = String(value ?? ""); 299 + el.value = String(value ?? ""); 322 300 } 323 301 } 324 - } else if (element instanceof HTMLSelectElement) { 325 - element.value = String(value ?? ""); 326 - } else if (element instanceof HTMLTextAreaElement) { 327 - element.value = String(value ?? ""); 302 + } else if (el instanceof HTMLSelectElement) { 303 + el.value = String(value ?? ""); 304 + } else if (el instanceof HTMLTextAreaElement) { 305 + el.value = String(value ?? ""); 328 306 } 329 307 } 330 308 331 - /** 332 - * Get element value based on type 333 - */ 334 - function getElementValue( 335 - element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, 336 - type: string | null, 337 - ): unknown { 338 - if (element instanceof HTMLInputElement) { 309 + function getElementValue(el: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement, type: string | null): unknown { 310 + if (el instanceof HTMLInputElement) { 339 311 if (type === "checkbox") { 340 - return element.checked; 312 + return el.checked; 341 313 } 342 314 if (type === "number") { 343 - return element.valueAsNumber; 315 + return el.valueAsNumber; 344 316 } 345 - return element.value; 317 + return el.value; 346 318 } 347 319 348 - if (element instanceof HTMLSelectElement) { 349 - return element.value; 320 + if (el instanceof HTMLSelectElement) { 321 + return el.value; 350 322 } 351 323 352 - if (element instanceof HTMLTextAreaElement) { 353 - return element.value; 324 + if (el instanceof HTMLTextAreaElement) { 325 + return el.value; 354 326 } 355 327 356 328 return ""; ··· 358 330 359 331 /** 360 332 * Bind data-volt-bind:attr for generic attribute binding. 361 - * 362 333 * Updates any HTML attribute reactively based on expression value. 363 334 */ 364 - function bindAttr(context: BindingContext, attrName: string, expression: string): void { 335 + function bindAttr(ctx: BindingContext, attrName: string, expr: string): void { 365 336 const update = () => { 366 - const value = evaluate(expression, context.scope); 337 + const value = evaluate(expr, ctx.scope); 367 338 368 339 const booleanAttrs = new Set([ 369 340 "disabled", ··· 381 352 382 353 if (booleanAttrs.has(attrName)) { 383 354 if (value) { 384 - context.element.setAttribute(attrName, ""); 355 + ctx.element.setAttribute(attrName, ""); 385 356 } else { 386 - context.element.removeAttribute(attrName); 357 + ctx.element.removeAttribute(attrName); 387 358 } 388 359 } else { 389 360 if (value === null || value === undefined || value === false) { 390 - context.element.removeAttribute(attrName); 361 + ctx.element.removeAttribute(attrName); 391 362 } else { 392 - context.element.setAttribute(attrName, String(value)); 363 + ctx.element.setAttribute(attrName, String(value)); 393 364 } 394 365 } 395 366 }; 396 367 397 368 update(); 398 369 399 - const dependencies = extractDependencies(expression, context.scope); 400 - for (const dependency of dependencies) { 401 - const unsubscribe = dependency.subscribe(update); 402 - context.cleanups.push(unsubscribe); 403 - } 404 - } 405 - 406 - /** 407 - * Find a signal in the scope by resolving a simple property path. 408 - */ 409 - function findSignalInScope(scope: Scope, path: string): Optional<Signal<unknown>> { 410 - const trimmed = path.trim(); 411 - const parts = trimmed.split("."); 412 - let current: unknown = scope; 413 - 414 - for (const part of parts) { 415 - if (current === null || current === undefined) { 416 - return undefined; 417 - } 418 - 419 - if (typeof current === "object" && part in (current as Record<string, unknown>)) { 420 - current = (current as Record<string, unknown>)[part]; 421 - } else { 422 - return undefined; 423 - } 424 - } 425 - 426 - if (isSignal(current)) { 427 - return current as Signal<unknown>; 370 + const deps = extractDeps(expr, ctx.scope); 371 + for (const dep of deps) { 372 + const unsubscribe = dep.subscribe(update); 373 + ctx.cleanups.push(unsubscribe); 428 374 } 429 - 430 - return undefined; 431 375 } 432 376 433 377 /** 434 378 * Bind data-volt-for to render a list of items. 435 379 * Subscribes to array signal and re-renders when array changes. 436 - * 437 - * @param context - Binding context 438 - * @param expression - Expression like "item in items" or "(item, index) in items" 439 380 */ 440 - function bindFor(context: BindingContext, expression: string): void { 441 - const parsed = parseForExpression(expression); 381 + function bindFor(ctx: BindingContext, expr: string): void { 382 + const parsed = parseForExpr(expr); 442 383 if (!parsed) { 443 - console.error(`Invalid data-volt-for expression: "${expression}"`); 384 + console.error(`Invalid data-volt-for expression: "${expr}"`); 444 385 return; 445 386 } 446 387 447 388 const { itemName, indexName, arrayPath } = parsed; 448 - const template = context.element as HTMLElement; 389 + const template = ctx.element as HTMLElement; 449 390 const parent = template.parentElement; 450 391 451 392 if (!parent) { ··· 453 394 return; 454 395 } 455 396 456 - const placeholder = document.createComment(`for: ${expression}`); 397 + const placeholder = document.createComment(`for: ${expr}`); 457 398 template.before(placeholder); 458 399 template.remove(); 459 400 ··· 471 412 } 472 413 renderedElements.length = 0; 473 414 474 - const arrayValue = evaluate(arrayPath, context.scope); 415 + const arrayValue = evaluate(arrayPath, ctx.scope); 475 416 if (!Array.isArray(arrayValue)) { 476 417 return; 477 418 } ··· 480 421 const clone = template.cloneNode(true) as Element; 481 422 delete (clone as HTMLElement).dataset.voltFor; 482 423 483 - const itemScope: Scope = { ...context.scope, [itemName]: item }; 424 + const itemScope: Scope = { ...ctx.scope, [itemName]: item }; 484 425 if (indexName) { 485 426 itemScope[indexName] = index; 486 427 } ··· 495 436 496 437 render(); 497 438 498 - const signal = findSignalInScope(context.scope, arrayPath); 499 - if (signal) { 500 - const unsubscribe = signal.subscribe(render); 501 - context.cleanups.push(unsubscribe); 439 + const deps = extractDeps(arrayPath, ctx.scope); 440 + for (const dep of deps) { 441 + const unsubscribe = dep.subscribe(render); 442 + ctx.cleanups.push(unsubscribe); 502 443 } 503 444 504 - context.cleanups.push(() => { 445 + ctx.cleanups.push(() => { 505 446 for (const cleanup of renderedCleanups) { 506 447 cleanup(); 507 448 } ··· 509 450 } 510 451 511 452 /** 512 - * Bind data-volt-if to conditionally render an element. 513 - * Supports data-volt-else on the next sibling element. 453 + * Bind data-volt-if to conditionally render an element. Supports data-volt-else on the next sibling element. 514 454 * Subscribes to condition signal and shows/hides elements when condition changes. 515 - * 516 - * @param ctx - Binding context 517 - * @param expr - Expression to evaluate as condition 518 455 */ 519 456 function bindIf(ctx: BindingContext, expr: string): void { 520 457 const ifTemplate = ctx.element as HTMLElement; ··· 583 520 584 521 render(); 585 522 586 - const signal = findSignalInScope(ctx.scope, expr); 587 - if (signal) { 588 - const unsubscribe = signal.subscribe(render); 523 + const deps = extractDeps(expr, ctx.scope); 524 + for (const dep of deps) { 525 + const unsubscribe = dep.subscribe(render); 589 526 ctx.cleanups.push(unsubscribe); 590 527 } 591 528 ··· 598 535 599 536 /** 600 537 * Parse a data-volt-for expression 601 - * 602 538 * Supports: "item in items" or "(item, index) in items" 603 539 */ 604 - function parseForExpression(expr: string): Optional<{ itemName: string; indexName?: string; arrayPath: string }> { 540 + function parseForExpr(expr: string): Optional<{ itemName: string; indexName?: string; arrayPath: string }> { 605 541 const trimmed = expr.trim(); 606 542 607 543 const withIndex = /^\((\w+)\s*,\s*(\w+)\)\s+in\s+(.+)$/.exec(trimmed); ··· 619 555 620 556 /** 621 557 * Create a plugin context from a binding context. 622 - * 623 558 * Provides the plugin with access to utilities and cleanup registration. 624 559 */ 625 - function createPluginContext(bindingContext: BindingContext): PluginContext { 560 + function createPluginCtx(ctx: BindingContext): PluginContext { 626 561 const mountCallbacks: Array<() => void> = []; 627 562 const unmountCallbacks: Array<() => void> = []; 628 563 const beforeBindingCallbacks: Array<() => void> = []; 629 564 const afterBindingCallbacks: Array<() => void> = []; 630 565 631 566 const lifecycle = { 632 - onMount: (callback: () => void) => { 633 - mountCallbacks.push(callback); 567 + onMount: (cb: () => void) => { 568 + mountCallbacks.push(cb); 634 569 try { 635 - callback(); 570 + cb(); 636 571 } catch (error) { 637 572 console.error("Error in plugin onMount hook:", error); 638 573 } ··· 648 583 console.error("Error in plugin beforeBinding hook:", error); 649 584 } 650 585 }, 651 - afterBinding: (callback: () => void) => { 652 - afterBindingCallbacks.push(callback); 586 + afterBinding: (cb: () => void) => { 587 + afterBindingCallbacks.push(cb); 653 588 queueMicrotask(() => { 654 589 try { 655 - callback(); 590 + cb(); 656 591 } catch (error) { 657 592 console.error("Error in plugin afterBinding hook:", error); 658 593 } ··· 660 595 }, 661 596 }; 662 597 663 - bindingContext.cleanups.push(() => { 598 + ctx.cleanups.push(() => { 664 599 for (const cb of unmountCallbacks) { 665 600 try { 666 601 cb(); ··· 671 606 }); 672 607 673 608 return { 674 - element: bindingContext.element, 675 - scope: bindingContext.scope, 609 + element: ctx.element, 610 + scope: ctx.scope, 676 611 addCleanup: (fn) => { 677 - bindingContext.cleanups.push(fn); 612 + ctx.cleanups.push(fn); 678 613 }, 679 - findSignal: (path) => findSignalInScope(bindingContext.scope, path), 680 - evaluate: (expr) => evaluate(expr, bindingContext.scope), 614 + findSignal: (path) => findScopedSignal(ctx.scope, path), 615 + evaluate: (expr) => evaluate(expr, ctx.scope), 681 616 lifecycle, 682 617 }; 683 618 }
+8 -33
lib/src/core/charge.ts
··· 6 6 7 7 import type { ChargedRoot, ChargeResult, Scope } from "$types/volt"; 8 8 import { mount } from "./binder"; 9 - import { evaluate, extractDependencies } from "./evaluator"; 9 + import { evaluate, extractDeps } from "./evaluator"; 10 + import { getComputedAttributes } from "./shared"; 10 11 import { computed, signal } from "./signal"; 11 12 12 13 /** ··· 60 61 61 62 /** 62 63 * Create a reactive scope from element's data-volt-state and data-volt-computed attributes 63 - * 64 - * @param element - The root element 65 - * @returns Reactive scope object with signals 66 64 */ 67 - function createScopeFromElement(element: Element): Scope { 65 + function createScopeFromElement(el: Element): Scope { 68 66 const scope: Scope = {}; 69 67 70 - const stateAttr = (element as HTMLElement).dataset.voltState; 68 + const stateAttr = (el as HTMLElement).dataset.voltState; 71 69 if (stateAttr) { 72 70 try { 73 71 const stateData = JSON.parse(stateAttr); 74 72 75 73 if (typeof stateData !== "object" || stateData === null || Array.isArray(stateData)) { 76 - console.error(`data-volt-state must be a JSON object, got ${typeof stateData}:`, element); 74 + console.error(`data-volt-state must be a JSON object, got ${typeof stateData}:`, el); 77 75 } else { 78 76 for (const [key, value] of Object.entries(stateData)) { 79 77 scope[key] = signal(value); ··· 81 79 } 82 80 } catch (error) { 83 81 console.error("Failed to parse data-volt-state JSON:", stateAttr, error); 84 - console.error("Element:", element); 82 + console.error("Element:", el); 85 83 } 86 84 } 87 85 88 - const computedAttrs = getComputedAttributes(element); 86 + const computedAttrs = getComputedAttributes(el); 89 87 for (const [name, expression] of computedAttrs) { 90 88 try { 91 - const dependencies = extractDependencies(expression, scope); 89 + const dependencies = extractDeps(expression, scope); 92 90 93 91 scope[name] = computed(() => evaluate(expression, scope), dependencies); 94 92 } catch (error) { ··· 98 96 99 97 return scope; 100 98 } 101 - 102 - /** 103 - * Get all data-volt-computed:name attributes from an element. 104 - * 105 - * Converts kebab-case names to camelCase to match JS conventions. 106 - */ 107 - function getComputedAttributes(element: Element): Map<string, string> { 108 - const computed = new Map<string, string>(); 109 - 110 - for (const attr of element.attributes) { 111 - if (attr.name.startsWith("data-volt-computed:")) { 112 - const name = attr.name.slice("data-volt-computed:".length); 113 - const camelName = kebabToCamel(name); 114 - computed.set(camelName, attr.value); 115 - } 116 - } 117 - 118 - return computed; 119 - } 120 - 121 - function kebabToCamel(str: string): string { 122 - return str.replaceAll(/-([a-z])/g, (_, letter) => letter.toUpperCase()); 123 - }
+17 -17
lib/src/core/dom.ts
··· 14 14 const elements: Element[] = []; 15 15 16 16 function walk(element: Element): void { 17 - if (hasVoltAttribute(element)) { 17 + if (hasVoltAttr(element)) { 18 18 elements.push(element); 19 19 20 20 if ( ··· 38 38 /** 39 39 * Check if an element has any data-volt-* attributes. 40 40 * 41 - * @param element - Element to check 41 + * @param el - Element to check 42 42 * @returns true if element has any Volt attributes 43 43 */ 44 - export function hasVoltAttribute(element: Element): boolean { 45 - return [...element.attributes].some((attribute) => attribute.name.startsWith("data-volt-")); 44 + export function hasVoltAttr(el: Element): boolean { 45 + return [...el.attributes].some((attribute) => attribute.name.startsWith("data-volt-")); 46 46 } 47 47 48 48 /** 49 49 * Get all data-volt-* attributes from an element. 50 50 * Excludes charge metadata attributes (state, computed:*) that are processed separately. 51 51 * 52 - * @param element - Element to get attributes from 52 + * @param el - Element to get attributes from 53 53 * @returns Map of attribute names to values (without the data-volt- prefix) 54 54 */ 55 - export function getVoltAttributes(element: Element): Map<string, string> { 55 + export function getVoltAttrs(el: Element): Map<string, string> { 56 56 const attributes = new Map<string, string>(); 57 57 58 - for (const attribute of element.attributes) { 58 + for (const attribute of el.attributes) { 59 59 if (attribute.name.startsWith("data-volt-")) { 60 60 const name = attribute.name.slice(10); 61 61 ··· 74 74 /** 75 75 * Set the text content of an element safely. 76 76 * 77 - * @param element - Element to update 77 + * @param el - Element to update 78 78 * @param value - Text value to set 79 79 */ 80 - export function setText(element: Element, value: unknown): void { 81 - element.textContent = String(value ?? ""); 80 + export function setText(el: Element, value: unknown): void { 81 + el.textContent = String(value ?? ""); 82 82 } 83 83 84 84 /** 85 85 * Set the HTML content of an element safely. 86 86 * Note: This trusts the input HTML and should only be used with sanitized content. 87 87 * 88 - * @param element - Element to update 88 + * @param el - Element to update 89 89 * @param value - HTML string to set 90 90 */ 91 - export function setHTML(element: Element, value: string): void { 92 - element.innerHTML = value; 91 + export function setHTML(el: Element, value: string): void { 92 + el.innerHTML = value; 93 93 } 94 94 95 95 /** 96 96 * Add or remove a CSS class from an element. 97 97 * 98 - * @param element - Element to update 99 - * @param className - Class name to toggle 98 + * @param el - Element to update 99 + * @param cls - Class name to toggle 100 100 * @param add - Whether to add (true) or remove (false) the class 101 101 */ 102 - export function toggleClass(element: Element, className: string, add: boolean): void { 103 - element.classList.toggle(className, add); 102 + export function toggleClass(el: Element, cls: string, add: boolean): void { 103 + el.classList.toggle(cls, add); 104 104 } 105 105 106 106 /**
+30 -33
lib/src/core/evaluator.ts
··· 6 6 */ 7 7 8 8 import type { Dep, Scope } from "$types/volt"; 9 + import { findScopedSignal, isSignal } from "./shared"; 9 10 10 - /** 11 - * Blocked properties to prevent prototype pollution and sandbox escape 12 - */ 13 11 const DANGEROUS_PROPERTIES = new Set(["__proto__", "prototype", "constructor"]); 14 12 15 13 const SAFE_GLOBALS = new Set([ ··· 40 38 "exports", 41 39 ]); 42 40 43 - /** 44 - * Validates that a property name is safe to access 45 - */ 46 41 function isSafeProp(key: unknown): boolean { 47 42 if (typeof key !== "string" && typeof key !== "number") { 48 43 return true; ··· 52 47 return !DANGEROUS_PROPERTIES.has(keyStr); 53 48 } 54 49 55 - /** 56 - * Validates that accessing a property on an object is safe 57 - */ 58 50 function isSafeAccess(object: unknown, key: unknown): boolean { 59 51 if (!isSafeProp(key)) { 60 52 return false; ··· 503 495 this.advance(); 504 496 const args = this.parseArgumentList(); 505 497 this.consume("RPAREN", "Expected ')' after arguments"); 506 - object = this.callMethod(object, prop.value as string, args); 498 + const propName = prop.value as string; 499 + const isSignalMethod = isSignal(object) 500 + && (propName === "get" || propName === "set" || propName === "subscribe"); 501 + const unwrappedObject = !isSignalMethod && isSignal(object) ? object.get() : object; 502 + object = this.callMethod(unwrappedObject, propName, args); 507 503 } else { 508 504 object = propValue; 509 505 } ··· 877 873 } 878 874 } 879 875 880 - export function isSignal(value: unknown): value is Dep { 881 - return (typeof value === "object" 882 - && value !== null 883 - && "get" in value 884 - && "subscribe" in value 885 - && typeof value.get === "function" 886 - && typeof (value as { subscribe: unknown }).subscribe === "function"); 887 - } 888 - 889 876 /** 890 877 * Evaluate an expression against a scope object. 891 878 * ··· 907 894 } 908 895 909 896 /** 910 - * Extract all signal dependencies from an expression by finding identifiers 911 - * that correspond to signals in the scope. 897 + * Extract all signal dependencies from an expression by finding identifiers that correspond to signals in the scope. 898 + * 899 + * This function handles both simple property paths (e.g., "todo.title") and complex expressions (e.g., "email.length > 0 && emailValid"). 912 900 * 913 901 * @param expr - The expression to analyze 914 902 * @param scope - The scope containing potential signal dependencies 915 903 * @returns Array of signals found in the expression 916 904 */ 917 - export function extractDependencies(expr: string, scope: Scope): Array<Dep> { 918 - const dependencies: Array<Dep> = []; 919 - const identifierRegex = /\b([a-zA-Z_$][\w$]*)\b/g; 920 - const matches = expr.matchAll(identifierRegex); 905 + export function extractDeps(expr: string, scope: Scope): Array<Dep> { 906 + const deps: Array<Dep> = []; 921 907 const seen = new Set<string>(); 922 908 909 + const identifierRegex = /\b([a-zA-Z_$][\w$]*(?:\.[a-zA-Z_$][\w$]*)*)\b/g; 910 + const matches = expr.matchAll(identifierRegex); 911 + 923 912 for (const match of matches) { 924 - const identifier = match[1]; 913 + const path = match[1]; 925 914 926 - if (["true", "false", "null", "undefined"].includes(identifier)) { 915 + if (["true", "false", "null", "undefined"].includes(path)) { 927 916 continue; 928 917 } 929 918 930 - if (seen.has(identifier)) { 919 + if (seen.has(path)) { 931 920 continue; 932 921 } 933 922 934 - seen.add(identifier); 923 + seen.add(path); 924 + 925 + const signal = findScopedSignal(scope, path); 926 + if (signal) { 927 + deps.push(signal); 928 + continue; 929 + } 935 930 936 - const value = scope[identifier]; 937 - if (isSignal(value)) { 938 - dependencies.push(value); 931 + const parts = path.split("."); 932 + const topLevel = parts[0]; 933 + const value = scope[topLevel]; 934 + if (isSignal(value) && !deps.includes(value)) { 935 + deps.push(value); 939 936 } 940 937 } 941 938 942 - return dependencies; 939 + return deps; 943 940 }
+55 -123
lib/src/core/http.ts
··· 17 17 SwapStrategy, 18 18 } from "$types/volt"; 19 19 import { evaluate } from "./evaluator"; 20 + import { sleep } from "./shared"; 20 21 21 22 /** 22 23 * Make an HTTP request and return the parsed response ··· 61 62 } 62 63 } 63 64 64 - /** 65 - * Capture state that should be preserved during DOM swap 66 - * 67 - * @param root - Root element to capture state from 68 - * @returns Captured state object 69 - */ 70 65 type CapturedState = { 71 66 focusPath: number[] | null; 72 67 scrollPositions: Map<number[], { top: number; left: number }>; 73 68 inputValues: Map<number[], string | boolean>; 74 69 }; 75 70 71 + /** 72 + * Capture state that should be preserved during DOM swap 73 + */ 76 74 function captureState(root: Element): CapturedState { 77 75 const state: CapturedState = { focusPath: null, scrollPositions: new Map(), inputValues: new Map() }; 78 76 ··· 109 107 } 110 108 111 109 /** 112 - * Get the path to an element from a root element 113 - * 114 - * Returns an array of child indices representing the path from root to element. 115 - * 116 - * @param element - Target element 117 - * @param root - Root element 118 - * @returns Array of indices, or empty array if element not found 110 + * Get the path to an element from a root element as an array of child indices representing the path from root to element. 119 111 */ 120 - function getElementPath(element: Element, root: Element): number[] { 112 + function getElementPath(el: Element, root: Element): number[] { 121 113 const path: number[] = []; 122 - let current: Element | null = element; 114 + let current: Element | null = el; 123 115 124 116 while (current && current !== root) { 125 117 const parent: Element | null = current.parentElement; ··· 137 129 138 130 /** 139 131 * Get element by path from root 140 - * 141 - * @param path - Array of child indices 142 - * @param root - Root element 143 - * @returns Element at path, or null if not found 144 132 */ 145 133 function getElementByPath(path: number[], root: Element): Element | null { 146 134 let current: Element = root; ··· 156 144 157 145 /** 158 146 * Restore preserved state after DOM swap 159 - * 160 - * @param root - Root element to restore state to 161 - * @param state - Previously captured state 162 147 */ 163 148 function restoreState(root: Element, state: CapturedState): void { 164 149 if (state.focusPath) { ··· 345 330 346 331 /** 347 332 * Get the default trigger event for an element 348 - * 349 - * - Forms: submit 350 - * - Buttons/links: click 351 - * - Everything else: click 352 - * 353 - * @param element - Element to get default trigger for 354 - * @returns Default event name 355 333 */ 356 - function getDefaultTrigger(element: Element): string { 357 - if (element instanceof HTMLFormElement) { 334 + function getDefaultTrigger(el: Element): string { 335 + if (el instanceof HTMLFormElement) { 358 336 return "submit"; 359 337 } 360 338 return "click"; ··· 366 344 * Sets data-volt-loading="true" attribute to indicate ongoing request. 367 345 * Shows indicator if data-volt-indicator is set. 368 346 * 369 - * @param element - Element to mark as loading 347 + * @param el - Element to mark as loading 370 348 * @param indicator - Optional indicator selector 371 349 */ 372 - export function setLoadingState(element: Element, indicator?: string): void { 373 - element.setAttribute("data-volt-loading", "true"); 350 + export function setLoadingState(el: Element, indicator?: string): void { 351 + el.setAttribute("data-volt-loading", "true"); 374 352 375 353 if (indicator) { 376 354 showIndicator(indicator); 377 355 } 378 356 379 - element.dispatchEvent(new CustomEvent("volt:loading", { detail: { element }, bubbles: true, cancelable: false })); 357 + el.dispatchEvent(new CustomEvent("volt:loading", { detail: { element: el }, bubbles: true, cancelable: false })); 380 358 } 381 359 382 360 /** ··· 385 363 * Sets data-volt-error attribute with error message. 386 364 * Hides indicator if data-volt-indicator is set. 387 365 * 388 - * @param element - Element to mark as errored 389 - * @param message - Error message 366 + * @param el - Element to mark as errored 367 + * @param msg - Error message 390 368 * @param indicator - Optional indicator selector 391 369 */ 392 - export function setErrorState(element: Element, message: string, indicator?: string): void { 393 - element.setAttribute("data-volt-error", message); 370 + export function setErrorState(el: Element, msg: string, indicator?: string): void { 371 + el.setAttribute("data-volt-error", msg); 394 372 395 373 if (indicator) { 396 374 hideIndicator(indicator); 397 375 } 398 376 399 - element.dispatchEvent( 400 - new CustomEvent("volt:error", { detail: { element, message }, bubbles: true, cancelable: false }), 377 + el.dispatchEvent( 378 + new CustomEvent("volt:error", { detail: { element: el, message: msg }, bubbles: true, cancelable: false }), 401 379 ); 402 380 } 403 381 ··· 407 385 * Removes data-volt-loading, data-volt-error, and data-volt-retry-attempt attributes. 408 386 * Hides indicator if data-volt-indicator is set. 409 387 * 410 - * @param element - Element to clear states from 388 + * @param el - Element to clear states from 411 389 * @param indicator - Optional indicator selector 412 390 */ 413 - export function clearStates(element: Element, indicator?: string): void { 414 - element.removeAttribute("data-volt-loading"); 415 - element.removeAttribute("data-volt-error"); 416 - element.removeAttribute("data-volt-retry-attempt"); 391 + export function clearStates(el: Element, indicator?: string): void { 392 + el.removeAttribute("data-volt-loading"); 393 + el.removeAttribute("data-volt-error"); 394 + el.removeAttribute("data-volt-retry-attempt"); 417 395 418 396 if (indicator) { 419 397 hideIndicator(indicator); 420 398 } 421 399 422 - element.dispatchEvent(new CustomEvent("volt:success", { detail: { element }, bubbles: true, cancelable: false })); 400 + el.dispatchEvent(new CustomEvent("volt:success", { detail: { element: el }, bubbles: true, cancelable: false })); 423 401 } 424 402 425 - /** 426 - * Visibility strategy for showing/hiding indicator elements 427 - */ 428 403 type IndicatorStrategy = "display" | "class"; 429 404 430 - /** 431 - * Cache for storing indicator visibility strategies 432 - */ 433 405 const indicatorStrategies = new WeakMap<Element, IndicatorStrategy>(); 434 406 435 407 /** ··· 438 410 * - If element has display: none (inline or computed), use display toggling 439 411 * - If element has a class containing "hidden", use class toggling 440 412 * - Otherwise, default to class toggling 441 - * 442 - * @param element - Indicator element 443 - * @returns Visibility strategy to use 444 413 */ 445 - function detectIndicatorStrategy(element: Element): IndicatorStrategy { 446 - if (indicatorStrategies.has(element)) { 447 - return indicatorStrategies.get(element)!; 414 + function detectIndicatorStrategy(el: Element): IndicatorStrategy { 415 + if (indicatorStrategies.has(el)) { 416 + return indicatorStrategies.get(el)!; 448 417 } 449 418 450 - const htmlElement = element as HTMLElement; 419 + const htmlElement = el as HTMLElement; 451 420 const inlineDisplay = htmlElement.style.display; 452 421 const computedDisplay = window.getComputedStyle(htmlElement).display; 453 422 454 423 if (inlineDisplay === "none" || computedDisplay === "none") { 455 - indicatorStrategies.set(element, "display"); 424 + indicatorStrategies.set(el, "display"); 456 425 return "display"; 457 426 } 458 427 459 - const hasHiddenClass = Array.from(element.classList).some((cls) => cls.toLowerCase().includes("hidden")); 428 + const hasHiddenClass = Array.from(el.classList).some((cls) => cls.toLowerCase().includes("hidden")); 460 429 if (hasHiddenClass) { 461 - indicatorStrategies.set(element, "class"); 430 + indicatorStrategies.set(el, "class"); 462 431 return "class"; 463 432 } 464 433 465 - indicatorStrategies.set(element, "class"); 434 + indicatorStrategies.set(el, "class"); 466 435 return "class"; 467 436 } 468 437 469 438 /** 470 439 * Show an indicator element using the appropriate visibility strategy 471 - * 472 - * @param element - Indicator element to show 473 440 */ 474 - function showIndicatorElement(element: Element): void { 475 - const strategy = detectIndicatorStrategy(element); 476 - const htmlElement = element as HTMLElement; 441 + function showIndicatorElement(el: Element): void { 442 + const strategy = detectIndicatorStrategy(el); 443 + const htmlElement = el as HTMLElement; 477 444 478 445 if (strategy === "display") { 479 446 htmlElement.style.display = ""; 480 447 } else { 481 - const hiddenClass = Array.from(element.classList).find((cls) => cls.toLowerCase().includes("hidden")) || "hidden"; 482 - element.classList.remove(hiddenClass); 448 + const hiddenClass = Array.from(el.classList).find((cls) => cls.toLowerCase().includes("hidden")) || "hidden"; 449 + el.classList.remove(hiddenClass); 483 450 } 484 451 } 485 452 486 453 /** 487 454 * Hide an indicator element using the appropriate visibility strategy 488 - * 489 - * @param element - Indicator element to hide 490 455 */ 491 - function hideIndicatorElement(element: Element): void { 492 - const strategy = detectIndicatorStrategy(element); 493 - const htmlElement = element as HTMLElement; 456 + function hideIndicatorElement(el: Element): void { 457 + const strategy = detectIndicatorStrategy(el); 458 + const htmlElement = el as HTMLElement; 494 459 495 460 if (strategy === "display") { 496 461 htmlElement.style.display = "none"; 497 462 } else { 498 - const hiddenClass = Array.from(element.classList).find((cls) => cls.toLowerCase().includes("hidden")) || "hidden"; 499 - element.classList.add(hiddenClass); 463 + const hiddenClass = Array.from(el.classList).find((cls) => cls.toLowerCase().includes("hidden")) || "hidden"; 464 + el.classList.add(hiddenClass); 500 465 } 501 466 } 502 467 ··· 549 514 return target; 550 515 } 551 516 552 - /** 553 - * Error type classification for retry logic 554 - */ 555 - type ErrorType = "network" | "server" | "client" | "other"; 556 - 557 - /** 558 - * Classify an error for retry decision 559 - * 560 - * @param error - Error or HTTP status code 561 - * @returns Error type classification 562 - */ 563 - function classifyError(error: unknown): ErrorType { 517 + function classifyError(error: unknown): "network" | "server" | "client" | "other" { 564 518 if (error instanceof Error && error.message.includes("HTTP")) { 565 519 const match = error.message.match(/HTTP (\d+):/); 566 520 if (match) { ··· 584 538 * - 5xx server errors: Always retry 585 539 * - 4xx client errors: Never retry 586 540 * - Other errors: Never retry 587 - * 588 - * @param error - Error to check 589 - * @returns True if error should be retried 590 541 */ 591 542 function shouldRetry(error: unknown): boolean { 592 543 const errorType = classifyError(error); ··· 599 550 * - Network errors: No delay (immediate retry) 600 551 * - Server errors: Exponential backoff (initialDelay × 2^attempt) 601 552 * - Other errors: No retry 602 - * 603 - * @param error - Error that occurred 604 - * @param attempt - Current attempt number (0-indexed) 605 - * @param initialDelay - Initial delay in milliseconds 606 - * @returns Delay in milliseconds before next retry 607 553 */ 608 554 function calculateRetryDelay(error: unknown, attempt: number, initialDelay: number): number { 609 555 const errorType = classifyError(error); ··· 617 563 } 618 564 619 565 return 0; 620 - } 621 - 622 - /** 623 - * Sleep for a specified duration 624 - * 625 - * @param ms - Milliseconds to sleep 626 - */ 627 - function sleep(ms: number): Promise<void> { 628 - return new Promise((resolve) => setTimeout(resolve, ms)); 629 566 } 630 567 631 568 /** ··· 704 641 console.error("HTTP request failed:", lastError); 705 642 } 706 643 707 - export function bindGet(context: BindingContext, url: string): void { 708 - bindHttpMethod(context, "GET", url); 644 + export function bindGet(ctx: BindingContext, url: string): void { 645 + bindHttpMethod(ctx, "GET", url); 709 646 } 710 647 711 - export function bindPost(context: BindingContext, url: string): void { 712 - bindHttpMethod(context, "POST", url); 648 + export function bindPost(ctx: BindingContext, url: string): void { 649 + bindHttpMethod(ctx, "POST", url); 713 650 } 714 651 715 - export function bindPut(context: BindingContext, url: string): void { 716 - bindHttpMethod(context, "PUT", url); 652 + export function bindPut(ctx: BindingContext, url: string): void { 653 + bindHttpMethod(ctx, "PUT", url); 717 654 } 718 655 719 - export function bindPatch(context: BindingContext, url: string): void { 720 - bindHttpMethod(context, "PATCH", url); 656 + export function bindPatch(ctx: BindingContext, url: string): void { 657 + bindHttpMethod(ctx, "PATCH", url); 721 658 } 722 659 723 - export function bindDelete(context: BindingContext, url: string): void { 724 - bindHttpMethod(context, "DELETE", url); 660 + export function bindDelete(ctx: BindingContext, url: string): void { 661 + bindHttpMethod(ctx, "DELETE", url); 725 662 } 726 663 727 664 /** 728 665 * Generic HTTP method binding handler 729 666 * 730 - * Attaches an event listener that triggers an HTTP request when fired. 731 - * Automatically serializes forms for POST/PUT/PATCH methods. 732 - * 733 - * @param ctx - Plugin context 734 - * @param method - HTTP method 735 - * @param url - URL expression to evaluate 667 + * Attaches an event listener that triggers an HTTP request when fired & automatically serializes forms for POST/PUT/PATCH methods. 736 668 */ 737 669 function bindHttpMethod(ctx: BindingContext | PluginContext, method: HttpMethod, url: string): void { 738 670 const config = parseHttpConfig(ctx.element, ctx.scope);
+9 -19
lib/src/core/lifecycle.ts
··· 3 3 * Provides beforeMount, afterMount, beforeUnmount, and afterUnmount hooks 4 4 */ 5 5 6 - import type { GlobalHookName, MountHookCallback, Scope, UnmountHookCallback } from "$types/volt"; 6 + import type { ElementLifecycleState, GlobalHookName, MountHookCallback, Scope, UnmountHookCallback } from "$types/volt"; 7 7 8 8 /** 9 9 * Global lifecycle hooks registry ··· 106 106 * @param root - The root element being mounted/unmounted 107 107 * @param scope - The scope object (only for mount hooks) 108 108 */ 109 - export function executeGlobalHooks(hookName: GlobalHookName, root: Element, scope?: Scope): void { 109 + export function execGlobalHooks(hookName: GlobalHookName, root: Element, scope?: Scope): void { 110 110 const hooks = lifecycleHooks.get(hookName); 111 111 if (!hooks || hooks.size === 0) { 112 112 return; ··· 126 126 } 127 127 } 128 128 } 129 - 130 - /** 131 - * Element-level lifecycle tracking for per-element hooks 132 - */ 133 - type ElementLifecycleState = { 134 - isMounted: boolean; 135 - bindings: Set<string>; 136 - onMount: Set<() => void>; 137 - onUnmount: Set<() => void>; 138 - }; 139 129 140 130 const elementLifecycleStates = new WeakMap<Element, ElementLifecycleState>(); 141 131 ··· 176 166 * Notify that an element has been mounted. 177 167 * Executes all registered onMount callbacks for the element. 178 168 * 179 - * @param element - The mounted element 169 + * @param el - The mounted element 180 170 */ 181 - export function notifyElementMounted(element: Element): void { 182 - const state = getElementLifecycleState(element); 171 + export function notifyElementMounted(el: Element): void { 172 + const state = getElementLifecycleState(el); 183 173 184 174 if (state.isMounted) { 185 175 return; ··· 200 190 * Notify that an element is being unmounted. 201 191 * Executes all registered onUnmount callbacks for the element. 202 192 * 203 - * @param element - The element being unmounted 193 + * @param el - The element being unmounted 204 194 */ 205 - export function notifyElementUnmounted(element: Element): void { 206 - const state = getElementLifecycleState(element); 195 + export function notifyElementUnmounted(el: Element): void { 196 + const state = getElementLifecycleState(el); 207 197 208 198 if (!state.isMounted) { 209 199 return; ··· 219 209 } 220 210 } 221 211 222 - elementLifecycleStates.delete(element); 212 + elementLifecycleStates.delete(el); 223 213 } 224 214 225 215 /**
+64
lib/src/core/shared.ts
··· 1 + import type { Optional } from "$types/helpers"; 2 + import type { Dep, Scope, Signal } from "$types/volt"; 3 + 4 + export function kebabToCamel(str: string): string { 5 + return str.replaceAll(/-([a-z])/g, (_, letter) => letter.toUpperCase()); 6 + } 7 + 8 + export function isSignal(value: unknown): value is Dep { 9 + return (typeof value === "object" 10 + && value !== null 11 + && "get" in value 12 + && "subscribe" in value 13 + && typeof value.get === "function" 14 + && typeof (value as { subscribe: unknown }).subscribe === "function"); 15 + } 16 + 17 + export function findScopedSignal(scope: Scope, path: string): Optional<Signal<unknown>> { 18 + const trimmed = path.trim(); 19 + const parts = trimmed.split("."); 20 + let current: unknown = scope; 21 + 22 + for (const part of parts) { 23 + if (current === null || current === undefined) { 24 + return undefined; 25 + } 26 + 27 + if (typeof current === "object" && part in (current as Record<string, unknown>)) { 28 + current = (current as Record<string, unknown>)[part]; 29 + } else { 30 + return undefined; 31 + } 32 + } 33 + 34 + if (isSignal(current)) { 35 + return current as Signal<unknown>; 36 + } 37 + 38 + return undefined; 39 + } 40 + 41 + /** 42 + * Get all data-volt-computed:name attributes from an element. 43 + * Converts kebab-case names to camelCase to match JS conventions. 44 + */ 45 + export function getComputedAttributes(el: Element): Map<string, string> { 46 + const computed = new Map<string, string>(); 47 + 48 + for (const attr of el.attributes) { 49 + if (attr.name.startsWith("data-volt-computed:")) { 50 + const name = attr.name.slice("data-volt-computed:".length); 51 + const camelName = kebabToCamel(name); 52 + computed.set(camelName, attr.value); 53 + } 54 + } 55 + 56 + return computed; 57 + } 58 + 59 + /** 60 + * Sleep for a specified duration 61 + */ 62 + export function sleep(ms: number): Promise<void> { 63 + return new Promise((resolve) => setTimeout(resolve, ms)); 64 + }
+15 -15
lib/src/core/signal.ts
··· 54 54 * The computation function is re-run whenever any of its dependencies change. 55 55 * 56 56 * @param compute - Function that computes the derived value 57 - * @param dependencies - Array of signals this computation depends on 57 + * @param dps - Array of signals this computation depends on 58 58 * @returns A ComputedSignal with get and subscribe methods 59 59 * 60 60 * @example ··· 66 66 */ 67 67 export function computed<T>( 68 68 compute: () => T, 69 - dependencies: Array<Signal<unknown> | ComputedSignal<unknown>>, 69 + dps: Array<Signal<unknown> | ComputedSignal<unknown>>, 70 70 ): ComputedSignal<T> { 71 71 let value = compute(); 72 - const subscribers = new Set<(value: T) => void>(); 72 + const subs = new Set<(value: T) => void>(); 73 73 74 74 const notify = () => { 75 - for (const callback of subscribers) { 75 + for (const cb of subs) { 76 76 try { 77 - callback(value); 77 + cb(value); 78 78 } catch (error) { 79 79 console.error("Error in computed subscriber:", error); 80 80 } ··· 89 89 } 90 90 }; 91 91 92 - for (const dependency of dependencies) { 93 - dependency.subscribe(recompute); 92 + for (const dep of dps) { 93 + dep.subscribe(recompute); 94 94 } 95 95 96 96 return { ··· 99 99 }, 100 100 101 101 subscribe(callback: (value: T) => void) { 102 - subscribers.add(callback); 102 + subs.add(callback); 103 103 104 104 return () => { 105 - subscribers.delete(callback); 105 + subs.delete(callback); 106 106 }; 107 107 }, 108 108 }; ··· 111 111 /** 112 112 * Creates a side effect that runs when dependencies change. 113 113 * 114 - * @param effectFunction - Function to run as a side effect 115 - * @param dependencies - Array of signals this effect depends on 114 + * @param cb - Function to run as a side effect 115 + * @param deps - Array of signals this effect depends on 116 116 * @returns Cleanup function to stop the effect 117 117 * 118 118 * @example ··· 122 122 * }, [count]); 123 123 */ 124 124 export function effect( 125 - effectFunction: () => void | (() => void), 126 - dependencies: Array<Signal<unknown> | ComputedSignal<unknown>>, 125 + cb: () => void | (() => void), 126 + deps: Array<Signal<unknown> | ComputedSignal<unknown>>, 127 127 ): () => void { 128 128 let cleanup: (() => void) | void; 129 129 ··· 132 132 cleanup(); 133 133 } 134 134 try { 135 - cleanup = effectFunction(); 135 + cleanup = cb(); 136 136 } catch (error) { 137 137 console.error("Error in effect:", error); 138 138 } ··· 140 140 141 141 runEffect(); 142 142 143 - const unsubscribers = dependencies.map((dependency) => dependency.subscribe(runEffect)); 143 + const unsubscribers = deps.map((dependency) => dependency.subscribe(runEffect)); 144 144 145 145 return () => { 146 146 if (cleanup) {
+24 -55
lib/src/core/ssr.ts
··· 5 5 * and hydrating client-side without re-rendering. 6 6 */ 7 7 8 + import type { Nullable } from "$types/helpers"; 8 9 import type { HydrateOptions, HydrateResult, Scope, SerializedScope } from "$types/volt"; 9 10 import { mount } from "./binder"; 10 - import { evaluate, extractDependencies } from "./evaluator"; 11 + import { evaluate, extractDeps } from "./evaluator"; 12 + import { getComputedAttributes, isSignal } from "./shared"; 11 13 import { computed, signal } from "./signal"; 12 14 13 15 /** ··· 71 73 /** 72 74 * Check if an element has already been hydrated 73 75 * 74 - * @param element - Element to check 76 + * @param el - Element to check 75 77 * @returns True if element is marked as hydrated 76 78 */ 77 - export function isHydrated(element: Element): boolean { 78 - return element.hasAttribute("data-volt-hydrated"); 79 + export function isHydrated(el: Element): boolean { 80 + return el.hasAttribute("data-volt-hydrated"); 79 81 } 80 82 81 83 /** 82 84 * Mark an element as hydrated to prevent double-hydration 83 85 * 84 - * @param element - Element to mark 86 + * @param el - Element to mark 85 87 */ 86 - function markHydrated(element: Element): void { 87 - element.setAttribute("data-volt-hydrated", "true"); 88 + function markHydrated(el: Element): void { 89 + el.setAttribute("data-volt-hydrated", "true"); 88 90 } 89 91 90 92 /** ··· 92 94 * 93 95 * Looks for a script tag with id="volt-state-{element-id}" containing JSON state. 94 96 * 95 - * @param element - Element to check 97 + * @param el - Element to check 96 98 * @returns True if serialized state is found 97 99 */ 98 - export function isServerRendered(element: Element): boolean { 99 - return getSerializedState(element) !== null; 100 + export function isServerRendered(el: Element): boolean { 101 + return getSerializedState(el) !== null; 100 102 } 101 103 102 104 /** ··· 105 107 * Searches for a `<script type="application/json" id="volt-state-{id}">` tag 106 108 * containing the serialized scope data. 107 109 * 108 - * @param element - Root element to extract state from 110 + * @param el - Root element to extract state from 109 111 * @returns Parsed state object, or null if not found 110 112 * 111 113 * @example ··· 117 119 * </div> 118 120 * ``` 119 121 */ 120 - export function getSerializedState(element: Element): SerializedScope | null { 121 - const elementId = element.id; 122 + export function getSerializedState(el: Element): Nullable<SerializedScope> { 123 + const elementId = el.id; 122 124 if (!elementId) { 123 125 return null; 124 126 } 125 127 126 128 const scriptId = `volt-state-${elementId}`; 127 - const scriptTag = element.querySelector(`script[type="application/json"]#${scriptId}`); 129 + const scriptTag = el.querySelector(`script[type="application/json"]#${scriptId}`); 128 130 129 131 if (!scriptTag || !scriptTag.textContent) { 130 132 return null; ··· 144 146 * This is similar to createScopeFromElement in charge.ts, but checks for 145 147 * server-rendered state first before falling back to data-volt-state. 146 148 * 147 - * @param element - The root element 149 + * @param el - The root element 148 150 * @returns Reactive scope object with signals 149 151 */ 150 - function createHydrationScope(element: Element): Scope { 152 + function createHydrationScope(el: Element): Scope { 151 153 let scope: Scope = {}; 152 154 153 - const serializedState = getSerializedState(element); 155 + const serializedState = getSerializedState(el); 154 156 if (serializedState) { 155 157 scope = deserializeScope(serializedState); 156 158 } else { 157 - const stateAttr = (element as HTMLElement).dataset.voltState; 159 + const stateAttr = (el as HTMLElement).dataset.voltState; 158 160 if (stateAttr) { 159 161 try { 160 162 const stateData = JSON.parse(stateAttr); 161 163 162 164 if (typeof stateData !== "object" || stateData === null || Array.isArray(stateData)) { 163 - console.error(`data-volt-state must be a JSON object, got ${typeof stateData}:`, element); 165 + console.error(`data-volt-state must be a JSON object, got ${typeof stateData}:`, el); 164 166 } else { 165 167 for (const [key, value] of Object.entries(stateData)) { 166 168 scope[key] = signal(value); ··· 168 170 } 169 171 } catch (error) { 170 172 console.error("Failed to parse data-volt-state JSON:", stateAttr, error); 171 - console.error("Element:", element); 173 + console.error("Element:", el); 172 174 } 173 175 } 174 176 } 175 177 176 - const computedAttrs = getComputedAttributes(element); 178 + const computedAttrs = getComputedAttributes(el); 177 179 for (const [name, expression] of computedAttrs) { 178 180 try { 179 - const dependencies = extractDependencies(expression, scope); 181 + const dependencies = extractDeps(expression, scope); 180 182 scope[name] = computed(() => evaluate(expression, scope), dependencies); 181 183 } catch (error) { 182 184 console.error(`Failed to create computed "${name}" with expression "${expression}":`, error); ··· 184 186 } 185 187 186 188 return scope; 187 - } 188 - 189 - /** 190 - * Get all data-volt-computed:name attributes from an element 191 - * 192 - * Converts kebab-case names to camelCase to match JS conventions. 193 - */ 194 - function getComputedAttributes(element: Element): Map<string, string> { 195 - const computedMap = new Map<string, string>(); 196 - 197 - for (const attr of element.attributes) { 198 - if (attr.name.startsWith("data-volt-computed:")) { 199 - const name = attr.name.slice("data-volt-computed:".length); 200 - const camelName = kebabToCamel(name); 201 - computedMap.set(camelName, attr.value); 202 - } 203 - } 204 - 205 - return computedMap; 206 - } 207 - 208 - function kebabToCamel(str: string): string { 209 - return str.replaceAll(/-([a-z])/g, (_, letter) => letter.toUpperCase()); 210 - } 211 - 212 - /** 213 - * Check if a value is a signal-like object 214 - */ 215 - function isSignal(value: unknown): value is { get: () => unknown } { 216 - return (typeof value === "object" 217 - && value !== null 218 - && "get" in value 219 - && typeof (value as { get: unknown }).get === "function"); 220 189 } 221 190 222 191 /**
+4 -7
lib/src/plugins/persist.ts
··· 109 109 let dbPromise: Optional<Promise<IDBDatabase>>; 110 110 111 111 /** 112 - * Open or create the IndexedDB database 112 + * Open or create the IndexedDB database ({@link IDBDatabase}) 113 113 */ 114 114 function openDB(): Promise<IDBDatabase> { 115 115 if (dbPromise) return dbPromise; ··· 136 136 return dbPromise; 137 137 } 138 138 139 - /** 140 - * Get storage adapter by name 141 - */ 142 139 function getStorageAdapter(type: string): Optional<StorageAdapter> { 143 140 switch (type) { 144 141 case "local": { ··· 167 164 * - data-volt-persist="userData:indexeddb" 168 165 * - data-volt-persist="settings:customAdapter" 169 166 */ 170 - export function persistPlugin(context: PluginContext, value: string): void { 167 + export function persistPlugin(ctx: PluginContext, value: string): void { 171 168 const parts = value.split(":"); 172 169 if (parts.length !== 2) { 173 170 console.error(`Invalid persist binding: "${value}". Expected format: "signalPath:storageType"`); ··· 175 172 } 176 173 177 174 const [signalPath, storageType] = parts; 178 - const signal = context.findSignal(signalPath.trim()); 175 + const signal = ctx.findSignal(signalPath.trim()); 179 176 180 177 if (!signal) { 181 178 console.error(`Signal "${signalPath}" not found in scope for persist binding`); ··· 220 217 } 221 218 }); 222 219 223 - context.addCleanup(unsubscribe); 220 + ctx.addCleanup(unsubscribe); 224 221 }
+23 -26
lib/src/plugins/scroll.ts
··· 6 6 import type { PluginContext, Signal } from "$types/volt"; 7 7 8 8 /** 9 - * Scroll plugin handler. 10 - * Manages various scroll-related behaviors. 9 + * Scroll plugin handler to manage various scroll-related behaviors. 11 10 * 12 11 * Syntax: data-volt-scroll="mode:signalPath" 13 12 * Modes: ··· 16 15 * - spy:signalPath - Update signal when element is visible 17 16 * - smooth:signalPath - Enable smooth scrolling behavior 18 17 */ 19 - export function scrollPlugin(context: PluginContext, value: string): void { 18 + export function scrollPlugin(ctx: PluginContext, value: string): void { 20 19 const parts = value.split(":"); 21 20 if (parts.length !== 2) { 22 21 console.error(`Invalid scroll binding: "${value}". Expected format: "mode:signalPath"`); ··· 27 26 28 27 switch (mode) { 29 28 case "restore": { 30 - handleScrollRestore(context, signalPath); 29 + handleScrollRestore(ctx, signalPath); 31 30 break; 32 31 } 33 32 case "scrollTo": { 34 - handleScrollTo(context, signalPath); 33 + handleScrollTo(ctx, signalPath); 35 34 break; 36 35 } 37 36 case "spy": { 38 - handleScrollSpy(context, signalPath); 37 + handleScrollSpy(ctx, signalPath); 39 38 break; 40 39 } 41 40 case "smooth": { 42 - handleSmoothScroll(context, signalPath); 41 + handleSmoothScroll(ctx, signalPath); 43 42 break; 44 43 } 45 44 default: { ··· 51 50 /** 52 51 * Saves current scroll position to signal on scroll events; Restores scroll position from signal on mount. 53 52 */ 54 - function handleScrollRestore(context: PluginContext, signalPath: string): void { 55 - const signal = context.findSignal(signalPath); 53 + function handleScrollRestore(ctx: PluginContext, signalPath: string): void { 54 + const signal = ctx.findSignal(signalPath); 56 55 if (!signal) { 57 56 console.error(`Signal "${signalPath}" not found for scroll restore`); 58 57 return; 59 58 } 60 59 61 - const element = context.element as HTMLElement; 60 + const element = ctx.element as HTMLElement; 62 61 const savedPosition = signal.get(); 63 62 if (typeof savedPosition === "number") { 64 63 element.scrollTop = savedPosition; ··· 70 69 71 70 element.addEventListener("scroll", savePosition, { passive: true }); 72 71 73 - context.addCleanup(() => { 72 + ctx.addCleanup(() => { 74 73 element.removeEventListener("scroll", savePosition); 75 74 }); 76 75 } 77 76 78 77 /** 79 78 * Scroll to element when signal value matches element's ID or selector. 80 - * 81 79 * Listens for changes to the target signal to determine position 82 80 */ 83 - function handleScrollTo(context: PluginContext, signalPath: string): void { 84 - const signal = context.findSignal(signalPath); 81 + function handleScrollTo(ctx: PluginContext, signalPath: string): void { 82 + const signal = ctx.findSignal(signalPath); 85 83 if (!signal) { 86 84 console.error(`Signal "${signalPath}" not found for scrollTo`); 87 85 return; 88 86 } 89 87 90 - const element = context.element as HTMLElement; 88 + const element = ctx.element as HTMLElement; 91 89 const elementId = element.id; 92 90 93 91 const checkAndScroll = (target: unknown) => { ··· 99 97 checkAndScroll(signal.get()); 100 98 101 99 const unsubscribe = signal.subscribe(checkAndScroll); 102 - context.addCleanup(unsubscribe); 100 + ctx.addCleanup(unsubscribe); 103 101 } 104 102 105 103 /** 106 104 * Update signal when element enters or exits viewport. 107 - * 108 - * Uses Intersection Observer to track visibility. 105 + * Uses {@link IntersectionObserver} to track visibility. 109 106 */ 110 - function handleScrollSpy(context: PluginContext, signalPath: string): void { 111 - const signal = context.findSignal(signalPath); 107 + function handleScrollSpy(ctx: PluginContext, signalPath: string): void { 108 + const signal = ctx.findSignal(signalPath); 112 109 if (!signal) { 113 110 console.error(`Signal "${signalPath}" not found for scroll spy`); 114 111 return; 115 112 } 116 113 117 - const element = context.element as HTMLElement; 114 + const element = ctx.element as HTMLElement; 118 115 119 116 const observer = new IntersectionObserver((entries) => { 120 117 for (const entry of entries) { ··· 126 123 127 124 observer.observe(element); 128 125 129 - context.addCleanup(() => { 126 + ctx.addCleanup(() => { 130 127 observer.disconnect(); 131 128 }); 132 129 } ··· 134 131 /** 135 132 * Enable smooth scrolling behavior and apply based on signal value. 136 133 */ 137 - function handleSmoothScroll(context: PluginContext, signalPath: string): void { 138 - const signal = context.findSignal(signalPath); 134 + function handleSmoothScroll(ctx: PluginContext, signalPath: string): void { 135 + const signal = ctx.findSignal(signalPath); 139 136 if (!signal) { 140 137 console.error(`Signal "${signalPath}" not found for smooth scroll`); 141 138 return; 142 139 } 143 140 144 - const element = context.element as HTMLElement; 141 + const element = ctx.element as HTMLElement; 145 142 146 143 const applyBehavior = (value: unknown) => { 147 144 if (value === true || value === "smooth") { ··· 155 152 156 153 const unsubscribe = signal.subscribe(applyBehavior); 157 154 158 - context.addCleanup(() => { 155 + ctx.addCleanup(() => { 159 156 unsubscribe(); 160 157 element.style.scrollBehavior = ""; 161 158 });
+12 -13
lib/src/plugins/url.ts
··· 16 16 * - sync:signalPath - Bidirectional sync between signal and URL param 17 17 * - hash:signalPath - Sync with hash portion for routing 18 18 */ 19 - export function urlPlugin(context: PluginContext, value: string): void { 19 + export function urlPlugin(ctx: PluginContext, value: string): void { 20 20 const parts = value.split(":"); 21 21 if (parts.length !== 2) { 22 22 console.error(`Invalid url binding: "${value}". Expected format: "mode:signalPath"`); ··· 27 27 28 28 switch (mode) { 29 29 case "read": { 30 - handleUrlRead(context, signalPath); 30 + handleUrlRead(ctx, signalPath); 31 31 break; 32 32 } 33 33 case "sync": { 34 - handleUrlSync(context, signalPath); 34 + handleUrlSync(ctx, signalPath); 35 35 break; 36 36 } 37 37 case "hash": { 38 - handleHashRouting(context, signalPath); 38 + handleHashRouting(ctx, signalPath); 39 39 break; 40 40 } 41 41 default: { ··· 48 48 * Read URL parameter into signal on mount (one-way). 49 49 * Signal changes do not update URL. 50 50 */ 51 - function handleUrlRead(context: PluginContext, signalPath: string): void { 52 - const signal = context.findSignal(signalPath); 51 + function handleUrlRead(ctx: PluginContext, signalPath: string): void { 52 + const signal = ctx.findSignal(signalPath); 53 53 if (!signal) { 54 54 console.error(`Signal "${signalPath}" not found for url read`); 55 55 return; ··· 67 67 * Bidirectional sync between signal and URL parameter. 68 68 * Changes to either the signal or URL update the other. 69 69 */ 70 - function handleUrlSync(context: PluginContext, signalPath: string): void { 71 - const signal = context.findSignal(signalPath); 70 + function handleUrlSync(ctx: PluginContext, signalPath: string): void { 71 + const signal = ctx.findSignal(signalPath); 72 72 if (!signal) { 73 73 console.error(`Signal "${signalPath}" not found for url sync`); 74 74 return; ··· 123 123 const unsubscribe = signal.subscribe(updateUrl); 124 124 globalThis.addEventListener("popstate", handlePopState); 125 125 126 - context.addCleanup(() => { 126 + ctx.addCleanup(() => { 127 127 unsubscribe(); 128 128 globalThis.removeEventListener("popstate", handlePopState); 129 129 if (updateTimeout) { ··· 136 136 * Sync signal with hash portion of URL for client-side routing. 137 137 * Bidirectional sync between signal and window.location.hash. 138 138 */ 139 - function handleHashRouting(context: PluginContext, signalPath: string): void { 140 - const signal = context.findSignal(signalPath); 139 + function handleHashRouting(ctx: PluginContext, signalPath: string): void { 140 + const signal = ctx.findSignal(signalPath); 141 141 if (!signal) { 142 142 console.error(`Signal "${signalPath}" not found for hash routing`); 143 143 return; ··· 171 171 const unsubscribe = signal.subscribe(updateHash); 172 172 globalThis.addEventListener("hashchange", handleHashChange); 173 173 174 - context.addCleanup(() => { 174 + ctx.addCleanup(() => { 175 175 unsubscribe(); 176 176 globalThis.removeEventListener("hashchange", handleHashChange); 177 177 }); ··· 179 179 180 180 /** 181 181 * Serialize a value for URL parameter storage. 182 - * 183 182 * Handles strings, numbers, booleans, and No Value (null/undefined). 184 183 */ 185 184 function serializeValue(value: unknown): string {
+39 -153
lib/src/styles/base.css
··· 15 15 16 16 /** 17 17 * Root-level CSS variables define the design system. 18 + * 18 19 * Light theme is default, dark theme overrides via media query. 19 20 */ 20 21 :root { 21 22 /* Typography Scale - Modular scale based on 1.25 ratio */ 22 23 --font-size-base: 18px; 23 - --font-size-sm: 0.889rem; /* 16px */ 24 - --font-size-lg: 1.125rem; /* 20.25px */ 25 - --font-size-xl: 1.266rem; /* 22.8px */ 26 - --font-size-2xl: 1.424rem; /* 25.6px */ 27 - --font-size-3xl: 1.802rem; /* 32.4px */ 28 - --font-size-4xl: 2.027rem; /* 36.5px */ 29 - --font-size-5xl: 2.566rem; /* 46.2px */ 24 + --font-size-sm: 0.889rem; 25 + --font-size-lg: 1.125rem; 26 + --font-size-xl: 1.266rem; 27 + --font-size-2xl: 1.424rem; 28 + --font-size-3xl: 1.802rem; 29 + --font-size-4xl: 2.027rem; 30 + --font-size-5xl: 2.566rem; 30 31 31 32 --font-sans: "Inter", sans-serif; 32 33 --font-serif: "Libre Baskerville", serif; 33 34 --font-mono: "Google Sans Code", monospace; 34 35 35 36 /* Spacing Scale - Based on 0.5rem increments */ 36 - --space-xs: 0.25rem; /* 4px */ 37 - --space-sm: 0.5rem; /* 8px */ 38 - --space-md: 1rem; /* 16px */ 39 - --space-lg: 1.5rem; /* 24px */ 40 - --space-xl: 2rem; /* 32px */ 41 - --space-2xl: 3rem; /* 48px */ 42 - --space-3xl: 4rem; /* 64px */ 37 + --space-xs: 0.25rem; 38 + --space-sm: 0.5rem; 39 + --space-md: 1rem; 40 + --space-lg: 1.5rem; 41 + --space-xl: 2rem; 42 + --space-2xl: 3rem; 43 + --space-3xl: 4rem; 43 44 44 - /* Line Heights */ 45 45 --line-height-tight: 1.25; 46 46 --line-height-base: 1.6; 47 47 --line-height-relaxed: 1.8; 48 48 49 - /* Layout Dimensions */ 50 - --content-width: 70ch; /* Optimal line length for reading */ 51 - --sidenote-width: 18rem; /* Width of margin notes */ 52 - --sidenote-gap: 2rem; /* Space between content and sidenotes */ 49 + --content-width: 79ch; 50 + /* Width of margin notes */ 51 + --sidenote-width: 18rem; 52 + /* Space between content and sidenotes */ 53 + --sidenote-gap: 2rem; 53 54 54 - /* Light Theme Colors - Duotone palette for clarity */ 55 55 --color-bg: #fefefe; 56 - --color-bg-alt: #f5f5f5; /* For code blocks, tables */ 56 + /* For code blocks, tables */ 57 + --color-bg-alt: #f5f5f5; 57 58 --color-text: #1a1a1a; 58 59 --color-text-muted: #666666; 59 - --color-accent: #0066cc; /* Links, primary actions */ 60 + /* Links, primary actions */ 61 + --color-accent: #0066cc; 60 62 --color-accent-hover: #0052a3; 61 63 --color-border: #d4d4d4; 62 64 --color-code-bg: #f8f8f8; 63 - --color-mark: #fff3cd; /* Highlighted text */ 65 + /* Highlighted text */ 66 + --color-mark: #fff3cd; 64 67 --color-success: #22863a; 65 68 --color-warning: #bf8700; 66 69 --color-error: #cb2431; ··· 70 73 --shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1); 71 74 72 75 /* Border Radius */ 76 + --radius-xs: 1px; 73 77 --radius-sm: 3px; 74 78 --radius-md: 6px; 75 79 --radius-lg: 8px; ··· 104 108 } 105 109 } 106 110 107 - /** 108 - * CSS reset 109 - */ 110 111 *, *::before, *::after { 111 112 box-sizing: border-box; 112 113 } ··· 147 148 148 149 /** 149 150 * Headings hierarchy 150 - * Uses modular scale for harmonious sizing 151 - * Tighter line-height for larger text improves readability 151 + * - Uses modular scale for harmonious sizing 152 + * - Tighter line-height for larger text improves readability 152 153 */ 153 154 h1, h2, h3, h4, h5, h6 { 154 155 font-weight: 700; ··· 156 157 color: var(--color-text); 157 158 margin-top: var(--space-2xl); 158 159 margin-bottom: var(--space-md); 159 - letter-spacing: -0.02em; /* Slight negative tracking for display text */ 160 + letter-spacing: -0.02em; 160 161 } 161 162 162 - /** 163 - * Individual heading sizes 164 - * h1-h3 use slightly larger weights for emphasis 165 - */ 166 163 h1 { 167 164 font-size: var(--font-size-5xl); 168 - margin-top: 0; /* No top margin on first heading */ 165 + margin-top: 0; 169 166 } 170 167 171 168 h2 { ··· 193 190 194 191 /** 195 192 * Paragraph spacing 193 + * 196 194 * Generous spacing between paragraphs aids scanning 197 195 */ 198 196 p { ··· 232 230 border-radius: var(--radius-sm); 233 231 } 234 232 235 - /** 236 - * Emphasis and strong elements 237 - */ 238 233 em { 239 234 font-style: italic; 240 235 } ··· 243 238 font-weight: 700; 244 239 } 245 240 246 - /** 247 - * Marked/highlighted text 248 - */ 249 241 mark { 250 242 background-color: var(--color-mark); 251 243 padding: 0.1em 0.2em; ··· 381 373 } 382 374 } 383 375 384 - /* ========================================================================== 385 - Blockquotes & Citations 386 - ========================================================================== */ 387 - 388 376 /** 389 377 * Blockquote styling 390 378 * Left border for visual distinction, italic for emphasis ··· 414 402 } 415 403 416 404 blockquote cite::before { 417 - /* TODO: fix */ 418 - content: " "; 405 + /* em dash */ 406 + content: "— "; 419 407 } 420 408 421 409 /** ··· 427 415 font-family: var(--font-mono); 428 416 font-size: 0.9em; 429 417 padding: 0.15em 0.4em; 418 + color: var(--color-text); 430 419 background-color: var(--color-code-bg); 431 420 border: 1px solid var(--color-border); 432 421 border-radius: var(--radius-sm); ··· 447 436 box-shadow: 0 1px 0 var(--color-border), 0 0 0 2px var(--color-bg) inset; 448 437 } 449 438 450 - /** 451 - * Sample output 452 - */ 453 439 samp { 454 440 font-family: var(--font-mono); 455 441 font-size: 0.9em; 456 442 } 457 443 458 - /** 459 - * Variable 460 - */ 461 444 var { 462 445 font-family: var(--font-mono); 463 446 font-style: normal; ··· 472 455 pre { 473 456 margin: var(--space-xl) 0; 474 457 padding: var(--space-lg); 458 + color: var(--color-text); 475 459 background-color: var(--color-code-bg); 476 460 border: 1px solid var(--color-border); 477 461 border-radius: var(--radius-md); ··· 482 466 483 467 pre code { 484 468 padding: 0; 469 + color: inherit; 485 470 background: none; 486 471 border: none; 487 472 font-size: 0.875rem; 488 473 } 489 474 490 475 491 - /** 492 - * Section dividers 493 - * 494 - * Centered decorative element 495 - */ 496 476 hr { 497 477 margin: var(--space-3xl) auto; 498 478 border: none; ··· 500 480 max-width: 50%; 501 481 } 502 482 503 - /** 504 - * Table container for horizontal scrolling on small screens 505 - */ 506 483 table { 507 484 width: 100%; 508 485 max-width: var(--content-width); ··· 512 489 display: block; 513 490 } 514 491 515 - /** 516 - * Table header styling 517 - * 518 - * Bold text with bottom border 519 - */ 520 492 thead { 521 493 background-color: var(--color-bg-alt); 522 494 border-bottom: 2px solid var(--color-border); ··· 529 501 color: var(--color-text); 530 502 } 531 503 532 - /** 533 - * Table cells 534 - */ 535 504 td { 536 505 padding: var(--space-sm) var(--space-md); 537 506 border-bottom: 1px solid var(--color-border); 538 507 } 539 508 540 - /** 541 - * Zebra striping for easier row scanning 542 - */ 543 509 tbody tr:nth-child(even) { 544 510 background-color: var(--color-bg-alt); 545 511 } 546 512 547 - /** 548 - * Hover state for interactive tables 549 - */ 550 513 tbody tr:hover { 551 514 background-color: var(--color-border); 552 515 transition: background-color var(--transition-fast); 553 516 } 554 517 555 - /** 556 - * Form container spacing 557 - */ 558 518 form { 559 519 margin: var(--space-xl) 0; 560 520 max-width: var(--content-width); 561 521 } 562 522 563 - /** 564 - * Fieldset grouping 565 - */ 566 523 fieldset { 567 524 border: 1px solid var(--color-border); 568 525 border-radius: var(--radius-md); ··· 576 533 color: var(--color-text); 577 534 } 578 535 579 - /** 580 - * Labels 581 - * 582 - * Block display for better touch targets 583 - */ 584 536 label { 585 537 display: block; 586 538 margin-bottom: var(--space-xs); ··· 588 540 color: var(--color-text); 589 541 } 590 542 591 - /** 592 - * Required field indicator 593 - */ 594 543 label:has(+ input[required])::after, 595 544 label:has(+ textarea[required])::after, 596 545 label:has(+ select[required])::after { ··· 598 547 color: var(--color-error); 599 548 } 600 549 601 - /** 602 - * Text inputs and textareas 603 - */ 604 550 input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="file"]), 605 551 select, 606 552 textarea { ··· 617 563 margin-bottom: var(--space-md); 618 564 } 619 565 620 - /** 621 - * Focus states for inputs 622 - * 623 - * Clear visual feedback for keyboard navigation 624 - */ 625 566 input:focus, 626 567 select:focus, 627 568 textarea:focus { ··· 630 571 box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1); 631 572 } 632 573 633 - /** 634 - * Disabled state 635 - */ 636 574 input:disabled, 637 575 select:disabled, 638 576 textarea:disabled { ··· 641 579 background-color: var(--color-bg-alt); 642 580 } 643 581 644 - /** 645 - * Textarea specific 646 - */ 647 582 textarea { 648 583 resize: vertical; 649 584 min-height: 8rem; 650 585 } 651 586 652 - /** 653 - * Checkboxes and radio buttons 654 - */ 655 587 input[type="checkbox"], 656 588 input[type="radio"] { 657 589 margin-right: var(--space-xs); 658 590 accent-color: var(--color-accent); 659 591 } 660 592 661 - /** 662 - * File input 663 - */ 664 593 input[type="file"] { 665 594 padding: var(--space-sm); 666 595 border: 1px dashed var(--color-border); ··· 669 598 margin-bottom: var(--space-md); 670 599 } 671 600 672 - /** 673 - * Range input 674 - */ 675 601 input[type="range"] { 676 602 width: 100%; 677 603 margin: var(--space-md) 0; 678 604 accent-color: var(--color-accent); 679 605 } 680 606 681 - /** 682 - * Progress and meter 683 - */ 684 607 progress, meter { 685 608 width: 100%; 686 609 height: 1.5rem; ··· 689 612 overflow: hidden; 690 613 } 691 614 692 - /** 693 - * Button styling 694 - * Primary action style with hover and active states 695 - */ 696 615 button, 697 616 input[type="submit"], 698 617 input[type="button"], ··· 726 645 transform: translateY(1px); 727 646 } 728 647 729 - /** 730 - * Reset button - Subdued styling 731 - */ 732 648 input[type="reset"] { 733 649 background-color: var(--color-bg-alt); 734 650 color: var(--color-text); ··· 739 655 background-color: var(--color-border); 740 656 } 741 657 742 - /** 743 - * Disabled buttons 744 - */ 745 658 button:disabled, 746 659 input[type="submit"]:disabled, 747 660 input[type="button"]:disabled { ··· 750 663 transform: none; 751 664 } 752 665 753 - /** 754 - * Focus state for buttons 755 - */ 756 666 button:focus-visible, 757 667 input[type="submit"]:focus-visible, 758 668 input[type="button"]:focus-visible { ··· 761 671 } 762 672 763 673 /** 764 - * Images 765 - * 766 - * Responsive by default, maintains aspect ratio 674 + * Images are responsive by default, maintains aspect ratio 767 675 */ 768 676 img { 769 677 max-width: 100%; ··· 789 697 text-align: center; 790 698 } 791 699 792 - /** 793 - * Video and audio 794 - */ 795 700 video, audio { 796 701 max-width: 100%; 797 702 margin: var(--space-xl) 0; ··· 809 714 margin: var(--space-xl) 0; 810 715 } 811 716 812 - /** 813 - * Article and Section 814 - * Spacing between major content blocks 815 - */ 816 717 article, section { 817 718 margin-bottom: var(--space-3xl); 818 719 } 819 720 820 - /** 821 - * Aside 822 - * Complementary content, styled distinctly 823 - */ 824 721 aside { 825 722 padding: var(--space-lg); 826 723 margin: var(--space-xl) 0; ··· 830 727 max-width: var(--content-width); 831 728 } 832 729 833 - /** 834 - * Header and Footer 835 - */ 836 730 header { 837 731 margin-bottom: var(--space-2xl); 838 732 padding-bottom: var(--space-xl); ··· 896 790 897 791 /** 898 792 * Screen reader only 793 + * 899 794 * Hides content visually but keeps it accessible to assistive technology 900 795 */ 901 796 .sr-only { ··· 910 805 border-width: 0; 911 806 } 912 807 913 - /** 914 - * Print-specific optimizations 915 - */ 916 808 @media print { 917 809 body { 918 810 font-size: 12pt; ··· 952 844 } 953 845 } 954 846 955 - /** 956 - * Tablet and below - Reduce spacing 957 - */ 958 847 @media (max-width: 768px) { 959 848 :root { 960 849 --font-size-base: 16px; ··· 981 870 } 982 871 } 983 872 984 - /** 985 - * Mobile - Further reduced spacing and sizing 986 - */ 987 873 @media (max-width: 480px) { 988 874 :root { 989 875 --font-size-base: 15px;
+10
lib/src/types/volt.d.ts
··· 281 281 export type SerializedScope = Record<string, unknown>; 282 282 283 283 export type HydrateResult = ChargeResult; 284 + 285 + /** 286 + * Element-level lifecycle tracking for per-element hooks 287 + */ 288 + export type ElementLifecycleState = { 289 + isMounted: boolean; 290 + bindings: Set<string>; 291 + onMount: Set<() => void>; 292 + onUnmount: Set<() => void>; 293 + };
+26
lib/test/core/binder.test.ts
··· 121 121 expect(element.classList.contains("baz")).toBe(true); 122 122 }); 123 123 124 + it("binds data-volt-class with multiple signal dependencies", () => { 125 + const element = document.createElement("div"); 126 + element.dataset.voltClass = "{active: isActive, disabled: isDisabled}"; 127 + 128 + const isActive = signal(true); 129 + const isDisabled = signal(false); 130 + const scope = { isActive, isDisabled }; 131 + mount(element, scope); 132 + 133 + expect(element.classList.contains("active")).toBe(true); 134 + expect(element.classList.contains("disabled")).toBe(false); 135 + 136 + isActive.set(false); 137 + expect(element.classList.contains("active")).toBe(false); 138 + expect(element.classList.contains("disabled")).toBe(false); 139 + 140 + isDisabled.set(true); 141 + expect(element.classList.contains("active")).toBe(false); 142 + expect(element.classList.contains("disabled")).toBe(true); 143 + 144 + isActive.set(true); 145 + isDisabled.set(false); 146 + expect(element.classList.contains("active")).toBe(true); 147 + expect(element.classList.contains("disabled")).toBe(false); 148 + }); 149 + 124 150 it("binds nested elements", () => { 125 151 const parent = document.createElement("div"); 126 152 const child1 = document.createElement("span");
+14
lib/test/core/evaluator.test.ts
··· 348 348 expect(evaluate("count.get()", scope)).toBe(5); 349 349 }); 350 350 351 + it("calls methods on signal values", () => { 352 + const email = signal("test@example.com"); 353 + const text = signal("hello world"); 354 + const items = signal([1, 2, 3, 4]); 355 + const scope = { email, text, items }; 356 + 357 + expect(evaluate("email.includes('@')", scope)).toBe(true); 358 + expect(evaluate("email.includes('xyz')", scope)).toBe(false); 359 + expect(evaluate("text.toUpperCase()", scope)).toBe("HELLO WORLD"); 360 + expect(evaluate("text.substring(0, 5)", scope)).toBe("hello"); 361 + expect(evaluate("items.indexOf(3)", scope)).toBe(2); 362 + expect(evaluate("items.slice(1, 3)", scope)).toEqual([2, 3]); 363 + }); 364 + 351 365 it("calls methods with multiple arguments", () => { 352 366 const scope = { text: "one,two,three" }; 353 367 expect(evaluate("text.split(',')", scope)).toEqual(["one", "two", "three"]);
+37
lib/test/core/if-binding.test.ts
··· 1 1 import { mount } from "$core/binder"; 2 + import { extractDeps } from "$core/evaluator"; 2 3 import { signal } from "$core/signal"; 3 4 import { describe, expect, it } from "vitest"; 4 5 ··· 249 250 expect(container.querySelector("#empty")).toBeNull(); 250 251 expect(container.querySelector("#one")).toBeTruthy(); 251 252 expect(container.querySelector("#string")).toBeTruthy(); 253 + }); 254 + 255 + it("reacts to complex expressions with multiple signal dependencies", () => { 256 + const container = document.createElement("div"); 257 + container.innerHTML = ` 258 + <div> 259 + <p data-volt-if="value.length > 0 && !isValid">Error message</p> 260 + </div> 261 + `; 262 + 263 + const value = signal(""); 264 + const isValid = signal(true); 265 + const scope = { value, isValid }; 266 + const deps = extractDeps("value.length > 0 && !isValid", scope); 267 + expect(deps.length).toBe(2); 268 + expect(deps).toContain(value); 269 + expect(deps).toContain(isValid); 270 + 271 + mount(container, scope); 272 + expect(container.querySelector("p")).toBeNull(); 273 + 274 + value.set("test"); 275 + expect(container.querySelector("p")).toBeNull(); 276 + 277 + isValid.set(false); 278 + expect(container.querySelector("p")).toBeTruthy(); 279 + expect(container.querySelector("p")?.textContent).toBe("Error message"); 280 + 281 + value.set(""); 282 + expect(container.querySelector("p")).toBeNull(); 283 + 284 + value.set("test"); 285 + expect(container.querySelector("p")).toBeTruthy(); 286 + 287 + isValid.set(true); 288 + expect(container.querySelector("p")).toBeNull(); 252 289 }); 253 290 });
-1
package.json
··· 3 3 "version": "1.0.0", 4 4 "private": true, 5 5 "type": "module", 6 - "workspaces": ["lib", "dev", "docs"], 7 6 "scripts": { 8 7 "dev": "pnpm --filter volt dev", 9 8 "build": "pnpm -r build",
+5 -5
pnpm-lock.yaml
··· 39 39 specifier: ^3.2.4 40 40 version: 3.2.4(@types/node@24.8.1)(jiti@2.6.1)(jsdom@27.0.0(postcss@8.5.6))(terser@5.44.0)(yaml@2.8.1) 41 41 42 - cli: 42 + dev: 43 43 dependencies: 44 44 chalk: 45 45 specifier: ^5.6.2 ··· 59 59 version: 10.3.1(magicast@0.3.5) 60 60 tsdown: 61 61 specifier: ^0.15.6 62 - version: 0.15.7(typescript@5.9.3) 62 + version: 0.15.8(typescript@5.9.3) 63 63 64 64 docs: 65 65 devDependencies: ··· 2119 2119 peerDependencies: 2120 2120 typescript: '>=4.8.4' 2121 2121 2122 - tsdown@0.15.7: 2123 - resolution: {integrity: sha512-uFaVgWAogjOMqjY+CQwrUt3C6wzy6ynt82CIoXymnbS17ipUZ8WDXUceJjkislUahF/BZc5+W44Ue3p2oWtqUg==} 2122 + tsdown@0.15.8: 2123 + resolution: {integrity: sha512-A9CY3lO2SC6G5wyQV38cNdPkDmCoIQ6zYVd+lLnEGH09BxNRTJkCHfb7cBeBxZYJDYGFtgg/3yBpEryYJjBd+Q==} 2124 2124 engines: {node: '>=20.19.0'} 2125 2125 hasBin: true 2126 2126 peerDependencies: ··· 4361 4361 dependencies: 4362 4362 typescript: 5.9.3 4363 4363 4364 - tsdown@0.15.7(typescript@5.9.3): 4364 + tsdown@0.15.8(typescript@5.9.3): 4365 4365 dependencies: 4366 4366 ansis: 4.2.0 4367 4367 cac: 6.7.14
+1 -1
pnpm-workspace.yaml
··· 1 1 packages: 2 2 - 'lib' 3 - - 'cli' 3 + - 'dev' 4 4 - 'docs'