web-doc 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. package/LICENSE-APACHE +201 -0
  2. package/LICENSE-MIT +21 -0
  3. package/README.md +148 -0
  4. package/THIRD_PARTY_NOTICES.md +20 -0
  5. package/bin/copy-assets.mjs +27 -0
  6. package/dist/abort.d.ts +1 -0
  7. package/dist/abort.js +18 -0
  8. package/dist/adapters/bitmap.d.ts +9 -0
  9. package/dist/adapters/bitmap.js +63 -0
  10. package/dist/adapters/csv-parser.d.ts +7 -0
  11. package/dist/adapters/csv-parser.js +124 -0
  12. package/dist/adapters/csv.d.ts +26 -0
  13. package/dist/adapters/csv.js +231 -0
  14. package/dist/adapters/image.d.ts +41 -0
  15. package/dist/adapters/image.js +198 -0
  16. package/dist/adapters/office.d.ts +211 -0
  17. package/dist/adapters/office.js +672 -0
  18. package/dist/adapters/pdf.d.ts +32 -0
  19. package/dist/adapters/pdf.js +429 -0
  20. package/dist/adapters/svg.d.ts +17 -0
  21. package/dist/adapters/svg.js +123 -0
  22. package/dist/assets/image/index.d.ts +75 -0
  23. package/dist/assets/image/index.js +289 -0
  24. package/dist/assets/image/index_bg.wasm +0 -0
  25. package/dist/assets/image/index_bg.wasm.d.ts +12 -0
  26. package/dist/assets/legacy/index.d.ts +54 -0
  27. package/dist/assets/legacy/index.js +306 -0
  28. package/dist/assets/legacy/index_bg.wasm +0 -0
  29. package/dist/assets/legacy/index_bg.wasm.d.ts +9 -0
  30. package/dist/assets/pdfjs/cmaps/78-EUC-H.bcmap +0 -0
  31. package/dist/assets/pdfjs/cmaps/78-EUC-V.bcmap +0 -0
  32. package/dist/assets/pdfjs/cmaps/78-H.bcmap +0 -0
  33. package/dist/assets/pdfjs/cmaps/78-RKSJ-H.bcmap +0 -0
  34. package/dist/assets/pdfjs/cmaps/78-RKSJ-V.bcmap +0 -0
  35. package/dist/assets/pdfjs/cmaps/78-V.bcmap +0 -0
  36. package/dist/assets/pdfjs/cmaps/78ms-RKSJ-H.bcmap +0 -0
  37. package/dist/assets/pdfjs/cmaps/78ms-RKSJ-V.bcmap +0 -0
  38. package/dist/assets/pdfjs/cmaps/83pv-RKSJ-H.bcmap +0 -0
  39. package/dist/assets/pdfjs/cmaps/90ms-RKSJ-H.bcmap +0 -0
  40. package/dist/assets/pdfjs/cmaps/90ms-RKSJ-V.bcmap +0 -0
  41. package/dist/assets/pdfjs/cmaps/90msp-RKSJ-H.bcmap +0 -0
  42. package/dist/assets/pdfjs/cmaps/90msp-RKSJ-V.bcmap +0 -0
  43. package/dist/assets/pdfjs/cmaps/90pv-RKSJ-H.bcmap +0 -0
  44. package/dist/assets/pdfjs/cmaps/90pv-RKSJ-V.bcmap +0 -0
  45. package/dist/assets/pdfjs/cmaps/Add-H.bcmap +0 -0
  46. package/dist/assets/pdfjs/cmaps/Add-RKSJ-H.bcmap +0 -0
  47. package/dist/assets/pdfjs/cmaps/Add-RKSJ-V.bcmap +0 -0
  48. package/dist/assets/pdfjs/cmaps/Add-V.bcmap +0 -0
  49. package/dist/assets/pdfjs/cmaps/Adobe-CNS1-0.bcmap +0 -0
  50. package/dist/assets/pdfjs/cmaps/Adobe-CNS1-1.bcmap +0 -0
  51. package/dist/assets/pdfjs/cmaps/Adobe-CNS1-2.bcmap +0 -0
  52. package/dist/assets/pdfjs/cmaps/Adobe-CNS1-3.bcmap +0 -0
  53. package/dist/assets/pdfjs/cmaps/Adobe-CNS1-4.bcmap +0 -0
  54. package/dist/assets/pdfjs/cmaps/Adobe-CNS1-5.bcmap +0 -0
  55. package/dist/assets/pdfjs/cmaps/Adobe-CNS1-6.bcmap +0 -0
  56. package/dist/assets/pdfjs/cmaps/Adobe-CNS1-UCS2.bcmap +0 -0
  57. package/dist/assets/pdfjs/cmaps/Adobe-GB1-0.bcmap +0 -0
  58. package/dist/assets/pdfjs/cmaps/Adobe-GB1-1.bcmap +0 -0
  59. package/dist/assets/pdfjs/cmaps/Adobe-GB1-2.bcmap +0 -0
  60. package/dist/assets/pdfjs/cmaps/Adobe-GB1-3.bcmap +0 -0
  61. package/dist/assets/pdfjs/cmaps/Adobe-GB1-4.bcmap +0 -0
  62. package/dist/assets/pdfjs/cmaps/Adobe-GB1-5.bcmap +0 -0
  63. package/dist/assets/pdfjs/cmaps/Adobe-GB1-UCS2.bcmap +0 -0
  64. package/dist/assets/pdfjs/cmaps/Adobe-Japan1-0.bcmap +0 -0
  65. package/dist/assets/pdfjs/cmaps/Adobe-Japan1-1.bcmap +0 -0
  66. package/dist/assets/pdfjs/cmaps/Adobe-Japan1-2.bcmap +0 -0
  67. package/dist/assets/pdfjs/cmaps/Adobe-Japan1-3.bcmap +0 -0
  68. package/dist/assets/pdfjs/cmaps/Adobe-Japan1-4.bcmap +0 -0
  69. package/dist/assets/pdfjs/cmaps/Adobe-Japan1-5.bcmap +0 -0
  70. package/dist/assets/pdfjs/cmaps/Adobe-Japan1-6.bcmap +0 -0
  71. package/dist/assets/pdfjs/cmaps/Adobe-Japan1-UCS2.bcmap +0 -0
  72. package/dist/assets/pdfjs/cmaps/Adobe-Korea1-0.bcmap +0 -0
  73. package/dist/assets/pdfjs/cmaps/Adobe-Korea1-1.bcmap +0 -0
  74. package/dist/assets/pdfjs/cmaps/Adobe-Korea1-2.bcmap +0 -0
  75. package/dist/assets/pdfjs/cmaps/Adobe-Korea1-UCS2.bcmap +0 -0
  76. package/dist/assets/pdfjs/cmaps/B5-H.bcmap +0 -0
  77. package/dist/assets/pdfjs/cmaps/B5-V.bcmap +0 -0
  78. package/dist/assets/pdfjs/cmaps/B5pc-H.bcmap +0 -0
  79. package/dist/assets/pdfjs/cmaps/B5pc-V.bcmap +0 -0
  80. package/dist/assets/pdfjs/cmaps/CNS-EUC-H.bcmap +0 -0
  81. package/dist/assets/pdfjs/cmaps/CNS-EUC-V.bcmap +0 -0
  82. package/dist/assets/pdfjs/cmaps/CNS1-H.bcmap +0 -0
  83. package/dist/assets/pdfjs/cmaps/CNS1-V.bcmap +0 -0
  84. package/dist/assets/pdfjs/cmaps/CNS2-H.bcmap +0 -0
  85. package/dist/assets/pdfjs/cmaps/CNS2-V.bcmap +3 -0
  86. package/dist/assets/pdfjs/cmaps/ETHK-B5-H.bcmap +0 -0
  87. package/dist/assets/pdfjs/cmaps/ETHK-B5-V.bcmap +0 -0
  88. package/dist/assets/pdfjs/cmaps/ETen-B5-H.bcmap +0 -0
  89. package/dist/assets/pdfjs/cmaps/ETen-B5-V.bcmap +0 -0
  90. package/dist/assets/pdfjs/cmaps/ETenms-B5-H.bcmap +3 -0
  91. package/dist/assets/pdfjs/cmaps/ETenms-B5-V.bcmap +0 -0
  92. package/dist/assets/pdfjs/cmaps/EUC-H.bcmap +0 -0
  93. package/dist/assets/pdfjs/cmaps/EUC-V.bcmap +0 -0
  94. package/dist/assets/pdfjs/cmaps/Ext-H.bcmap +0 -0
  95. package/dist/assets/pdfjs/cmaps/Ext-RKSJ-H.bcmap +0 -0
  96. package/dist/assets/pdfjs/cmaps/Ext-RKSJ-V.bcmap +0 -0
  97. package/dist/assets/pdfjs/cmaps/Ext-V.bcmap +0 -0
  98. package/dist/assets/pdfjs/cmaps/GB-EUC-H.bcmap +0 -0
  99. package/dist/assets/pdfjs/cmaps/GB-EUC-V.bcmap +0 -0
  100. package/dist/assets/pdfjs/cmaps/GB-H.bcmap +4 -0
  101. package/dist/assets/pdfjs/cmaps/GB-V.bcmap +0 -0
  102. package/dist/assets/pdfjs/cmaps/GBK-EUC-H.bcmap +0 -0
  103. package/dist/assets/pdfjs/cmaps/GBK-EUC-V.bcmap +0 -0
  104. package/dist/assets/pdfjs/cmaps/GBK2K-H.bcmap +0 -0
  105. package/dist/assets/pdfjs/cmaps/GBK2K-V.bcmap +0 -0
  106. package/dist/assets/pdfjs/cmaps/GBKp-EUC-H.bcmap +0 -0
  107. package/dist/assets/pdfjs/cmaps/GBKp-EUC-V.bcmap +0 -0
  108. package/dist/assets/pdfjs/cmaps/GBT-EUC-H.bcmap +0 -0
  109. package/dist/assets/pdfjs/cmaps/GBT-EUC-V.bcmap +0 -0
  110. package/dist/assets/pdfjs/cmaps/GBT-H.bcmap +0 -0
  111. package/dist/assets/pdfjs/cmaps/GBT-V.bcmap +0 -0
  112. package/dist/assets/pdfjs/cmaps/GBTpc-EUC-H.bcmap +0 -0
  113. package/dist/assets/pdfjs/cmaps/GBTpc-EUC-V.bcmap +0 -0
  114. package/dist/assets/pdfjs/cmaps/GBpc-EUC-H.bcmap +0 -0
  115. package/dist/assets/pdfjs/cmaps/GBpc-EUC-V.bcmap +0 -0
  116. package/dist/assets/pdfjs/cmaps/H.bcmap +0 -0
  117. package/dist/assets/pdfjs/cmaps/HKdla-B5-H.bcmap +0 -0
  118. package/dist/assets/pdfjs/cmaps/HKdla-B5-V.bcmap +0 -0
  119. package/dist/assets/pdfjs/cmaps/HKdlb-B5-H.bcmap +0 -0
  120. package/dist/assets/pdfjs/cmaps/HKdlb-B5-V.bcmap +0 -0
  121. package/dist/assets/pdfjs/cmaps/HKgccs-B5-H.bcmap +0 -0
  122. package/dist/assets/pdfjs/cmaps/HKgccs-B5-V.bcmap +0 -0
  123. package/dist/assets/pdfjs/cmaps/HKm314-B5-H.bcmap +0 -0
  124. package/dist/assets/pdfjs/cmaps/HKm314-B5-V.bcmap +0 -0
  125. package/dist/assets/pdfjs/cmaps/HKm471-B5-H.bcmap +0 -0
  126. package/dist/assets/pdfjs/cmaps/HKm471-B5-V.bcmap +0 -0
  127. package/dist/assets/pdfjs/cmaps/HKscs-B5-H.bcmap +0 -0
  128. package/dist/assets/pdfjs/cmaps/HKscs-B5-V.bcmap +0 -0
  129. package/dist/assets/pdfjs/cmaps/Hankaku.bcmap +0 -0
  130. package/dist/assets/pdfjs/cmaps/Hiragana.bcmap +0 -0
  131. package/dist/assets/pdfjs/cmaps/KSC-EUC-H.bcmap +0 -0
  132. package/dist/assets/pdfjs/cmaps/KSC-EUC-V.bcmap +0 -0
  133. package/dist/assets/pdfjs/cmaps/KSC-H.bcmap +0 -0
  134. package/dist/assets/pdfjs/cmaps/KSC-Johab-H.bcmap +0 -0
  135. package/dist/assets/pdfjs/cmaps/KSC-Johab-V.bcmap +0 -0
  136. package/dist/assets/pdfjs/cmaps/KSC-V.bcmap +0 -0
  137. package/dist/assets/pdfjs/cmaps/KSCms-UHC-H.bcmap +0 -0
  138. package/dist/assets/pdfjs/cmaps/KSCms-UHC-HW-H.bcmap +0 -0
  139. package/dist/assets/pdfjs/cmaps/KSCms-UHC-HW-V.bcmap +0 -0
  140. package/dist/assets/pdfjs/cmaps/KSCms-UHC-V.bcmap +0 -0
  141. package/dist/assets/pdfjs/cmaps/KSCpc-EUC-H.bcmap +0 -0
  142. package/dist/assets/pdfjs/cmaps/KSCpc-EUC-V.bcmap +0 -0
  143. package/dist/assets/pdfjs/cmaps/Katakana.bcmap +0 -0
  144. package/dist/assets/pdfjs/cmaps/LICENSE +36 -0
  145. package/dist/assets/pdfjs/cmaps/NWP-H.bcmap +0 -0
  146. package/dist/assets/pdfjs/cmaps/NWP-V.bcmap +0 -0
  147. package/dist/assets/pdfjs/cmaps/RKSJ-H.bcmap +0 -0
  148. package/dist/assets/pdfjs/cmaps/RKSJ-V.bcmap +0 -0
  149. package/dist/assets/pdfjs/cmaps/Roman.bcmap +0 -0
  150. package/dist/assets/pdfjs/cmaps/UniCNS-UCS2-H.bcmap +0 -0
  151. package/dist/assets/pdfjs/cmaps/UniCNS-UCS2-V.bcmap +0 -0
  152. package/dist/assets/pdfjs/cmaps/UniCNS-UTF16-H.bcmap +0 -0
  153. package/dist/assets/pdfjs/cmaps/UniCNS-UTF16-V.bcmap +0 -0
  154. package/dist/assets/pdfjs/cmaps/UniCNS-UTF32-H.bcmap +0 -0
  155. package/dist/assets/pdfjs/cmaps/UniCNS-UTF32-V.bcmap +0 -0
  156. package/dist/assets/pdfjs/cmaps/UniCNS-UTF8-H.bcmap +0 -0
  157. package/dist/assets/pdfjs/cmaps/UniCNS-UTF8-V.bcmap +0 -0
  158. package/dist/assets/pdfjs/cmaps/UniGB-UCS2-H.bcmap +0 -0
  159. package/dist/assets/pdfjs/cmaps/UniGB-UCS2-V.bcmap +0 -0
  160. package/dist/assets/pdfjs/cmaps/UniGB-UTF16-H.bcmap +0 -0
  161. package/dist/assets/pdfjs/cmaps/UniGB-UTF16-V.bcmap +0 -0
  162. package/dist/assets/pdfjs/cmaps/UniGB-UTF32-H.bcmap +0 -0
  163. package/dist/assets/pdfjs/cmaps/UniGB-UTF32-V.bcmap +0 -0
  164. package/dist/assets/pdfjs/cmaps/UniGB-UTF8-H.bcmap +0 -0
  165. package/dist/assets/pdfjs/cmaps/UniGB-UTF8-V.bcmap +0 -0
  166. package/dist/assets/pdfjs/cmaps/UniJIS-UCS2-H.bcmap +0 -0
  167. package/dist/assets/pdfjs/cmaps/UniJIS-UCS2-HW-H.bcmap +0 -0
  168. package/dist/assets/pdfjs/cmaps/UniJIS-UCS2-HW-V.bcmap +0 -0
  169. package/dist/assets/pdfjs/cmaps/UniJIS-UCS2-V.bcmap +0 -0
  170. package/dist/assets/pdfjs/cmaps/UniJIS-UTF16-H.bcmap +0 -0
  171. package/dist/assets/pdfjs/cmaps/UniJIS-UTF16-V.bcmap +0 -0
  172. package/dist/assets/pdfjs/cmaps/UniJIS-UTF32-H.bcmap +0 -0
  173. package/dist/assets/pdfjs/cmaps/UniJIS-UTF32-V.bcmap +0 -0
  174. package/dist/assets/pdfjs/cmaps/UniJIS-UTF8-H.bcmap +0 -0
  175. package/dist/assets/pdfjs/cmaps/UniJIS-UTF8-V.bcmap +0 -0
  176. package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF16-H.bcmap +0 -0
  177. package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF16-V.bcmap +0 -0
  178. package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF32-H.bcmap +0 -0
  179. package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF32-V.bcmap +0 -0
  180. package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF8-H.bcmap +0 -0
  181. package/dist/assets/pdfjs/cmaps/UniJIS2004-UTF8-V.bcmap +0 -0
  182. package/dist/assets/pdfjs/cmaps/UniJISPro-UCS2-HW-V.bcmap +0 -0
  183. package/dist/assets/pdfjs/cmaps/UniJISPro-UCS2-V.bcmap +0 -0
  184. package/dist/assets/pdfjs/cmaps/UniJISPro-UTF8-V.bcmap +0 -0
  185. package/dist/assets/pdfjs/cmaps/UniJISX0213-UTF32-H.bcmap +0 -0
  186. package/dist/assets/pdfjs/cmaps/UniJISX0213-UTF32-V.bcmap +0 -0
  187. package/dist/assets/pdfjs/cmaps/UniJISX02132004-UTF32-H.bcmap +0 -0
  188. package/dist/assets/pdfjs/cmaps/UniJISX02132004-UTF32-V.bcmap +0 -0
  189. package/dist/assets/pdfjs/cmaps/UniKS-UCS2-H.bcmap +0 -0
  190. package/dist/assets/pdfjs/cmaps/UniKS-UCS2-V.bcmap +0 -0
  191. package/dist/assets/pdfjs/cmaps/UniKS-UTF16-H.bcmap +0 -0
  192. package/dist/assets/pdfjs/cmaps/UniKS-UTF16-V.bcmap +0 -0
  193. package/dist/assets/pdfjs/cmaps/UniKS-UTF32-H.bcmap +0 -0
  194. package/dist/assets/pdfjs/cmaps/UniKS-UTF32-V.bcmap +0 -0
  195. package/dist/assets/pdfjs/cmaps/UniKS-UTF8-H.bcmap +0 -0
  196. package/dist/assets/pdfjs/cmaps/UniKS-UTF8-V.bcmap +0 -0
  197. package/dist/assets/pdfjs/cmaps/V.bcmap +0 -0
  198. package/dist/assets/pdfjs/cmaps/WP-Symbol.bcmap +0 -0
  199. package/dist/assets/pdfjs/iccs/CGATS001Compat-v2-micro.icc +0 -0
  200. package/dist/assets/pdfjs/iccs/LICENSE +116 -0
  201. package/dist/assets/pdfjs/standard_fonts/FoxitDingbats.pfb +0 -0
  202. package/dist/assets/pdfjs/standard_fonts/FoxitFixed.pfb +0 -0
  203. package/dist/assets/pdfjs/standard_fonts/FoxitFixedBold.pfb +0 -0
  204. package/dist/assets/pdfjs/standard_fonts/FoxitFixedBoldItalic.pfb +0 -0
  205. package/dist/assets/pdfjs/standard_fonts/FoxitFixedItalic.pfb +0 -0
  206. package/dist/assets/pdfjs/standard_fonts/FoxitSerif.pfb +0 -0
  207. package/dist/assets/pdfjs/standard_fonts/FoxitSerifBold.pfb +0 -0
  208. package/dist/assets/pdfjs/standard_fonts/FoxitSerifBoldItalic.pfb +0 -0
  209. package/dist/assets/pdfjs/standard_fonts/FoxitSerifItalic.pfb +0 -0
  210. package/dist/assets/pdfjs/standard_fonts/FoxitSymbol.pfb +0 -0
  211. package/dist/assets/pdfjs/standard_fonts/LICENSE_FOXIT +27 -0
  212. package/dist/assets/pdfjs/standard_fonts/LICENSE_LIBERATION +102 -0
  213. package/dist/assets/pdfjs/standard_fonts/LiberationSans-Bold.ttf +0 -0
  214. package/dist/assets/pdfjs/standard_fonts/LiberationSans-BoldItalic.ttf +0 -0
  215. package/dist/assets/pdfjs/standard_fonts/LiberationSans-Italic.ttf +0 -0
  216. package/dist/assets/pdfjs/standard_fonts/LiberationSans-Regular.ttf +0 -0
  217. package/dist/assets/pdfjs/wasm/LICENSE_JBIG2 +196 -0
  218. package/dist/assets/pdfjs/wasm/LICENSE_OPENJPEG +39 -0
  219. package/dist/assets/pdfjs/wasm/LICENSE_PDFJS_JBIG2 +13 -0
  220. package/dist/assets/pdfjs/wasm/LICENSE_PDFJS_OPENJPEG +22 -0
  221. package/dist/assets/pdfjs/wasm/LICENSE_PDFJS_QCMS +22 -0
  222. package/dist/assets/pdfjs/wasm/LICENSE_QCMS +21 -0
  223. package/dist/assets/pdfjs/wasm/jbig2.wasm +0 -0
  224. package/dist/assets/pdfjs/wasm/jbig2_nowasm_fallback.js +15 -0
  225. package/dist/assets/pdfjs/wasm/openjpeg.wasm +0 -0
  226. package/dist/assets/pdfjs/wasm/openjpeg_nowasm_fallback.js +17 -0
  227. package/dist/assets/pdfjs/wasm/qcms_bg.wasm +0 -0
  228. package/dist/assets/pdfjs/wasm/quickjs-eval.js +16 -0
  229. package/dist/assets/pdfjs/wasm/quickjs-eval.wasm +0 -0
  230. package/dist/client.d.ts +20 -0
  231. package/dist/client.js +82 -0
  232. package/dist/contracts.d.ts +379 -0
  233. package/dist/contracts.js +22 -0
  234. package/dist/csv-worker.d.ts +1 -0
  235. package/dist/csv-worker.js +17 -0
  236. package/dist/detect.d.ts +15 -0
  237. package/dist/detect.js +290 -0
  238. package/dist/errors.d.ts +14 -0
  239. package/dist/errors.js +40 -0
  240. package/dist/font-manifest.d.ts +11 -0
  241. package/dist/font-manifest.js +31 -0
  242. package/dist/fonts/OFL-1.1.txt +88 -0
  243. package/dist/fonts/THIRD_PARTY_NOTICES.md +10 -0
  244. package/dist/fonts/manifest.json +83 -0
  245. package/dist/fonts/noto-sans-arabic.woff2 +0 -0
  246. package/dist/fonts/noto-sans-bengali.woff2 +0 -0
  247. package/dist/fonts/noto-sans-cjk.woff2 +0 -0
  248. package/dist/fonts/noto-sans-devanagari.woff2 +0 -0
  249. package/dist/fonts/noto-sans-gujarati.woff2 +0 -0
  250. package/dist/fonts/noto-sans-gurmukhi.woff2 +0 -0
  251. package/dist/fonts/noto-sans-japanese.woff2 +0 -0
  252. package/dist/fonts/noto-sans-kannada.woff2 +0 -0
  253. package/dist/fonts/noto-sans-korean.woff2 +0 -0
  254. package/dist/fonts/noto-sans-latin-cyrillic.woff2 +0 -0
  255. package/dist/fonts/noto-sans-malayalam.woff2 +0 -0
  256. package/dist/fonts/noto-sans-odia.woff2 +0 -0
  257. package/dist/fonts/noto-sans-tamil.woff2 +0 -0
  258. package/dist/fonts/noto-sans-telugu.woff2 +0 -0
  259. package/dist/fonts.d.ts +20 -0
  260. package/dist/fonts.js +238 -0
  261. package/dist/format.d.ts +1 -0
  262. package/dist/format.js +1 -0
  263. package/dist/headless.d.ts +18 -0
  264. package/dist/headless.js +18 -0
  265. package/dist/i18n.d.ts +4 -0
  266. package/dist/i18n.js +55 -0
  267. package/dist/image-worker.d.ts +1 -0
  268. package/dist/image-worker.js +41 -0
  269. package/dist/index.d.ts +27 -0
  270. package/dist/index.js +29 -0
  271. package/dist/interaction.d.ts +24 -0
  272. package/dist/interaction.js +183 -0
  273. package/dist/legacy-converter-worker.d.ts +1 -0
  274. package/dist/legacy-converter-worker.js +19 -0
  275. package/dist/limits.d.ts +4 -0
  276. package/dist/limits.js +162 -0
  277. package/dist/registry.d.ts +8 -0
  278. package/dist/registry.js +35 -0
  279. package/dist/render-scheduler.d.ts +8 -0
  280. package/dist/render-scheduler.js +63 -0
  281. package/dist/source.d.ts +14 -0
  282. package/dist/source.js +116 -0
  283. package/dist/spreadsheet-viewport.d.ts +34 -0
  284. package/dist/spreadsheet-viewport.js +1035 -0
  285. package/dist/styles.css +137 -0
  286. package/dist/ui-styles.d.ts +1 -0
  287. package/dist/ui-styles.js +139 -0
  288. package/dist/ui.d.ts +8 -0
  289. package/dist/ui.js +390 -0
  290. package/dist/viewer.d.ts +52 -0
  291. package/dist/viewer.js +901 -0
  292. package/dist/viewport.d.ts +54 -0
  293. package/dist/viewport.js +907 -0
  294. package/dist/worker-adapter.d.ts +24 -0
  295. package/dist/worker-adapter.js +97 -0
  296. package/dist/worker-client.d.ts +23 -0
  297. package/dist/worker-client.js +105 -0
  298. package/dist/worker-endpoint.d.ts +13 -0
  299. package/dist/worker-endpoint.js +57 -0
  300. package/dist/worker-protocol.d.ts +48 -0
  301. package/dist/worker-protocol.js +14 -0
  302. package/dist/worker.d.ts +4 -0
  303. package/dist/worker.js +4 -0
  304. package/dist/workers/csv-worker.js +160 -0
  305. package/dist/workers/image-worker.js +41 -0
  306. package/dist/workers/legacy-converter-worker.js +19 -0
  307. package/dist/workers/pdf.worker.min.mjs +28 -0
  308. package/package.json +74 -0
@@ -0,0 +1,1035 @@
1
+ import { normalizeCellRange } from "./interaction.js";
2
+ const DEFAULT_COLUMN_WIDTH = 64;
3
+ const DEFAULT_ROW_HEIGHT = 20;
4
+ const DEFAULT_ROW_HEADER_WIDTH = 50;
5
+ const DEFAULT_COLUMN_HEADER_HEIGHT = 22;
6
+ const OVERSCAN = 2;
7
+ const TRAILING_COLUMNS = 2;
8
+ const TRAILING_ROWS = 2;
9
+ const COLUMN_RESIZE_GRAB_PX = 5;
10
+ const MIN_COLUMN_WIDTH = 24;
11
+ const MAX_COLUMN_WIDTH = 2_000;
12
+ export class AxisGeometry {
13
+ #count;
14
+ #defaultSize;
15
+ #indices;
16
+ #sizes;
17
+ #prefixDeltas;
18
+ constructor(count, defaultSize, overrides = {}) {
19
+ this.#count = Math.max(0, Math.trunc(count));
20
+ this.#defaultSize = nonNegative(defaultSize, 1);
21
+ const entries = Object.entries(overrides)
22
+ .map(([rawIndex, rawSize]) => [Number(rawIndex), Number(rawSize)])
23
+ .filter(([index, size]) => Number.isInteger(index) &&
24
+ index >= 1 &&
25
+ index <= this.#count &&
26
+ Number.isFinite(size) &&
27
+ size >= 0)
28
+ .sort(([left], [right]) => left - right);
29
+ this.#indices = entries.map(([index]) => index);
30
+ this.#sizes = entries.map(([, size]) => size);
31
+ const prefix = [0];
32
+ for (const size of this.#sizes)
33
+ prefix.push(prefix[prefix.length - 1] + size - this.#defaultSize);
34
+ this.#prefixDeltas = prefix;
35
+ }
36
+ get count() {
37
+ return this.#count;
38
+ }
39
+ get totalSize() {
40
+ return this.offsetOf(this.#count + 1);
41
+ }
42
+ sizeOf(index) {
43
+ const normalized = Math.max(1, Math.min(this.#count, Math.trunc(index)));
44
+ const position = lowerBound(this.#indices, normalized);
45
+ return this.#indices[position] === normalized
46
+ ? this.#sizes[position]
47
+ : this.#defaultSize;
48
+ }
49
+ /** Offset of a 1-based band; count + 1 returns the full extent. */
50
+ offsetOf(index) {
51
+ const normalized = Math.max(1, Math.min(this.#count + 1, Math.trunc(index)));
52
+ const overridesBefore = lowerBound(this.#indices, normalized);
53
+ return ((normalized - 1) * this.#defaultSize +
54
+ this.#prefixDeltas[overridesBefore]);
55
+ }
56
+ /** Band containing an unscaled logical offset. Hidden zero-sized bands skip. */
57
+ indexAt(offset) {
58
+ if (this.#count <= 0)
59
+ return 1;
60
+ const target = Math.max(0, Math.min(this.totalSize, offset));
61
+ let low = 1;
62
+ let high = this.#count;
63
+ while (low < high) {
64
+ const middle = Math.ceil((low + high) / 2);
65
+ if (this.offsetOf(middle) <= target)
66
+ low = middle;
67
+ else
68
+ high = middle - 1;
69
+ }
70
+ while (low < this.#count && this.sizeOf(low) === 0)
71
+ low += 1;
72
+ return low;
73
+ }
74
+ }
75
+ export class SpreadsheetViewport {
76
+ #host;
77
+ #container;
78
+ #root;
79
+ #spacer;
80
+ #canvas;
81
+ #selectionLayer;
82
+ #searchLayer;
83
+ #searchBoxes = [];
84
+ #selectionBoxes = [];
85
+ #onScroll = () => this.#handleScroll();
86
+ #onWheel = (event) => this.#handleWheel(event);
87
+ #onPointerDown = (event) => this.#handlePointerDown(event);
88
+ #onPointerMove = (event) => this.#handlePointerMove(event);
89
+ #onPointerUp = (event) => this.#handlePointerUp(event);
90
+ #onKeyDown = (event) => this.#handleKeyDown(event);
91
+ #onCopy = (event) => this.#handleCopy(event);
92
+ #sheetScroll = new Map();
93
+ #columnWidthOverrides = new Map();
94
+ #info;
95
+ #columns = new AxisGeometry(0, DEFAULT_COLUMN_WIDTH);
96
+ #rows = new AxisGeometry(0, DEFAULT_ROW_HEIGHT);
97
+ #sheet;
98
+ #sheetIndex = 0;
99
+ #frame = 0;
100
+ #generation = 0;
101
+ #controller;
102
+ #resizeObserver;
103
+ #destroyed = false;
104
+ #renderKey;
105
+ #appliedZoom;
106
+ #zoomAnchor;
107
+ #panPointer;
108
+ #cellPointerId;
109
+ #cellAnchor;
110
+ #cellFocus;
111
+ #cellBaseRanges = [];
112
+ #columnResizeDrag;
113
+ #searchCells = [];
114
+ #searchKey = "";
115
+ #searchGeneration = 0;
116
+ constructor(container, host) {
117
+ this.#container = container;
118
+ this.#host = host;
119
+ this.#appliedZoom = host.state.zoom;
120
+ this.#root = document.createElement("div");
121
+ this.#root.dataset.zrimo = "spreadsheet-viewport";
122
+ this.#root.tabIndex = 0;
123
+ this.#root.setAttribute("role", "application");
124
+ this.#root.setAttribute("aria-label", "Spreadsheet viewport");
125
+ Object.assign(this.#root.style, {
126
+ position: "relative",
127
+ overflow: "auto",
128
+ width: "100%",
129
+ height: "100%",
130
+ minHeight: "160px",
131
+ background: "var(--zrimo-background, #e9edf2)",
132
+ touchAction: "none",
133
+ contain: "strict",
134
+ });
135
+ this.#spacer = document.createElement("div");
136
+ Object.assign(this.#spacer.style, {
137
+ position: "relative",
138
+ width: "1px",
139
+ height: "1px",
140
+ });
141
+ this.#canvas = document.createElement("canvas");
142
+ this.#canvas.dataset.zrimoLayer = "spreadsheet-canvas";
143
+ Object.assign(this.#canvas.style, {
144
+ position: "absolute",
145
+ left: "0",
146
+ top: "0",
147
+ display: "block",
148
+ pointerEvents: "none",
149
+ background: "white",
150
+ });
151
+ this.#selectionLayer = document.createElement("div");
152
+ this.#selectionLayer.dataset.zrimoLayer = "cell-selection";
153
+ Object.assign(this.#selectionLayer.style, {
154
+ position: "sticky",
155
+ left: "0",
156
+ top: "0",
157
+ width: "0",
158
+ height: "0",
159
+ cursor: "cell",
160
+ userSelect: "none",
161
+ overflow: "hidden",
162
+ });
163
+ this.#searchLayer = document.createElement("div");
164
+ this.#searchLayer.dataset.zrimoLayer = "spreadsheet-search";
165
+ Object.assign(this.#searchLayer.style, {
166
+ position: "absolute",
167
+ left: "0",
168
+ top: "0",
169
+ pointerEvents: "none",
170
+ overflow: "hidden",
171
+ });
172
+ this.#selectionLayer.append(this.#canvas, this.#searchLayer);
173
+ this.#selectionBoxes.push(this.#createSelectionBox());
174
+ this.#spacer.append(this.#selectionLayer);
175
+ this.#root.append(this.#spacer);
176
+ this.#container.append(this.#root);
177
+ this.#root.addEventListener("scroll", this.#onScroll, { passive: true });
178
+ this.#root.addEventListener("wheel", this.#onWheel, { passive: false });
179
+ this.#selectionLayer.addEventListener("pointerdown", this.#onPointerDown);
180
+ this.#selectionLayer.addEventListener("pointermove", this.#onPointerMove);
181
+ this.#selectionLayer.addEventListener("pointerup", this.#onPointerUp);
182
+ this.#selectionLayer.addEventListener("pointercancel", this.#onPointerUp);
183
+ this.#root.addEventListener("keydown", this.#onKeyDown);
184
+ document.addEventListener("copy", this.#onCopy);
185
+ if (typeof ResizeObserver !== "undefined") {
186
+ this.#resizeObserver = new ResizeObserver(() => this.schedule());
187
+ this.#resizeObserver.observe(this.#root);
188
+ }
189
+ }
190
+ setDocument(info) {
191
+ this.#controller?.abort();
192
+ this.#generation += 1;
193
+ this.#info = info?.unit === "sheet" ? info : undefined;
194
+ this.#sheetScroll.clear();
195
+ this.#columnWidthOverrides.clear();
196
+ this.#columnResizeDrag = undefined;
197
+ this.#resetSearchHighlights();
198
+ this.#resetCellSelection();
199
+ this.#sheetIndex = this.#host.state.pageIndex;
200
+ this.#appliedZoom = this.#host.state.zoom;
201
+ this.#renderKey = undefined;
202
+ this.#setSheetGeometry();
203
+ this.#root.scrollTo({ left: 0, top: 0 });
204
+ this.schedule();
205
+ }
206
+ update() {
207
+ if (!this.#info)
208
+ return;
209
+ const nextSheet = this.#host.state.pageIndex;
210
+ if (nextSheet !== this.#sheetIndex) {
211
+ this.#sheetScroll.set(this.#sheetIndex, {
212
+ left: this.#root.scrollLeft,
213
+ top: this.#root.scrollTop,
214
+ });
215
+ this.#sheetIndex = nextSheet;
216
+ this.#renderKey = undefined;
217
+ this.#resetCellSelection();
218
+ this.#host.onCellSelection(null);
219
+ this.#setSheetGeometry();
220
+ const saved = this.#sheetScroll.get(nextSheet);
221
+ this.#root.scrollTo({ left: saved?.left ?? 0, top: saved?.top ?? 0 });
222
+ }
223
+ const zoom = this.#host.state.zoom;
224
+ if (zoom !== this.#appliedZoom) {
225
+ const anchor = this.#zoomAnchor ?? { x: 0, y: 0 };
226
+ const logicalX = (this.#root.scrollLeft + anchor.x) / this.#appliedZoom;
227
+ const logicalY = (this.#root.scrollTop + anchor.y) / this.#appliedZoom;
228
+ this.#appliedZoom = zoom;
229
+ this.#ensureViewportGeometry();
230
+ this.#updateExtent();
231
+ this.#root.scrollLeft = logicalX * zoom - anchor.x;
232
+ this.#root.scrollTop = logicalY * zoom - anchor.y;
233
+ this.#zoomAnchor = undefined;
234
+ this.#renderKey = undefined;
235
+ }
236
+ this.schedule();
237
+ }
238
+ panBy(deltaX, deltaY) {
239
+ this.#root.scrollLeft += deltaX;
240
+ this.#root.scrollTop += deltaY;
241
+ this.#reportPan();
242
+ this.schedule();
243
+ }
244
+ goToPage(pageIndex) {
245
+ if (pageIndex === this.#sheetIndex)
246
+ return;
247
+ this.update();
248
+ }
249
+ fitWidth() {
250
+ const usedColumns = this.#usedColumns();
251
+ const naturalWidth = this.#rowHeaderWidth() + Math.max(1, usedColumns.totalSize);
252
+ const zoom = clampZoom((this.#root.clientWidth - 2) / naturalWidth);
253
+ if (zoom !== this.#appliedZoom)
254
+ this.#zoomAnchor = { x: 0, y: 0 };
255
+ return zoom;
256
+ }
257
+ fitPage() {
258
+ const usedColumns = this.#usedColumns();
259
+ const usedRows = this.#usedRows();
260
+ const naturalWidth = this.#rowHeaderWidth() + Math.max(1, usedColumns.totalSize);
261
+ const naturalHeight = this.#columnHeaderHeight() + Math.max(1, usedRows.totalSize);
262
+ const zoom = clampZoom(Math.min((this.#root.clientWidth - 2) / naturalWidth, (this.#root.clientHeight - 2) / naturalHeight));
263
+ if (zoom !== this.#appliedZoom)
264
+ this.#zoomAnchor = { x: 0, y: 0 };
265
+ return zoom;
266
+ }
267
+ schedule() {
268
+ if (this.#destroyed || this.#frame)
269
+ return;
270
+ this.#frame = requestAnimationFrame(() => {
271
+ this.#frame = 0;
272
+ void this.#renderVisible();
273
+ });
274
+ }
275
+ destroy() {
276
+ if (this.#destroyed)
277
+ return;
278
+ this.#destroyed = true;
279
+ this.#searchGeneration += 1;
280
+ this.#controller?.abort();
281
+ if (this.#frame)
282
+ cancelAnimationFrame(this.#frame);
283
+ this.#resizeObserver?.disconnect();
284
+ this.#root.removeEventListener("scroll", this.#onScroll);
285
+ this.#root.removeEventListener("wheel", this.#onWheel);
286
+ this.#selectionLayer.removeEventListener("pointerdown", this.#onPointerDown);
287
+ this.#selectionLayer.removeEventListener("pointermove", this.#onPointerMove);
288
+ this.#selectionLayer.removeEventListener("pointerup", this.#onPointerUp);
289
+ this.#selectionLayer.removeEventListener("pointercancel", this.#onPointerUp);
290
+ this.#root.removeEventListener("keydown", this.#onKeyDown);
291
+ document.removeEventListener("copy", this.#onCopy);
292
+ this.#root.remove();
293
+ }
294
+ async #renderVisible() {
295
+ const info = this.#info;
296
+ const sheet = this.#sheet;
297
+ if (!info ||
298
+ !sheet ||
299
+ this.#host.state.status !== "ready" ||
300
+ this.#root.clientWidth <= 0 ||
301
+ this.#root.clientHeight <= 0)
302
+ return;
303
+ this.#ensureViewportGeometry();
304
+ this.#updateExtent();
305
+ await this.#syncSearchHighlights();
306
+ if (this.#destroyed || this.#sheetIndex !== this.#host.state.pageIndex)
307
+ return;
308
+ const render = this.#visibleRange();
309
+ const width = this.#root.clientWidth;
310
+ const height = this.#root.clientHeight;
311
+ const zoom = this.#host.state.zoom;
312
+ const dpr = window.devicePixelRatio || 1;
313
+ const key = [
314
+ this.#sheetIndex,
315
+ render.range.row,
316
+ render.range.column,
317
+ render.range.rowCount,
318
+ render.range.columnCount,
319
+ render.offsetX.toFixed(3),
320
+ render.offsetY.toFixed(3),
321
+ width,
322
+ height,
323
+ zoom,
324
+ dpr,
325
+ ].join(":");
326
+ this.#sizeLayers(width, height);
327
+ this.#paintSearchHighlights();
328
+ this.#paintSelection();
329
+ if (key === this.#renderKey)
330
+ return;
331
+ this.#renderKey = key;
332
+ this.#controller?.abort();
333
+ const controller = new AbortController();
334
+ this.#controller = controller;
335
+ const generation = ++this.#generation;
336
+ const frame = document.createElement("canvas");
337
+ try {
338
+ await this.#host.renderSheetViewport(this.#sheetIndex, frame, render.range, {
339
+ width,
340
+ height,
341
+ zoom,
342
+ devicePixelRatio: dpr,
343
+ scrollOffsetX: render.offsetX,
344
+ scrollOffsetY: render.offsetY,
345
+ columnWidths: this.#currentColumnWidthOverrides(),
346
+ priority: "visible",
347
+ signal: controller.signal,
348
+ });
349
+ if (controller.signal.aborted ||
350
+ generation !== this.#generation ||
351
+ this.#destroyed)
352
+ return;
353
+ this.#canvas.width = frame.width;
354
+ this.#canvas.height = frame.height;
355
+ const context = this.#canvas.getContext("2d");
356
+ context?.clearRect(0, 0, frame.width, frame.height);
357
+ context?.drawImage(frame, 0, 0);
358
+ delete this.#root.dataset.renderError;
359
+ }
360
+ catch (error) {
361
+ if (!controller.signal.aborted && generation === this.#generation)
362
+ this.#root.dataset.renderError =
363
+ error instanceof Error ? error.message : String(error);
364
+ }
365
+ }
366
+ #visibleRange() {
367
+ const zoom = this.#host.state.zoom;
368
+ const freezeColumns = Math.min(this.#columns.count, Math.max(0, this.#sheet?.frozenColumns ?? 0));
369
+ const freezeRows = Math.min(this.#rows.count, Math.max(0, this.#sheet?.frozenRows ?? 0));
370
+ const frozenWidth = this.#columns.offsetOf(freezeColumns + 1);
371
+ const frozenHeight = this.#rows.offsetOf(freezeRows + 1);
372
+ const logicalLeft = this.#root.scrollLeft / zoom;
373
+ const logicalTop = this.#root.scrollTop / zoom;
374
+ const startColumn = Math.max(freezeColumns + 1, this.#columns.indexAt(logicalLeft + frozenWidth));
375
+ const startRow = Math.max(freezeRows + 1, this.#rows.indexAt(logicalTop + frozenHeight));
376
+ const offsetX = Math.max(0, logicalLeft + frozenWidth - this.#columns.offsetOf(startColumn));
377
+ const offsetY = Math.max(0, logicalTop + frozenHeight - this.#rows.offsetOf(startRow));
378
+ const naturalWidth = this.#root.clientWidth / zoom - this.#rowHeaderWidth() - frozenWidth;
379
+ const naturalHeight = this.#root.clientHeight / zoom -
380
+ this.#columnHeaderHeight() -
381
+ frozenHeight;
382
+ const endColumn = this.#columns.indexAt(this.#columns.offsetOf(startColumn) + offsetX + Math.max(0, naturalWidth));
383
+ const endRow = this.#rows.indexAt(this.#rows.offsetOf(startRow) + offsetY + Math.max(0, naturalHeight));
384
+ return {
385
+ range: {
386
+ row: startRow,
387
+ column: startColumn,
388
+ rowCount: Math.max(1, Math.min(this.#rows.count - startRow + 1, endRow - startRow + 1 + OVERSCAN)),
389
+ columnCount: Math.max(1, Math.min(this.#columns.count - startColumn + 1, endColumn - startColumn + 1 + OVERSCAN)),
390
+ },
391
+ offsetX,
392
+ offsetY,
393
+ };
394
+ }
395
+ #setSheetGeometry() {
396
+ this.#sheet = this.#info?.sheets?.[this.#sheetIndex];
397
+ this.#columns = new AxisGeometry(0, DEFAULT_COLUMN_WIDTH);
398
+ this.#rows = new AxisGeometry(0, DEFAULT_ROW_HEIGHT);
399
+ this.#ensureViewportGeometry();
400
+ this.#updateExtent();
401
+ }
402
+ #ensureViewportGeometry() {
403
+ const sheet = this.#sheet;
404
+ const zoom = Math.max(0.1, this.#host.state.zoom);
405
+ const defaultColumnWidth = sheet?.defaultColumnWidth ?? DEFAULT_COLUMN_WIDTH;
406
+ const defaultRowHeight = sheet?.defaultRowHeight ?? DEFAULT_ROW_HEIGHT;
407
+ const viewportColumns = Math.ceil(Math.max(0, this.#root.clientWidth / zoom - this.#rowHeaderWidth()) /
408
+ Math.max(1, defaultColumnWidth));
409
+ const viewportRows = Math.ceil(Math.max(0, this.#root.clientHeight / zoom - this.#columnHeaderHeight()) /
410
+ Math.max(1, defaultRowHeight));
411
+ const columnCount = Math.max(1, sheet?.maxColumn ?? 1, viewportColumns + TRAILING_COLUMNS);
412
+ const rowCount = Math.max(1, sheet?.maxRow ?? 1, viewportRows + TRAILING_ROWS);
413
+ if (this.#columns.count !== columnCount)
414
+ this.#columns = new AxisGeometry(columnCount, defaultColumnWidth, this.#effectiveColumnWidths());
415
+ if (this.#rows.count !== rowCount)
416
+ this.#rows = new AxisGeometry(rowCount, defaultRowHeight, sheet?.rowHeights);
417
+ }
418
+ #usedColumns() {
419
+ return new AxisGeometry(Math.max(1, this.#sheet?.maxColumn ?? 1), this.#sheet?.defaultColumnWidth ?? DEFAULT_COLUMN_WIDTH, this.#effectiveColumnWidths());
420
+ }
421
+ #usedRows() {
422
+ return new AxisGeometry(Math.max(1, this.#sheet?.maxRow ?? 1), this.#sheet?.defaultRowHeight ?? DEFAULT_ROW_HEIGHT, this.#sheet?.rowHeights);
423
+ }
424
+ #updateExtent() {
425
+ const zoom = this.#host.state.zoom;
426
+ this.#spacer.style.width = `${Math.max(1, (this.#rowHeaderWidth() + this.#columns.totalSize) * zoom)}px`;
427
+ this.#spacer.style.height = `${Math.max(1, (this.#columnHeaderHeight() + this.#rows.totalSize) * zoom)}px`;
428
+ }
429
+ #sizeLayers(width, height) {
430
+ for (const layer of [
431
+ this.#canvas,
432
+ this.#selectionLayer,
433
+ this.#searchLayer,
434
+ ]) {
435
+ layer.style.width = `${width}px`;
436
+ layer.style.height = `${height}px`;
437
+ }
438
+ }
439
+ #handleScroll() {
440
+ this.#reportPan();
441
+ this.#paintSearchHighlights();
442
+ this.#paintSelection();
443
+ this.schedule();
444
+ }
445
+ #handleWheel(event) {
446
+ if (!event.ctrlKey && !event.metaKey)
447
+ return;
448
+ event.preventDefault();
449
+ const bounds = this.#root.getBoundingClientRect();
450
+ this.#zoomAnchor = {
451
+ x: event.clientX - bounds.left,
452
+ y: event.clientY - bounds.top,
453
+ };
454
+ this.#host.onZoom(this.#host.state.zoom * Math.exp(-event.deltaY * 0.002));
455
+ }
456
+ #handlePointerDown(event) {
457
+ if (event.button !== 0)
458
+ return;
459
+ this.#root.focus({ preventScroll: true });
460
+ const resizeTarget = this.#columnResizeTargetAt(event.clientX, event.clientY);
461
+ if (resizeTarget) {
462
+ event.preventDefault();
463
+ this.#columnResizeDrag = {
464
+ ...resizeTarget,
465
+ pointerId: event.pointerId,
466
+ startClientX: event.clientX,
467
+ };
468
+ this.#selectionLayer.style.cursor = "col-resize";
469
+ this.#capturePointer(event.pointerId);
470
+ return;
471
+ }
472
+ const cell = this.#cellAt(event.clientX, event.clientY);
473
+ if (cell) {
474
+ event.preventDefault();
475
+ const additive = event.ctrlKey || event.metaKey;
476
+ if (event.shiftKey && this.#cellAnchor) {
477
+ this.#cellFocus = cell;
478
+ this.#cellPointerId = event.pointerId;
479
+ }
480
+ else if (additive) {
481
+ const current = this.#selectionRanges();
482
+ if (current.some((range) => cellInRange(cell, range))) {
483
+ this.#cellBaseRanges = current.flatMap((range) => subtractCell(range, cell));
484
+ this.#cellAnchor = undefined;
485
+ this.#cellFocus = undefined;
486
+ this.#cellPointerId = undefined;
487
+ }
488
+ else {
489
+ this.#cellBaseRanges = current;
490
+ this.#cellAnchor = cell;
491
+ this.#cellFocus = cell;
492
+ this.#cellPointerId = event.pointerId;
493
+ }
494
+ }
495
+ else {
496
+ this.#cellBaseRanges = [];
497
+ this.#cellAnchor = cell;
498
+ this.#cellFocus = cell;
499
+ this.#cellPointerId = event.pointerId;
500
+ }
501
+ this.#emitSelection();
502
+ }
503
+ else {
504
+ this.#panPointer = {
505
+ id: event.pointerId,
506
+ x: event.clientX,
507
+ y: event.clientY,
508
+ };
509
+ }
510
+ this.#capturePointer(event.pointerId);
511
+ }
512
+ #handlePointerMove(event) {
513
+ const resize = this.#columnResizeDrag;
514
+ if (resize?.pointerId === event.pointerId) {
515
+ event.preventDefault();
516
+ const width = Math.max(MIN_COLUMN_WIDTH, Math.min(MAX_COLUMN_WIDTH, resize.width +
517
+ (event.clientX - resize.startClientX) / this.#host.state.zoom));
518
+ this.#resizeColumn(resize.column, width);
519
+ return;
520
+ }
521
+ if (this.#cellPointerId === event.pointerId && this.#cellAnchor) {
522
+ const cell = this.#cellAt(event.clientX, event.clientY);
523
+ if (cell) {
524
+ this.#cellFocus = cell;
525
+ this.#emitSelection();
526
+ }
527
+ return;
528
+ }
529
+ if (!this.#panPointer) {
530
+ this.#selectionLayer.style.cursor = this.#columnResizeTargetAt(event.clientX, event.clientY)
531
+ ? "col-resize"
532
+ : "cell";
533
+ }
534
+ const pointer = this.#panPointer;
535
+ if (!pointer || pointer.id !== event.pointerId)
536
+ return;
537
+ this.panBy(pointer.x - event.clientX, pointer.y - event.clientY);
538
+ this.#panPointer = { id: pointer.id, x: event.clientX, y: event.clientY };
539
+ }
540
+ #handlePointerUp(event) {
541
+ if (this.#columnResizeDrag?.pointerId === event.pointerId) {
542
+ this.#columnResizeDrag = undefined;
543
+ this.#selectionLayer.style.cursor = "cell";
544
+ }
545
+ if (this.#cellPointerId === event.pointerId)
546
+ this.#cellPointerId = undefined;
547
+ if (this.#panPointer?.id === event.pointerId)
548
+ this.#panPointer = undefined;
549
+ this.#releasePointer(event.pointerId);
550
+ }
551
+ #handleKeyDown(event) {
552
+ const delta = cellKeyDelta(event.key);
553
+ if (delta && this.#cellFocus) {
554
+ event.preventDefault();
555
+ const focus = {
556
+ row: Math.max(1, Math.min(this.#rows.count, this.#cellFocus.row + delta.row)),
557
+ column: Math.max(1, Math.min(this.#columns.count, this.#cellFocus.column + delta.column)),
558
+ };
559
+ if (!event.shiftKey) {
560
+ this.#cellBaseRanges = [];
561
+ this.#cellAnchor = focus;
562
+ }
563
+ this.#cellFocus = focus;
564
+ this.#scrollCellIntoView(focus);
565
+ this.#emitSelection();
566
+ return;
567
+ }
568
+ const step = Math.max(48, this.#root.clientHeight * 0.9);
569
+ switch (event.key) {
570
+ case "PageDown":
571
+ event.preventDefault();
572
+ this.panBy(0, step);
573
+ break;
574
+ case "PageUp":
575
+ event.preventDefault();
576
+ this.panBy(0, -step);
577
+ break;
578
+ case "ArrowDown":
579
+ event.preventDefault();
580
+ this.panBy(0, 48);
581
+ break;
582
+ case "ArrowUp":
583
+ event.preventDefault();
584
+ this.panBy(0, -48);
585
+ break;
586
+ case "ArrowRight":
587
+ event.preventDefault();
588
+ this.panBy(48, 0);
589
+ break;
590
+ case "ArrowLeft":
591
+ event.preventDefault();
592
+ this.panBy(-48, 0);
593
+ break;
594
+ }
595
+ }
596
+ #handleCopy(event) {
597
+ if (document.activeElement !== this.#root &&
598
+ !this.#root.contains(document.activeElement))
599
+ return;
600
+ const text = this.#host.getSelectionText();
601
+ if (text === undefined)
602
+ return;
603
+ if (event.clipboardData) {
604
+ event.preventDefault();
605
+ event.clipboardData.setData("text/plain", text);
606
+ return;
607
+ }
608
+ void globalThis.navigator?.clipboard?.writeText(text).catch(() => { });
609
+ }
610
+ #cellAt(clientX, clientY) {
611
+ const bounds = this.#root.getBoundingClientRect();
612
+ const zoom = this.#host.state.zoom;
613
+ const x = clientX - bounds.left - this.#rowHeaderWidth() * zoom;
614
+ const y = clientY - bounds.top - this.#columnHeaderHeight() * zoom;
615
+ if (x < 0 || y < 0)
616
+ return undefined;
617
+ const freezeColumns = Math.max(0, this.#sheet?.frozenColumns ?? 0);
618
+ const freezeRows = Math.max(0, this.#sheet?.frozenRows ?? 0);
619
+ const frozenWidth = this.#columns.offsetOf(freezeColumns + 1);
620
+ const frozenHeight = this.#rows.offsetOf(freezeRows + 1);
621
+ const logicalX = x / zoom < frozenWidth
622
+ ? x / zoom
623
+ : this.#root.scrollLeft / zoom + x / zoom;
624
+ const logicalY = y / zoom < frozenHeight
625
+ ? y / zoom
626
+ : this.#root.scrollTop / zoom + y / zoom;
627
+ return {
628
+ row: this.#rows.indexAt(logicalY),
629
+ column: this.#columns.indexAt(logicalX),
630
+ };
631
+ }
632
+ #columnResizeTargetAt(clientX, clientY) {
633
+ if (!this.#sheet || this.#columns.count === 0)
634
+ return undefined;
635
+ const bounds = this.#root.getBoundingClientRect();
636
+ const zoom = this.#host.state.zoom;
637
+ const localY = clientY - bounds.top;
638
+ if (localY < 0 || localY > this.#columnHeaderHeight() * zoom)
639
+ return undefined;
640
+ const gridX = clientX - bounds.left - this.#rowHeaderWidth() * zoom;
641
+ if (gridX <= 0)
642
+ return undefined;
643
+ const freezeColumns = Math.max(0, this.#sheet.frozenColumns);
644
+ const frozenWidth = this.#columns.offsetOf(freezeColumns + 1);
645
+ const logicalX = gridX / zoom < frozenWidth
646
+ ? gridX / zoom
647
+ : this.#root.scrollLeft / zoom + gridX / zoom;
648
+ const hitColumn = this.#columns.indexAt(logicalX);
649
+ for (const column of [hitColumn - 1, hitColumn]) {
650
+ if (column < 1 || column > this.#columns.count)
651
+ continue;
652
+ const naturalEdge = this.#columns.offsetOf(column + 1);
653
+ const scrollOffset = column <= freezeColumns ? 0 : this.#root.scrollLeft / zoom;
654
+ const edge = this.#rowHeaderWidth() * zoom + (naturalEdge - scrollOffset) * zoom;
655
+ if (Math.abs(clientX - bounds.left - edge) <= COLUMN_RESIZE_GRAB_PX)
656
+ return { column, width: this.#columns.sizeOf(column) };
657
+ }
658
+ return undefined;
659
+ }
660
+ #resizeColumn(column, width) {
661
+ const overrides = this.#currentColumnWidthOverrides(true);
662
+ overrides[column] = Math.round(width * 10) / 10;
663
+ this.#columns = new AxisGeometry(this.#columns.count, this.#sheet?.defaultColumnWidth ?? DEFAULT_COLUMN_WIDTH, this.#effectiveColumnWidths());
664
+ this.#controller?.abort();
665
+ this.#renderKey = undefined;
666
+ this.#updateExtent();
667
+ this.#paintSearchHighlights();
668
+ this.#paintSelection();
669
+ this.schedule();
670
+ }
671
+ #effectiveColumnWidths() {
672
+ return {
673
+ ...(this.#sheet?.columnWidths ?? {}),
674
+ ...this.#currentColumnWidthOverrides(),
675
+ };
676
+ }
677
+ #currentColumnWidthOverrides(create = false) {
678
+ const current = this.#columnWidthOverrides.get(this.#sheetIndex);
679
+ if (current || !create)
680
+ return current ?? {};
681
+ const overrides = {};
682
+ this.#columnWidthOverrides.set(this.#sheetIndex, overrides);
683
+ return overrides;
684
+ }
685
+ #capturePointer(pointerId) {
686
+ try {
687
+ this.#selectionLayer.setPointerCapture(pointerId);
688
+ }
689
+ catch {
690
+ // Synthetic events may not expose an active pointer.
691
+ }
692
+ }
693
+ #releasePointer(pointerId) {
694
+ try {
695
+ if (this.#selectionLayer.hasPointerCapture(pointerId))
696
+ this.#selectionLayer.releasePointerCapture(pointerId);
697
+ }
698
+ catch {
699
+ // Pointer may already have been released.
700
+ }
701
+ }
702
+ #emitSelection() {
703
+ const ranges = this.#selectionRanges();
704
+ const selection = ranges.length === 0
705
+ ? null
706
+ : ranges.length === 1
707
+ ? ranges[0]
708
+ : { sheetIndex: this.#sheetIndex, ranges };
709
+ this.#host.onCellSelection(selection);
710
+ this.#paintSelection();
711
+ }
712
+ #paintSelection() {
713
+ const ranges = this.#selectionRanges();
714
+ while (this.#selectionBoxes.length < ranges.length)
715
+ this.#selectionBoxes.push(this.#createSelectionBox());
716
+ this.#selectionBoxes.forEach((box, index) => {
717
+ const range = ranges[index];
718
+ if (!range) {
719
+ box.style.display = "none";
720
+ return;
721
+ }
722
+ const topLeft = this.#cellPosition(range.startRow, range.startColumn);
723
+ const bottomRight = this.#cellPosition(range.endRow + 1, range.endColumn + 1);
724
+ Object.assign(box.style, {
725
+ display: "block",
726
+ left: `${topLeft.x}px`,
727
+ top: `${topLeft.y}px`,
728
+ width: `${Math.max(1, bottomRight.x - topLeft.x)}px`,
729
+ height: `${Math.max(1, bottomRight.y - topLeft.y)}px`,
730
+ });
731
+ });
732
+ }
733
+ async #syncSearchHighlights() {
734
+ const sheetIndex = this.#sheetIndex;
735
+ const matches = this.#host.getSearchMatches(sheetIndex);
736
+ const currentActive = this.#host.getActiveSearchMatch();
737
+ const active = currentActive?.pageIndex === sheetIndex ? currentActive : undefined;
738
+ const key = spreadsheetSearchKey(matches, active);
739
+ if (key === this.#searchKey)
740
+ return;
741
+ const generation = ++this.#searchGeneration;
742
+ if (matches.length === 0) {
743
+ this.#searchKey = key;
744
+ this.#searchCells = [];
745
+ this.#paintSearchHighlights();
746
+ return;
747
+ }
748
+ const runs = await this.#host.getTextRuns(sheetIndex);
749
+ const latestActive = this.#host.getActiveSearchMatch();
750
+ if (this.#destroyed ||
751
+ generation !== this.#searchGeneration ||
752
+ sheetIndex !== this.#sheetIndex ||
753
+ key !==
754
+ spreadsheetSearchKey(this.#host.getSearchMatches(sheetIndex), latestActive?.pageIndex === sheetIndex ? latestActive : undefined))
755
+ return;
756
+ this.#searchKey = key;
757
+ this.#searchCells = spreadsheetSearchCells(runs, matches, active);
758
+ const activeCell = this.#searchCells.find((cell) => cell.active);
759
+ if (activeCell)
760
+ this.#scrollCellIntoView(activeCell);
761
+ this.#paintSearchHighlights();
762
+ }
763
+ #paintSearchHighlights() {
764
+ const width = this.#root.clientWidth;
765
+ const height = this.#root.clientHeight;
766
+ const zoom = this.#host.state.zoom;
767
+ const gridLeft = this.#rowHeaderWidth() * zoom;
768
+ const gridTop = this.#columnHeaderHeight() * zoom;
769
+ const visible = this.#searchCells.flatMap((cell) => {
770
+ const range = this.#searchRange(cell);
771
+ const start = this.#cellPosition(range.startRow, range.startColumn);
772
+ const end = this.#cellPosition(range.endRow + 1, range.endColumn + 1);
773
+ const left = Math.max(gridLeft, start.x);
774
+ const top = Math.max(gridTop, start.y);
775
+ const right = Math.min(width, end.x);
776
+ const bottom = Math.min(height, end.y);
777
+ return right > left && bottom > top
778
+ ? [{ cell, left, top, width: right - left, height: bottom - top }]
779
+ : [];
780
+ });
781
+ while (this.#searchBoxes.length < visible.length)
782
+ this.#searchBoxes.push(this.#createSearchBox());
783
+ this.#searchBoxes.forEach((box, index) => {
784
+ const highlight = visible[index];
785
+ if (!highlight) {
786
+ box.style.display = "none";
787
+ delete box.dataset.row;
788
+ delete box.dataset.column;
789
+ delete box.dataset.active;
790
+ return;
791
+ }
792
+ box.dataset.row = String(highlight.cell.row);
793
+ box.dataset.column = String(highlight.cell.column);
794
+ box.dataset.active = String(highlight.cell.active);
795
+ Object.assign(box.style, {
796
+ display: "block",
797
+ left: `${highlight.left}px`,
798
+ top: `${highlight.top}px`,
799
+ width: `${Math.max(1, highlight.width)}px`,
800
+ height: `${Math.max(1, highlight.height)}px`,
801
+ background: "var(--zrimo-highlight, rgb(255 215 0 / 45%))",
802
+ boxShadow: highlight.cell.active
803
+ ? "inset 0 0 0 2px var(--zrimo-primary, #175cd3)"
804
+ : "none",
805
+ });
806
+ });
807
+ }
808
+ #searchRange(cell) {
809
+ const merged = this.#sheet?.mergedRanges.find((range) => cellInRange(cell, { ...range, sheetIndex: this.#sheetIndex }));
810
+ return merged
811
+ ? { ...merged, sheetIndex: this.#sheetIndex }
812
+ : {
813
+ sheetIndex: this.#sheetIndex,
814
+ startRow: cell.row,
815
+ startColumn: cell.column,
816
+ endRow: cell.row,
817
+ endColumn: cell.column,
818
+ };
819
+ }
820
+ #createSearchBox() {
821
+ const box = document.createElement("div");
822
+ Object.assign(box.style, {
823
+ position: "absolute",
824
+ display: "none",
825
+ boxSizing: "border-box",
826
+ pointerEvents: "none",
827
+ });
828
+ this.#searchLayer.append(box);
829
+ return box;
830
+ }
831
+ #resetSearchHighlights() {
832
+ this.#searchGeneration += 1;
833
+ this.#searchCells = [];
834
+ this.#searchKey = "";
835
+ for (const box of this.#searchBoxes)
836
+ box.style.display = "none";
837
+ }
838
+ #selectionRanges() {
839
+ const anchor = this.#cellAnchor;
840
+ const focus = this.#cellFocus;
841
+ if (!anchor || !focus)
842
+ return [...this.#cellBaseRanges];
843
+ const active = normalizeCellRange({
844
+ sheetIndex: this.#sheetIndex,
845
+ startRow: anchor.row,
846
+ startColumn: anchor.column,
847
+ endRow: focus.row,
848
+ endColumn: focus.column,
849
+ });
850
+ return [
851
+ ...this.#cellBaseRanges.flatMap((range) => subtractRange(range, active)),
852
+ active,
853
+ ];
854
+ }
855
+ #createSelectionBox() {
856
+ const box = document.createElement("div");
857
+ Object.assign(box.style, {
858
+ position: "absolute",
859
+ display: "none",
860
+ boxSizing: "border-box",
861
+ border: "2px solid var(--zrimo-selection, #2563eb)",
862
+ background: "rgb(37 99 235 / 10%)",
863
+ pointerEvents: "none",
864
+ });
865
+ this.#selectionLayer.append(box);
866
+ return box;
867
+ }
868
+ #resetCellSelection() {
869
+ this.#cellPointerId = undefined;
870
+ this.#cellAnchor = undefined;
871
+ this.#cellFocus = undefined;
872
+ this.#cellBaseRanges = [];
873
+ for (const box of this.#selectionBoxes)
874
+ box.style.display = "none";
875
+ }
876
+ #cellPosition(row, column) {
877
+ const zoom = this.#host.state.zoom;
878
+ const freezeColumns = Math.max(0, this.#sheet?.frozenColumns ?? 0);
879
+ const freezeRows = Math.max(0, this.#sheet?.frozenRows ?? 0);
880
+ const naturalX = this.#columns.offsetOf(column);
881
+ const naturalY = this.#rows.offsetOf(row);
882
+ return {
883
+ x: this.#rowHeaderWidth() * zoom +
884
+ (naturalX -
885
+ (column <= freezeColumns + 1 ? 0 : this.#root.scrollLeft / zoom)) *
886
+ zoom,
887
+ y: this.#columnHeaderHeight() * zoom +
888
+ (naturalY - (row <= freezeRows + 1 ? 0 : this.#root.scrollTop / zoom)) *
889
+ zoom,
890
+ };
891
+ }
892
+ #scrollCellIntoView(cell) {
893
+ const zoom = this.#host.state.zoom;
894
+ const left = (this.#rowHeaderWidth() + this.#columns.offsetOf(cell.column)) * zoom;
895
+ const right = left + this.#columns.sizeOf(cell.column) * zoom;
896
+ const top = (this.#columnHeaderHeight() + this.#rows.offsetOf(cell.row)) * zoom;
897
+ const bottom = top + this.#rows.sizeOf(cell.row) * zoom;
898
+ if (left < this.#root.scrollLeft)
899
+ this.#root.scrollLeft = left;
900
+ else if (right > this.#root.scrollLeft + this.#root.clientWidth)
901
+ this.#root.scrollLeft = right - this.#root.clientWidth;
902
+ if (top < this.#root.scrollTop)
903
+ this.#root.scrollTop = top;
904
+ else if (bottom > this.#root.scrollTop + this.#root.clientHeight)
905
+ this.#root.scrollTop = bottom - this.#root.clientHeight;
906
+ this.#reportPan();
907
+ this.schedule();
908
+ }
909
+ #rowHeaderWidth() {
910
+ return this.#sheet?.rowHeaderWidth ?? DEFAULT_ROW_HEADER_WIDTH;
911
+ }
912
+ #columnHeaderHeight() {
913
+ return this.#sheet?.columnHeaderHeight ?? DEFAULT_COLUMN_HEADER_HEIGHT;
914
+ }
915
+ #reportPan() {
916
+ this.#host.onPan(this.#root.scrollLeft, this.#root.scrollTop);
917
+ }
918
+ }
919
+ export function spreadsheetSearchCells(runs, matches, activeMatch) {
920
+ const cells = new Map();
921
+ let logicalOffset = 0;
922
+ let firstPossibleMatch = 0;
923
+ for (const run of runs) {
924
+ const start = run.logicalStart ?? logicalOffset;
925
+ const end = run.logicalEnd ?? start + run.text.length;
926
+ while (firstPossibleMatch < matches.length &&
927
+ matches[firstPossibleMatch].end <= start)
928
+ firstPossibleMatch += 1;
929
+ if (run.row !== undefined && run.column !== undefined) {
930
+ for (let index = firstPossibleMatch; index < matches.length && matches[index].start < end; index += 1) {
931
+ const match = matches[index];
932
+ if (match.end <= start)
933
+ continue;
934
+ const key = `${run.row}:${run.column}`;
935
+ const active = sameSearchMatch(match, activeMatch);
936
+ const existing = cells.get(key);
937
+ if (!existing || (active && !existing.active))
938
+ cells.set(key, {
939
+ row: run.row,
940
+ column: run.column,
941
+ active,
942
+ });
943
+ }
944
+ }
945
+ logicalOffset = end;
946
+ }
947
+ return Array.from(cells.values());
948
+ }
949
+ function spreadsheetSearchKey(matches, activeMatch) {
950
+ return `${matches
951
+ .map((match) => `${match.pageIndex}:${match.start}:${match.end}`)
952
+ .join(",")}|${activeMatch
953
+ ? `${activeMatch.pageIndex}:${activeMatch.start}:${activeMatch.end}`
954
+ : ""}`;
955
+ }
956
+ function sameSearchMatch(left, right) {
957
+ return (right !== undefined &&
958
+ left.pageIndex === right.pageIndex &&
959
+ left.start === right.start &&
960
+ left.end === right.end);
961
+ }
962
+ function lowerBound(values, target) {
963
+ let low = 0;
964
+ let high = values.length;
965
+ while (low < high) {
966
+ const middle = Math.floor((low + high) / 2);
967
+ if (values[middle] < target)
968
+ low = middle + 1;
969
+ else
970
+ high = middle;
971
+ }
972
+ return low;
973
+ }
974
+ function nonNegative(value, fallback) {
975
+ return Number.isFinite(value) && value >= 0 ? value : fallback;
976
+ }
977
+ function clampZoom(value) {
978
+ return Math.max(0.1, Math.min(8, Number.isFinite(value) ? value : 1));
979
+ }
980
+ function cellInRange(cell, rawRange) {
981
+ const range = normalizeCellRange(rawRange);
982
+ return (cell.row >= range.startRow &&
983
+ cell.row <= range.endRow &&
984
+ cell.column >= range.startColumn &&
985
+ cell.column <= range.endColumn);
986
+ }
987
+ function subtractCell(range, cell) {
988
+ return subtractRange(range, {
989
+ sheetIndex: range.sheetIndex,
990
+ startRow: cell.row,
991
+ startColumn: cell.column,
992
+ endRow: cell.row,
993
+ endColumn: cell.column,
994
+ });
995
+ }
996
+ function subtractRange(rawSource, rawRemoved) {
997
+ const source = normalizeCellRange(rawSource);
998
+ const removed = normalizeCellRange(rawRemoved);
999
+ const top = Math.max(source.startRow, removed.startRow);
1000
+ const bottom = Math.min(source.endRow, removed.endRow);
1001
+ const left = Math.max(source.startColumn, removed.startColumn);
1002
+ const right = Math.min(source.endColumn, removed.endColumn);
1003
+ if (top > bottom || left > right)
1004
+ return [source];
1005
+ const result = [];
1006
+ const add = (startRow, startColumn, endRow, endColumn) => {
1007
+ if (startRow <= endRow && startColumn <= endColumn)
1008
+ result.push({
1009
+ sheetIndex: source.sheetIndex,
1010
+ startRow,
1011
+ startColumn,
1012
+ endRow,
1013
+ endColumn,
1014
+ });
1015
+ };
1016
+ add(source.startRow, source.startColumn, top - 1, source.endColumn);
1017
+ add(bottom + 1, source.startColumn, source.endRow, source.endColumn);
1018
+ add(top, source.startColumn, bottom, left - 1);
1019
+ add(top, right + 1, bottom, source.endColumn);
1020
+ return result;
1021
+ }
1022
+ function cellKeyDelta(key) {
1023
+ switch (key) {
1024
+ case "ArrowUp":
1025
+ return { row: -1, column: 0 };
1026
+ case "ArrowDown":
1027
+ return { row: 1, column: 0 };
1028
+ case "ArrowLeft":
1029
+ return { row: 0, column: -1 };
1030
+ case "ArrowRight":
1031
+ return { row: 0, column: 1 };
1032
+ default:
1033
+ return undefined;
1034
+ }
1035
+ }