@tonyclaw/llm-inspector 1.6.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 (286) hide show
  1. package/.output/nitro.json +17 -0
  2. package/.output/public/assets/alibaba-TTwafVwX.svg +1 -0
  3. package/.output/public/assets/index-B3RwBPLW.css +1 -0
  4. package/.output/public/assets/index-s4lwsWvq.js +97 -0
  5. package/.output/public/assets/main-Cp8AM0Pa.js +17 -0
  6. package/.output/public/assets/minimax-BPMzvuL-.jpeg +0 -0
  7. package/.output/public/assets/qwen-CONDcHqt.png +0 -0
  8. package/.output/public/assets/zhipuai-BPNAnxo-.svg +219 -0
  9. package/.output/server/_chunks/ssr-renderer.mjs +17 -0
  10. package/.output/server/_libs/@radix-ui/react-accessible-icon+[...].mjs +1 -0
  11. package/.output/server/_libs/@radix-ui/react-dismissable-layer+[...].mjs +210 -0
  12. package/.output/server/_libs/@radix-ui/react-navigation-menu+[...].mjs +1 -0
  13. package/.output/server/_libs/@radix-ui/react-one-time-password-field+[...].mjs +1 -0
  14. package/.output/server/_libs/@radix-ui/react-password-toggle-field+[...].mjs +1 -0
  15. package/.output/server/_libs/@radix-ui/react-use-callback-ref+[...].mjs +11 -0
  16. package/.output/server/_libs/@radix-ui/react-use-controllable-state+[...].mjs +69 -0
  17. package/.output/server/_libs/@radix-ui/react-use-effect-event+[...].mjs +1 -0
  18. package/.output/server/_libs/@radix-ui/react-use-escape-keydown+[...].mjs +17 -0
  19. package/.output/server/_libs/@radix-ui/react-use-is-hydrated+[...].mjs +1 -0
  20. package/.output/server/_libs/@radix-ui/react-use-layout-effect+[...].mjs +6 -0
  21. package/.output/server/_libs/@radix-ui/react-visually-hidden+[...].mjs +34 -0
  22. package/.output/server/_libs/ajv-formats.mjs +330 -0
  23. package/.output/server/_libs/ajv.mjs +11444 -0
  24. package/.output/server/_libs/aria-hidden.mjs +122 -0
  25. package/.output/server/_libs/atomically.mjs +152 -0
  26. package/.output/server/_libs/bail.mjs +8 -0
  27. package/.output/server/_libs/character-entities.mjs +2130 -0
  28. package/.output/server/_libs/class-variance-authority.mjs +44 -0
  29. package/.output/server/_libs/clsx.mjs +16 -0
  30. package/.output/server/_libs/comma-separated-tokens.mjs +10 -0
  31. package/.output/server/_libs/conf.mjs +635 -0
  32. package/.output/server/_libs/cookie-es.mjs +58 -0
  33. package/.output/server/_libs/core-util-is.mjs +75 -0
  34. package/.output/server/_libs/croner.mjs +1 -0
  35. package/.output/server/_libs/crossws.mjs +1 -0
  36. package/.output/server/_libs/debounce-fn.mjs +69 -0
  37. package/.output/server/_libs/decode-named-character-reference+[...].mjs +8 -0
  38. package/.output/server/_libs/detect-node-es.mjs +1 -0
  39. package/.output/server/_libs/devlop.mjs +8 -0
  40. package/.output/server/_libs/dot-prop.mjs +265 -0
  41. package/.output/server/_libs/env-paths.mjs +57 -0
  42. package/.output/server/_libs/estree-util-is-identifier-name.mjs +11 -0
  43. package/.output/server/_libs/extend.mjs +97 -0
  44. package/.output/server/_libs/fast-deep-equal.mjs +38 -0
  45. package/.output/server/_libs/fast-uri.mjs +812 -0
  46. package/.output/server/_libs/floating-ui__core.mjs +725 -0
  47. package/.output/server/_libs/floating-ui__dom.mjs +622 -0
  48. package/.output/server/_libs/floating-ui__react-dom.mjs +292 -0
  49. package/.output/server/_libs/floating-ui__utils.mjs +320 -0
  50. package/.output/server/_libs/get-nonce.mjs +9 -0
  51. package/.output/server/_libs/h3-v2.mjs +276 -0
  52. package/.output/server/_libs/h3.mjs +400 -0
  53. package/.output/server/_libs/hast-util-to-jsx-runtime.mjs +388 -0
  54. package/.output/server/_libs/hast-util-whitespace.mjs +10 -0
  55. package/.output/server/_libs/hookable.mjs +1 -0
  56. package/.output/server/_libs/html-url-attributes.mjs +26 -0
  57. package/.output/server/_libs/immediate.mjs +74 -0
  58. package/.output/server/_libs/inherits.mjs +50 -0
  59. package/.output/server/_libs/inline-style-parser.mjs +142 -0
  60. package/.output/server/_libs/is-plain-obj.mjs +10 -0
  61. package/.output/server/_libs/isarray.mjs +14 -0
  62. package/.output/server/_libs/isbot.mjs +20 -0
  63. package/.output/server/_libs/json-schema-traverse.mjs +180 -0
  64. package/.output/server/_libs/jszip.mjs +3049 -0
  65. package/.output/server/_libs/lie.mjs +273 -0
  66. package/.output/server/_libs/lucide-react.mjs +368 -0
  67. package/.output/server/_libs/mdast-util-from-markdown.mjs +717 -0
  68. package/.output/server/_libs/mdast-util-to-hast.mjs +710 -0
  69. package/.output/server/_libs/mdast-util-to-string.mjs +38 -0
  70. package/.output/server/_libs/micromark-core-commonmark.mjs +2259 -0
  71. package/.output/server/_libs/micromark-factory-destination.mjs +94 -0
  72. package/.output/server/_libs/micromark-factory-label.mjs +63 -0
  73. package/.output/server/_libs/micromark-factory-space.mjs +24 -0
  74. package/.output/server/_libs/micromark-factory-title.mjs +65 -0
  75. package/.output/server/_libs/micromark-factory-whitespace.mjs +22 -0
  76. package/.output/server/_libs/micromark-util-character.mjs +44 -0
  77. package/.output/server/_libs/micromark-util-chunked.mjs +36 -0
  78. package/.output/server/_libs/micromark-util-classify-character+[...].mjs +12 -0
  79. package/.output/server/_libs/micromark-util-combine-extensions+[...].mjs +41 -0
  80. package/.output/server/_libs/micromark-util-decode-numeric-character-reference+[...].mjs +19 -0
  81. package/.output/server/_libs/micromark-util-decode-string.mjs +21 -0
  82. package/.output/server/_libs/micromark-util-encode.mjs +1 -0
  83. package/.output/server/_libs/micromark-util-html-tag-name.mjs +69 -0
  84. package/.output/server/_libs/micromark-util-normalize-identifier+[...].mjs +6 -0
  85. package/.output/server/_libs/micromark-util-resolve-all.mjs +15 -0
  86. package/.output/server/_libs/micromark-util-sanitize-uri.mjs +41 -0
  87. package/.output/server/_libs/micromark-util-subtokenize.mjs +346 -0
  88. package/.output/server/_libs/micromark.mjs +906 -0
  89. package/.output/server/_libs/mimic-function.mjs +47 -0
  90. package/.output/server/_libs/ohash.mjs +1 -0
  91. package/.output/server/_libs/pako.mjs +4223 -0
  92. package/.output/server/_libs/process-nextick-args.mjs +48 -0
  93. package/.output/server/_libs/property-information.mjs +1209 -0
  94. package/.output/server/_libs/radix-ui.mjs +1 -0
  95. package/.output/server/_libs/radix-ui__number.mjs +6 -0
  96. package/.output/server/_libs/radix-ui__primitive.mjs +11 -0
  97. package/.output/server/_libs/radix-ui__react-accordion.mjs +1 -0
  98. package/.output/server/_libs/radix-ui__react-alert-dialog.mjs +1 -0
  99. package/.output/server/_libs/radix-ui__react-arrow.mjs +23 -0
  100. package/.output/server/_libs/radix-ui__react-aspect-ratio.mjs +1 -0
  101. package/.output/server/_libs/radix-ui__react-avatar.mjs +1 -0
  102. package/.output/server/_libs/radix-ui__react-checkbox.mjs +1 -0
  103. package/.output/server/_libs/radix-ui__react-collapsible.mjs +144 -0
  104. package/.output/server/_libs/radix-ui__react-collection.mjs +69 -0
  105. package/.output/server/_libs/radix-ui__react-compose-refs.mjs +39 -0
  106. package/.output/server/_libs/radix-ui__react-context-menu.mjs +1 -0
  107. package/.output/server/_libs/radix-ui__react-context.mjs +78 -0
  108. package/.output/server/_libs/radix-ui__react-dialog.mjs +325 -0
  109. package/.output/server/_libs/radix-ui__react-direction.mjs +9 -0
  110. package/.output/server/_libs/radix-ui__react-dropdown-menu.mjs +1 -0
  111. package/.output/server/_libs/radix-ui__react-focus-guards.mjs +29 -0
  112. package/.output/server/_libs/radix-ui__react-focus-scope.mjs +206 -0
  113. package/.output/server/_libs/radix-ui__react-form.mjs +1 -0
  114. package/.output/server/_libs/radix-ui__react-hover-card.mjs +1 -0
  115. package/.output/server/_libs/radix-ui__react-id.mjs +14 -0
  116. package/.output/server/_libs/radix-ui__react-label.mjs +1 -0
  117. package/.output/server/_libs/radix-ui__react-menu.mjs +1 -0
  118. package/.output/server/_libs/radix-ui__react-menubar.mjs +1 -0
  119. package/.output/server/_libs/radix-ui__react-popover.mjs +1 -0
  120. package/.output/server/_libs/radix-ui__react-popper.mjs +286 -0
  121. package/.output/server/_libs/radix-ui__react-portal.mjs +16 -0
  122. package/.output/server/_libs/radix-ui__react-presence.mjs +128 -0
  123. package/.output/server/_libs/radix-ui__react-primitive.mjs +42 -0
  124. package/.output/server/_libs/radix-ui__react-progress.mjs +1 -0
  125. package/.output/server/_libs/radix-ui__react-radio-group.mjs +1 -0
  126. package/.output/server/_libs/radix-ui__react-roving-focus.mjs +224 -0
  127. package/.output/server/_libs/radix-ui__react-scroll-area.mjs +721 -0
  128. package/.output/server/_libs/radix-ui__react-select.mjs +1163 -0
  129. package/.output/server/_libs/radix-ui__react-separator.mjs +28 -0
  130. package/.output/server/_libs/radix-ui__react-slider.mjs +1 -0
  131. package/.output/server/_libs/radix-ui__react-slot.mjs +99 -0
  132. package/.output/server/_libs/radix-ui__react-switch.mjs +1 -0
  133. package/.output/server/_libs/radix-ui__react-tabs.mjs +189 -0
  134. package/.output/server/_libs/radix-ui__react-toast.mjs +1 -0
  135. package/.output/server/_libs/radix-ui__react-toggle-group.mjs +1 -0
  136. package/.output/server/_libs/radix-ui__react-toggle.mjs +1 -0
  137. package/.output/server/_libs/radix-ui__react-toolbar.mjs +1 -0
  138. package/.output/server/_libs/radix-ui__react-tooltip.mjs +495 -0
  139. package/.output/server/_libs/radix-ui__react-use-previous.mjs +14 -0
  140. package/.output/server/_libs/radix-ui__react-use-size.mjs +39 -0
  141. package/.output/server/_libs/react-dom.mjs +9935 -0
  142. package/.output/server/_libs/react-markdown.mjs +147 -0
  143. package/.output/server/_libs/react-remove-scroll-bar.mjs +82 -0
  144. package/.output/server/_libs/react-remove-scroll.mjs +328 -0
  145. package/.output/server/_libs/react-style-singleton.mjs +69 -0
  146. package/.output/server/_libs/react.mjs +515 -0
  147. package/.output/server/_libs/readable-stream.mjs +1518 -0
  148. package/.output/server/_libs/remark-parse.mjs +19 -0
  149. package/.output/server/_libs/remark-rehype.mjs +21 -0
  150. package/.output/server/_libs/rou3.mjs +8 -0
  151. package/.output/server/_libs/safe-buffer.mjs +64 -0
  152. package/.output/server/_libs/semver.mjs +1984 -0
  153. package/.output/server/_libs/seroval-plugins.mjs +58 -0
  154. package/.output/server/_libs/seroval.mjs +1765 -0
  155. package/.output/server/_libs/setimmediate.mjs +1 -0
  156. package/.output/server/_libs/space-separated-tokens.mjs +6 -0
  157. package/.output/server/_libs/srvx.mjs +334 -0
  158. package/.output/server/_libs/stubborn-fs.mjs +91 -0
  159. package/.output/server/_libs/stubborn-utils.mjs +66 -0
  160. package/.output/server/_libs/style-to-js.mjs +72 -0
  161. package/.output/server/_libs/style-to-object.mjs +38 -0
  162. package/.output/server/_libs/tailwind-merge.mjs +3010 -0
  163. package/.output/server/_libs/tanstack__history.mjs +217 -0
  164. package/.output/server/_libs/tanstack__react-router.mjs +1480 -0
  165. package/.output/server/_libs/tanstack__react-store.mjs +1 -0
  166. package/.output/server/_libs/tanstack__react-virtual.mjs +44 -0
  167. package/.output/server/_libs/tanstack__router-core.mjs +4827 -0
  168. package/.output/server/_libs/tanstack__store.mjs +1 -0
  169. package/.output/server/_libs/tanstack__virtual-core.mjs +1225 -0
  170. package/.output/server/_libs/tiny-invariant.mjs +12 -0
  171. package/.output/server/_libs/tiny-warning.mjs +5 -0
  172. package/.output/server/_libs/trim-lines.mjs +41 -0
  173. package/.output/server/_libs/trough.mjs +85 -0
  174. package/.output/server/_libs/tslib.mjs +576 -0
  175. package/.output/server/_libs/ufo.mjs +54 -0
  176. package/.output/server/_libs/uint8array-extras.mjs +69 -0
  177. package/.output/server/_libs/unctx.mjs +1 -0
  178. package/.output/server/_libs/ungap__structured-clone.mjs +212 -0
  179. package/.output/server/_libs/unified.mjs +661 -0
  180. package/.output/server/_libs/unist-util-is.mjs +100 -0
  181. package/.output/server/_libs/unist-util-position.mjs +27 -0
  182. package/.output/server/_libs/unist-util-stringify-position.mjs +27 -0
  183. package/.output/server/_libs/unist-util-visit-parents.mjs +82 -0
  184. package/.output/server/_libs/unist-util-visit.mjs +24 -0
  185. package/.output/server/_libs/unstorage.mjs +1 -0
  186. package/.output/server/_libs/use-callback-ref.mjs +66 -0
  187. package/.output/server/_libs/use-sidecar.mjs +106 -0
  188. package/.output/server/_libs/use-sync-external-store.mjs +1 -0
  189. package/.output/server/_libs/util-deprecate.mjs +12 -0
  190. package/.output/server/_libs/vfile-message.mjs +138 -0
  191. package/.output/server/_libs/vfile.mjs +467 -0
  192. package/.output/server/_libs/when-exit.mjs +53 -0
  193. package/.output/server/_libs/zod.mjs +4460 -0
  194. package/.output/server/_ssr/index-ByCLZu7J.mjs +3061 -0
  195. package/.output/server/_ssr/index.mjs +1176 -0
  196. package/.output/server/_ssr/router-Bq_mxeNz.mjs +2872 -0
  197. package/.output/server/_ssr/start-HYkvq4Ni.mjs +4 -0
  198. package/.output/server/_tanstack-start-manifest_v-C4E0e9my.mjs +4 -0
  199. package/.output/server/index.mjs +393 -0
  200. package/README.md +196 -0
  201. package/package.json +91 -0
  202. package/src/assets/logos/alibaba.svg +1 -0
  203. package/src/assets/logos/anthropic.svg +1 -0
  204. package/src/assets/logos/deepseek.svg +1 -0
  205. package/src/assets/logos/minimax.jpeg +0 -0
  206. package/src/assets/logos/openai.svg +1 -0
  207. package/src/assets/logos/qwen.png +0 -0
  208. package/src/assets/logos/zhipuai.svg +219 -0
  209. package/src/cli.ts +68 -0
  210. package/src/components/ProxyViewer.tsx +325 -0
  211. package/src/components/ProxyViewerContainer.tsx +211 -0
  212. package/src/components/providers/ProviderCard.tsx +186 -0
  213. package/src/components/providers/ProviderForm.tsx +259 -0
  214. package/src/components/providers/ProviderLogo.tsx +111 -0
  215. package/src/components/providers/ProvidersPanel.tsx +259 -0
  216. package/src/components/providers/SettingsDialog.tsx +39 -0
  217. package/src/components/proxy-viewer/ConversationGroup.tsx +68 -0
  218. package/src/components/proxy-viewer/ConversationHeader.tsx +141 -0
  219. package/src/components/proxy-viewer/LogEntry.tsx +225 -0
  220. package/src/components/proxy-viewer/LogEntryHeader.tsx +250 -0
  221. package/src/components/proxy-viewer/ReplayDialog.tsx +208 -0
  222. package/src/components/proxy-viewer/ResponseView.tsx +161 -0
  223. package/src/components/proxy-viewer/StreamingChunkSequence.tsx +171 -0
  224. package/src/components/proxy-viewer/formats/anthropic/ContentBlocks.tsx +139 -0
  225. package/src/components/proxy-viewer/formats/anthropic/ResponseView.tsx +64 -0
  226. package/src/components/proxy-viewer/formats/index.tsx +24 -0
  227. package/src/components/proxy-viewer/formats/openai/ResponseView.tsx +80 -0
  228. package/src/components/proxy-viewer/index.ts +8 -0
  229. package/src/components/ui/badge.tsx +47 -0
  230. package/src/components/ui/button.tsx +47 -0
  231. package/src/components/ui/collapsible.tsx +21 -0
  232. package/src/components/ui/dialog.tsx +129 -0
  233. package/src/components/ui/json-viewer.tsx +464 -0
  234. package/src/components/ui/scroll-area.tsx +54 -0
  235. package/src/components/ui/select.tsx +178 -0
  236. package/src/components/ui/separator.tsx +28 -0
  237. package/src/components/ui/tabs.tsx +88 -0
  238. package/src/components/ui/tooltip.tsx +51 -0
  239. package/src/index.css +11 -0
  240. package/src/lib/export-logs.ts +51 -0
  241. package/src/lib/utils.ts +22 -0
  242. package/src/proxy/chunkStorage.ts +118 -0
  243. package/src/proxy/constants.ts +36 -0
  244. package/src/proxy/formats/anthropic/anthropicProvider.ts +75 -0
  245. package/src/proxy/formats/anthropic/handler.ts +74 -0
  246. package/src/proxy/formats/anthropic/index.ts +14 -0
  247. package/src/proxy/formats/anthropic/register.ts +4 -0
  248. package/src/proxy/formats/anthropic/schemas.ts +217 -0
  249. package/src/proxy/formats/anthropic/stream.ts +167 -0
  250. package/src/proxy/formats/handler.ts +46 -0
  251. package/src/proxy/formats/index.ts +12 -0
  252. package/src/proxy/formats/jsonSchema.ts +24 -0
  253. package/src/proxy/formats/openai/alibabaProvider.ts +38 -0
  254. package/src/proxy/formats/openai/handler.ts +70 -0
  255. package/src/proxy/formats/openai/index.ts +25 -0
  256. package/src/proxy/formats/openai/provider.ts +50 -0
  257. package/src/proxy/formats/openai/register.ts +4 -0
  258. package/src/proxy/formats/openai/schemas.ts +150 -0
  259. package/src/proxy/formats/openai/stream.ts +153 -0
  260. package/src/proxy/formats/protocol.ts +50 -0
  261. package/src/proxy/formats/providerRegistry.ts +51 -0
  262. package/src/proxy/formats/providers/index.ts +3 -0
  263. package/src/proxy/formats/registry.ts +61 -0
  264. package/src/proxy/handler.ts +389 -0
  265. package/src/proxy/logIndex.ts +187 -0
  266. package/src/proxy/logger.ts +99 -0
  267. package/src/proxy/providers.ts +234 -0
  268. package/src/proxy/schemas.ts +160 -0
  269. package/src/proxy/socketTracker.ts +158 -0
  270. package/src/proxy/store.ts +386 -0
  271. package/src/router.tsx +16 -0
  272. package/src/routes/__root.tsx +38 -0
  273. package/src/routes/api/config.paths.ts +14 -0
  274. package/src/routes/api/health.ts +11 -0
  275. package/src/routes/api/logs.$id.chunks.ts +36 -0
  276. package/src/routes/api/logs.$id.replay.ts +262 -0
  277. package/src/routes/api/logs.$id.ts +22 -0
  278. package/src/routes/api/logs.stream.ts +64 -0
  279. package/src/routes/api/logs.ts +30 -0
  280. package/src/routes/api/models.ts +10 -0
  281. package/src/routes/api/providers.$providerId.ts +45 -0
  282. package/src/routes/api/providers.ts +37 -0
  283. package/src/routes/api/sessions.ts +10 -0
  284. package/src/routes/index.tsx +6 -0
  285. package/src/routes/proxy/$.ts +15 -0
  286. package/styles/globals.css +121 -0
@@ -0,0 +1,1225 @@
1
+ function createLazyMeasurementsView(count, flat, getItemKey) {
2
+ const cache = new Array(count);
3
+ return new Proxy(cache, {
4
+ get(target, prop, receiver) {
5
+ if (typeof prop === "string") {
6
+ const c = prop.charCodeAt(0);
7
+ if (c >= 48 && c <= 57) {
8
+ const i = +prop;
9
+ if (Number.isInteger(i) && i >= 0 && i < count) {
10
+ let v = target[i];
11
+ if (!v) {
12
+ const s = flat[i * 2];
13
+ v = target[i] = {
14
+ index: i,
15
+ key: getItemKey(i),
16
+ start: s,
17
+ size: flat[i * 2 + 1],
18
+ end: s + flat[i * 2 + 1],
19
+ lane: 0
20
+ };
21
+ }
22
+ return v;
23
+ }
24
+ }
25
+ if (prop === "length") return count;
26
+ }
27
+ return Reflect.get(target, prop, receiver);
28
+ }
29
+ });
30
+ }
31
+ function memo(getDeps, fn, opts) {
32
+ let deps = opts.initialDeps ?? [];
33
+ let result;
34
+ let isInitial = true;
35
+ function memoizedFunction() {
36
+ const newDeps = getDeps();
37
+ const depsChanged = newDeps.length !== deps.length || newDeps.some((dep, index) => deps[index] !== dep);
38
+ if (!depsChanged) {
39
+ return result;
40
+ }
41
+ deps = newDeps;
42
+ result = fn(...newDeps);
43
+ if ((opts == null ? void 0 : opts.onChange) && !(isInitial && opts.skipInitialOnChange)) {
44
+ opts.onChange(result);
45
+ }
46
+ isInitial = false;
47
+ return result;
48
+ }
49
+ memoizedFunction.updateDeps = (newDeps) => {
50
+ deps = newDeps;
51
+ };
52
+ return memoizedFunction;
53
+ }
54
+ function notUndefined(value, msg) {
55
+ if (value === void 0) {
56
+ throw new Error(`Unexpected undefined${""}`);
57
+ } else {
58
+ return value;
59
+ }
60
+ }
61
+ const approxEqual = (a, b) => Math.abs(a - b) < 1.01;
62
+ const debounce = (targetWindow, fn, ms) => {
63
+ let timeoutId;
64
+ return function(...args) {
65
+ targetWindow.clearTimeout(timeoutId);
66
+ timeoutId = targetWindow.setTimeout(() => fn.apply(this, args), ms);
67
+ };
68
+ };
69
+ let _isIOSResult;
70
+ const isIOSWebKit = () => {
71
+ if (_isIOSResult !== void 0) return _isIOSResult;
72
+ if (typeof navigator === "undefined") return _isIOSResult = false;
73
+ if (/iP(hone|od|ad)/.test(navigator.userAgent)) return _isIOSResult = true;
74
+ const mtp = navigator.maxTouchPoints;
75
+ return _isIOSResult = navigator.platform === "MacIntel" && mtp !== void 0 && mtp > 0;
76
+ };
77
+ const getRect = (element) => {
78
+ const { offsetWidth, offsetHeight } = element;
79
+ return { width: offsetWidth, height: offsetHeight };
80
+ };
81
+ const defaultKeyExtractor = (index) => index;
82
+ const defaultRangeExtractor = (range) => {
83
+ const start = Math.max(range.startIndex - range.overscan, 0);
84
+ const end = Math.min(range.endIndex + range.overscan, range.count - 1);
85
+ const len = end - start + 1;
86
+ const arr = new Array(len);
87
+ for (let i = 0; i < len; i++) {
88
+ arr[i] = start + i;
89
+ }
90
+ return arr;
91
+ };
92
+ const observeElementRect = (instance, cb) => {
93
+ const element = instance.scrollElement;
94
+ if (!element) {
95
+ return;
96
+ }
97
+ const targetWindow = instance.targetWindow;
98
+ if (!targetWindow) {
99
+ return;
100
+ }
101
+ const handler = (rect) => {
102
+ const { width, height } = rect;
103
+ cb({ width: Math.round(width), height: Math.round(height) });
104
+ };
105
+ handler(getRect(element));
106
+ if (!targetWindow.ResizeObserver) {
107
+ return () => {
108
+ };
109
+ }
110
+ const observer = new targetWindow.ResizeObserver((entries) => {
111
+ const run = () => {
112
+ const entry = entries[0];
113
+ if (entry == null ? void 0 : entry.borderBoxSize) {
114
+ const box = entry.borderBoxSize[0];
115
+ if (box) {
116
+ handler({ width: box.inlineSize, height: box.blockSize });
117
+ return;
118
+ }
119
+ }
120
+ handler(getRect(element));
121
+ };
122
+ instance.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
123
+ });
124
+ observer.observe(element, { box: "border-box" });
125
+ return () => {
126
+ observer.unobserve(element);
127
+ };
128
+ };
129
+ const addEventListenerOptions = {
130
+ passive: true
131
+ };
132
+ const supportsScrollend = typeof window == "undefined" ? true : "onscrollend" in window;
133
+ const observeOffset = (instance, cb, readOffset) => {
134
+ const element = instance.scrollElement;
135
+ if (!element) {
136
+ return;
137
+ }
138
+ const targetWindow = instance.targetWindow;
139
+ if (!targetWindow) {
140
+ return;
141
+ }
142
+ const registerScrollendEvent = instance.options.useScrollendEvent && supportsScrollend;
143
+ let offset = 0;
144
+ const fallback = registerScrollendEvent ? null : debounce(
145
+ targetWindow,
146
+ () => cb(offset, false),
147
+ instance.options.isScrollingResetDelay
148
+ );
149
+ const createHandler = (isScrolling) => () => {
150
+ offset = readOffset(element);
151
+ fallback == null ? void 0 : fallback();
152
+ cb(offset, isScrolling);
153
+ };
154
+ const handler = createHandler(true);
155
+ const endHandler = createHandler(false);
156
+ element.addEventListener("scroll", handler, addEventListenerOptions);
157
+ if (registerScrollendEvent) {
158
+ element.addEventListener("scrollend", endHandler, addEventListenerOptions);
159
+ }
160
+ return () => {
161
+ element.removeEventListener("scroll", handler);
162
+ if (registerScrollendEvent) {
163
+ element.removeEventListener("scrollend", endHandler);
164
+ }
165
+ };
166
+ };
167
+ const observeElementOffset = (instance, cb) => observeOffset(instance, cb, (el) => {
168
+ const { horizontal, isRtl } = instance.options;
169
+ return horizontal ? el.scrollLeft * (isRtl && -1 || 1) : el.scrollTop;
170
+ });
171
+ const measureElement = (element, entry, instance) => {
172
+ if (entry == null ? void 0 : entry.borderBoxSize) {
173
+ const box = entry.borderBoxSize[0];
174
+ if (box) {
175
+ const size = Math.round(
176
+ box[instance.options.horizontal ? "inlineSize" : "blockSize"]
177
+ );
178
+ return size;
179
+ }
180
+ }
181
+ return element[instance.options.horizontal ? "offsetWidth" : "offsetHeight"];
182
+ };
183
+ const scrollWithAdjustments = (offset, {
184
+ adjustments = 0,
185
+ behavior
186
+ }, instance) => {
187
+ var _a, _b;
188
+ (_b = (_a = instance.scrollElement) == null ? void 0 : _a.scrollTo) == null ? void 0 : _b.call(_a, {
189
+ [instance.options.horizontal ? "left" : "top"]: offset + adjustments,
190
+ behavior
191
+ });
192
+ };
193
+ const elementScroll = scrollWithAdjustments;
194
+ class Virtualizer {
195
+ constructor(opts) {
196
+ this.unsubs = [];
197
+ this.scrollElement = null;
198
+ this.targetWindow = null;
199
+ this.isScrolling = false;
200
+ this.scrollState = null;
201
+ this.measurementsCache = [];
202
+ this._flatMeasurements = null;
203
+ this.itemSizeCache = /* @__PURE__ */ new Map();
204
+ this.itemSizeCacheVersion = 0;
205
+ this.laneAssignments = /* @__PURE__ */ new Map();
206
+ this.pendingMin = null;
207
+ this.prevLanes = void 0;
208
+ this.lanesChangedFlag = false;
209
+ this.lanesSettling = false;
210
+ this.pendingScrollAnchor = null;
211
+ this.scrollRect = null;
212
+ this.scrollOffset = null;
213
+ this.scrollDirection = null;
214
+ this.scrollAdjustments = 0;
215
+ this._iosDeferredAdjustment = 0;
216
+ this._iosTouching = false;
217
+ this._iosJustTouchEnded = false;
218
+ this._iosTouchEndTimerId = null;
219
+ this._intendedScrollOffset = null;
220
+ this.elementsCache = /* @__PURE__ */ new Map();
221
+ this.now = () => {
222
+ var _a, _b, _c;
223
+ return ((_c = (_b = (_a = this.targetWindow) == null ? void 0 : _a.performance) == null ? void 0 : _b.now) == null ? void 0 : _c.call(_b)) ?? Date.now();
224
+ };
225
+ this.observer = /* @__PURE__ */ (() => {
226
+ let _ro = null;
227
+ const get = () => {
228
+ if (_ro) {
229
+ return _ro;
230
+ }
231
+ if (!this.targetWindow || !this.targetWindow.ResizeObserver) {
232
+ return null;
233
+ }
234
+ return _ro = new this.targetWindow.ResizeObserver((entries) => {
235
+ entries.forEach((entry) => {
236
+ const run = () => {
237
+ const node = entry.target;
238
+ const index = this.indexFromElement(node);
239
+ if (!node.isConnected) {
240
+ this.observer.unobserve(node);
241
+ for (const [cacheKey, cachedNode] of this.elementsCache) {
242
+ if (cachedNode === node) {
243
+ this.elementsCache.delete(cacheKey);
244
+ break;
245
+ }
246
+ }
247
+ return;
248
+ }
249
+ if (this.shouldMeasureDuringScroll(index)) {
250
+ this.resizeItem(
251
+ index,
252
+ this.options.measureElement(node, entry, this)
253
+ );
254
+ }
255
+ };
256
+ this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
257
+ });
258
+ });
259
+ };
260
+ return {
261
+ disconnect: () => {
262
+ var _a;
263
+ (_a = get()) == null ? void 0 : _a.disconnect();
264
+ _ro = null;
265
+ },
266
+ observe: (target) => {
267
+ var _a;
268
+ return (_a = get()) == null ? void 0 : _a.observe(target, { box: "border-box" });
269
+ },
270
+ unobserve: (target) => {
271
+ var _a;
272
+ return (_a = get()) == null ? void 0 : _a.unobserve(target);
273
+ }
274
+ };
275
+ })();
276
+ this.range = null;
277
+ this.setOptions = (opts2) => {
278
+ var _a, _b;
279
+ const merged = {
280
+ debug: false,
281
+ initialOffset: 0,
282
+ overscan: 1,
283
+ paddingStart: 0,
284
+ paddingEnd: 0,
285
+ scrollPaddingStart: 0,
286
+ scrollPaddingEnd: 0,
287
+ horizontal: false,
288
+ getItemKey: defaultKeyExtractor,
289
+ rangeExtractor: defaultRangeExtractor,
290
+ onChange: () => {
291
+ },
292
+ measureElement,
293
+ initialRect: { width: 0, height: 0 },
294
+ scrollMargin: 0,
295
+ gap: 0,
296
+ indexAttribute: "data-index",
297
+ initialMeasurementsCache: [],
298
+ lanes: 1,
299
+ anchorTo: "start",
300
+ followOnAppend: false,
301
+ scrollEndThreshold: 1,
302
+ isScrollingResetDelay: 150,
303
+ enabled: true,
304
+ isRtl: false,
305
+ useScrollendEvent: false,
306
+ useAnimationFrameWithResizeObserver: false,
307
+ laneAssignmentMode: "estimate"
308
+ };
309
+ for (const key in opts2) {
310
+ const v = opts2[key];
311
+ if (v !== void 0) merged[key] = v;
312
+ }
313
+ const prevOptions = this.options;
314
+ let anchor = null;
315
+ let followOnAppend = null;
316
+ if (prevOptions !== void 0 && prevOptions.enabled && merged.enabled && merged.anchorTo === "end" && this.scrollElement !== null) {
317
+ const prevCount = prevOptions.count;
318
+ const nextCount = merged.count;
319
+ const measurements = this.getMeasurements();
320
+ const prevFirstKey = prevCount > 0 ? ((_a = measurements[0]) == null ? void 0 : _a.key) ?? prevOptions.getItemKey(0) : null;
321
+ const prevLastKey = prevCount > 0 ? ((_b = measurements[prevCount - 1]) == null ? void 0 : _b.key) ?? prevOptions.getItemKey(prevCount - 1) : null;
322
+ const didCountChange = nextCount !== prevCount;
323
+ const didEdgeKeysChange = didCountChange || prevCount > 0 && nextCount > 0 && (merged.getItemKey(0) !== prevFirstKey || merged.getItemKey(nextCount - 1) !== prevLastKey);
324
+ if (didEdgeKeysChange) {
325
+ const item = prevCount > 0 ? this.getVirtualItemForOffset(this.getScrollOffset()) ?? measurements[0] : null;
326
+ if (item) {
327
+ anchor = [item.key, this.getScrollOffset() - item.start];
328
+ }
329
+ const behavior = merged.followOnAppend === true ? "auto" : merged.followOnAppend || null;
330
+ if (behavior && nextCount > prevCount && this.isAtEnd(prevOptions.scrollEndThreshold) && (prevCount === 0 || merged.getItemKey(nextCount - 1) !== prevLastKey)) {
331
+ followOnAppend = behavior;
332
+ }
333
+ }
334
+ }
335
+ this.options = merged;
336
+ if (anchor || followOnAppend) {
337
+ this.pendingScrollAnchor = [
338
+ (anchor == null ? void 0 : anchor[0]) ?? null,
339
+ (anchor == null ? void 0 : anchor[1]) ?? 0,
340
+ followOnAppend
341
+ ];
342
+ }
343
+ };
344
+ this.notify = (sync) => {
345
+ var _a, _b;
346
+ (_b = (_a = this.options).onChange) == null ? void 0 : _b.call(_a, this, sync);
347
+ };
348
+ this.maybeNotify = memo(
349
+ () => {
350
+ this.calculateRange();
351
+ return [
352
+ this.isScrolling,
353
+ this.range ? this.range.startIndex : null,
354
+ this.range ? this.range.endIndex : null
355
+ ];
356
+ },
357
+ (isScrolling) => {
358
+ this.notify(isScrolling);
359
+ },
360
+ {
361
+ key: false,
362
+ debug: () => this.options.debug,
363
+ initialDeps: [
364
+ this.isScrolling,
365
+ this.range ? this.range.startIndex : null,
366
+ this.range ? this.range.endIndex : null
367
+ ]
368
+ }
369
+ );
370
+ this.cleanup = () => {
371
+ this.unsubs.filter(Boolean).forEach((d) => d());
372
+ this.unsubs = [];
373
+ this.observer.disconnect();
374
+ if (this.rafId != null && this.targetWindow) {
375
+ this.targetWindow.cancelAnimationFrame(this.rafId);
376
+ this.rafId = null;
377
+ }
378
+ this.scrollState = null;
379
+ this.scrollElement = null;
380
+ this.targetWindow = null;
381
+ };
382
+ this._didMount = () => {
383
+ return () => {
384
+ this.cleanup();
385
+ };
386
+ };
387
+ this._willUpdate = () => {
388
+ var _a;
389
+ const scrollElement = this.options.enabled ? this.options.getScrollElement() : null;
390
+ if (this.scrollElement !== scrollElement) {
391
+ this.cleanup();
392
+ if (!scrollElement) {
393
+ this.maybeNotify();
394
+ return;
395
+ }
396
+ this.scrollElement = scrollElement;
397
+ if (this.scrollElement && "ownerDocument" in this.scrollElement) {
398
+ this.targetWindow = this.scrollElement.ownerDocument.defaultView;
399
+ } else {
400
+ this.targetWindow = ((_a = this.scrollElement) == null ? void 0 : _a.window) ?? null;
401
+ }
402
+ this.elementsCache.forEach((cached) => {
403
+ this.observer.observe(cached);
404
+ });
405
+ this.unsubs.push(
406
+ this.options.observeElementRect(this, (rect) => {
407
+ this.scrollRect = rect;
408
+ this.maybeNotify();
409
+ })
410
+ );
411
+ this.unsubs.push(
412
+ this.options.observeElementOffset(this, (offset, isScrolling) => {
413
+ if (this._intendedScrollOffset !== null && Math.abs(offset - this._intendedScrollOffset) < 1.5) {
414
+ offset = this._intendedScrollOffset;
415
+ }
416
+ this._intendedScrollOffset = null;
417
+ this.scrollAdjustments = 0;
418
+ this.scrollDirection = isScrolling ? this.getScrollOffset() < offset ? "forward" : "backward" : null;
419
+ this.scrollOffset = offset;
420
+ this.isScrolling = isScrolling;
421
+ this._flushIosDeferredIfReady();
422
+ if (this.scrollState) {
423
+ this.scheduleScrollReconcile();
424
+ }
425
+ this.maybeNotify();
426
+ })
427
+ );
428
+ if ("addEventListener" in this.scrollElement) {
429
+ const scrollEl = this.scrollElement;
430
+ const onTouchStart = () => {
431
+ this._iosTouching = true;
432
+ this._iosJustTouchEnded = false;
433
+ if (this._iosTouchEndTimerId !== null && this.targetWindow != null) {
434
+ this.targetWindow.clearTimeout(this._iosTouchEndTimerId);
435
+ this._iosTouchEndTimerId = null;
436
+ }
437
+ };
438
+ const onTouchEnd = () => {
439
+ this._iosTouching = false;
440
+ if (!isIOSWebKit() || this.targetWindow == null) {
441
+ return;
442
+ }
443
+ this._iosJustTouchEnded = true;
444
+ this._iosTouchEndTimerId = this.targetWindow.setTimeout(() => {
445
+ this._iosJustTouchEnded = false;
446
+ this._iosTouchEndTimerId = null;
447
+ this._flushIosDeferredIfReady();
448
+ }, 150);
449
+ };
450
+ scrollEl.addEventListener(
451
+ "touchstart",
452
+ onTouchStart,
453
+ addEventListenerOptions
454
+ );
455
+ scrollEl.addEventListener(
456
+ "touchend",
457
+ onTouchEnd,
458
+ addEventListenerOptions
459
+ );
460
+ this.unsubs.push(() => {
461
+ scrollEl.removeEventListener("touchstart", onTouchStart);
462
+ scrollEl.removeEventListener("touchend", onTouchEnd);
463
+ if (this._iosTouchEndTimerId !== null && this.targetWindow != null) {
464
+ this.targetWindow.clearTimeout(this._iosTouchEndTimerId);
465
+ this._iosTouchEndTimerId = null;
466
+ }
467
+ });
468
+ }
469
+ this._scrollToOffset(this.getScrollOffset(), {
470
+ adjustments: void 0,
471
+ behavior: void 0
472
+ });
473
+ }
474
+ const anchor = this.pendingScrollAnchor;
475
+ this.pendingScrollAnchor = null;
476
+ if (anchor && this.scrollElement && this.options.enabled) {
477
+ const [key, offset, followOnAppend] = anchor;
478
+ if (key !== null) {
479
+ const { count, getItemKey } = this.options;
480
+ let index = 0;
481
+ while (index < count && getItemKey(index) !== key) {
482
+ index++;
483
+ }
484
+ const item = index < count ? this.getMeasurements()[index] : void 0;
485
+ if (item) {
486
+ const delta = item.start + offset - this.getScrollOffset();
487
+ if (!approxEqual(delta, 0)) {
488
+ this.applyScrollAdjustment(delta);
489
+ }
490
+ }
491
+ }
492
+ if (followOnAppend) {
493
+ this.scrollToEnd({ behavior: followOnAppend });
494
+ }
495
+ }
496
+ };
497
+ this._flushIosDeferredIfReady = () => {
498
+ if (this._iosDeferredAdjustment === 0) return;
499
+ if (this.isScrolling) return;
500
+ if (this._iosTouching) return;
501
+ if (this._iosJustTouchEnded) return;
502
+ const cur = this.getScrollOffset();
503
+ const max = this.getMaxScrollOffset();
504
+ if (cur < 0 || cur > max) return;
505
+ const delta = this._iosDeferredAdjustment;
506
+ this._iosDeferredAdjustment = 0;
507
+ this._scrollToOffset(cur, {
508
+ adjustments: this.scrollAdjustments += delta,
509
+ behavior: void 0
510
+ });
511
+ };
512
+ this.rafId = null;
513
+ this.getSize = () => {
514
+ if (!this.options.enabled) {
515
+ this.scrollRect = null;
516
+ return 0;
517
+ }
518
+ this.scrollRect = this.scrollRect ?? this.options.initialRect;
519
+ return this.scrollRect[this.options.horizontal ? "width" : "height"];
520
+ };
521
+ this.getScrollOffset = () => {
522
+ if (!this.options.enabled) {
523
+ this.scrollOffset = null;
524
+ return 0;
525
+ }
526
+ this.scrollOffset = this.scrollOffset ?? (typeof this.options.initialOffset === "function" ? this.options.initialOffset() : this.options.initialOffset);
527
+ return this.scrollOffset;
528
+ };
529
+ this.getFurthestMeasurement = (measurements, index) => {
530
+ const furthestMeasurementsFound = /* @__PURE__ */ new Map();
531
+ const furthestMeasurements = /* @__PURE__ */ new Map();
532
+ for (let m = index - 1; m >= 0; m--) {
533
+ const measurement = measurements[m];
534
+ if (furthestMeasurementsFound.has(measurement.lane)) {
535
+ continue;
536
+ }
537
+ const previousFurthestMeasurement = furthestMeasurements.get(
538
+ measurement.lane
539
+ );
540
+ if (previousFurthestMeasurement == null || measurement.end > previousFurthestMeasurement.end) {
541
+ furthestMeasurements.set(measurement.lane, measurement);
542
+ } else if (measurement.end < previousFurthestMeasurement.end) {
543
+ furthestMeasurementsFound.set(measurement.lane, true);
544
+ }
545
+ if (furthestMeasurementsFound.size === this.options.lanes) {
546
+ break;
547
+ }
548
+ }
549
+ return furthestMeasurements.size === this.options.lanes ? Array.from(furthestMeasurements.values()).sort((a, b) => {
550
+ if (a.end === b.end) {
551
+ return a.index - b.index;
552
+ }
553
+ return a.end - b.end;
554
+ })[0] : void 0;
555
+ };
556
+ this.getMeasurementOptions = memo(
557
+ () => [
558
+ this.options.count,
559
+ this.options.paddingStart,
560
+ this.options.scrollMargin,
561
+ this.options.getItemKey,
562
+ this.options.enabled,
563
+ this.options.lanes,
564
+ this.options.laneAssignmentMode
565
+ ],
566
+ (count, paddingStart, scrollMargin, getItemKey, enabled, lanes, laneAssignmentMode) => {
567
+ const lanesChanged = this.prevLanes !== void 0 && this.prevLanes !== lanes;
568
+ if (lanesChanged) {
569
+ this.lanesChangedFlag = true;
570
+ }
571
+ this.prevLanes = lanes;
572
+ this.pendingMin = null;
573
+ return {
574
+ count,
575
+ paddingStart,
576
+ scrollMargin,
577
+ getItemKey,
578
+ enabled,
579
+ lanes,
580
+ laneAssignmentMode
581
+ };
582
+ },
583
+ {
584
+ key: false
585
+ }
586
+ );
587
+ this.getMeasurements = memo(
588
+ () => [this.getMeasurementOptions(), this.itemSizeCacheVersion],
589
+ ({
590
+ count,
591
+ paddingStart,
592
+ scrollMargin,
593
+ getItemKey,
594
+ enabled,
595
+ lanes,
596
+ laneAssignmentMode
597
+ }, _itemSizeCacheVersion) => {
598
+ const itemSizeCache = this.itemSizeCache;
599
+ if (!enabled) {
600
+ this.measurementsCache = [];
601
+ this.itemSizeCache.clear();
602
+ this.laneAssignments.clear();
603
+ return [];
604
+ }
605
+ if (this.laneAssignments.size > count) {
606
+ for (const index of this.laneAssignments.keys()) {
607
+ if (index >= count) {
608
+ this.laneAssignments.delete(index);
609
+ }
610
+ }
611
+ }
612
+ if (this.lanesChangedFlag) {
613
+ this.lanesChangedFlag = false;
614
+ this.lanesSettling = true;
615
+ this.measurementsCache = [];
616
+ this.itemSizeCache.clear();
617
+ this.laneAssignments.clear();
618
+ this.pendingMin = null;
619
+ }
620
+ if (this.measurementsCache.length === 0 && !this.lanesSettling) {
621
+ this.measurementsCache = this.options.initialMeasurementsCache;
622
+ this.measurementsCache.forEach((item) => {
623
+ this.itemSizeCache.set(item.key, item.size);
624
+ });
625
+ }
626
+ const min = this.lanesSettling ? 0 : this.pendingMin ?? 0;
627
+ this.pendingMin = null;
628
+ if (this.lanesSettling && this.measurementsCache.length === count) {
629
+ this.lanesSettling = false;
630
+ }
631
+ if (lanes === 1) {
632
+ const gap = this.options.gap;
633
+ const need = count * 2;
634
+ let flat = this._flatMeasurements;
635
+ if (!flat || flat.length < need) {
636
+ const next = new Float64Array(need);
637
+ if (flat && min > 0) next.set(flat.subarray(0, min * 2));
638
+ flat = next;
639
+ this._flatMeasurements = flat;
640
+ }
641
+ let runningStart;
642
+ if (min === 0) {
643
+ runningStart = paddingStart + scrollMargin;
644
+ } else {
645
+ const prevIdx = min - 1;
646
+ runningStart = flat[prevIdx * 2] + flat[prevIdx * 2 + 1] + gap;
647
+ }
648
+ for (let i = min; i < count; i++) {
649
+ const key = getItemKey(i);
650
+ const measuredSize = itemSizeCache.get(key);
651
+ const size = typeof measuredSize === "number" ? measuredSize : this.options.estimateSize(i);
652
+ flat[i * 2] = runningStart;
653
+ flat[i * 2 + 1] = size;
654
+ runningStart += size + gap;
655
+ }
656
+ const view = createLazyMeasurementsView(count, flat, getItemKey);
657
+ this.measurementsCache = view;
658
+ return view;
659
+ }
660
+ const measurements = this.measurementsCache.slice(0, min);
661
+ const laneLastIndex = new Array(lanes).fill(
662
+ void 0
663
+ );
664
+ for (let m = 0; m < min; m++) {
665
+ const item = measurements[m];
666
+ if (item) {
667
+ laneLastIndex[item.lane] = m;
668
+ }
669
+ }
670
+ for (let i = min; i < count; i++) {
671
+ const key = getItemKey(i);
672
+ const cachedLane = this.laneAssignments.get(i);
673
+ let lane;
674
+ let start;
675
+ const shouldCacheLane = laneAssignmentMode === "estimate" || itemSizeCache.has(key);
676
+ if (cachedLane !== void 0 && this.options.lanes > 1) {
677
+ lane = cachedLane;
678
+ const prevIndex = laneLastIndex[lane];
679
+ const prevInLane = prevIndex !== void 0 ? measurements[prevIndex] : void 0;
680
+ start = prevInLane ? prevInLane.end + this.options.gap : paddingStart + scrollMargin;
681
+ } else {
682
+ const furthestMeasurement = this.options.lanes === 1 ? measurements[i - 1] : this.getFurthestMeasurement(measurements, i);
683
+ start = furthestMeasurement ? furthestMeasurement.end + this.options.gap : paddingStart + scrollMargin;
684
+ lane = furthestMeasurement ? furthestMeasurement.lane : i % this.options.lanes;
685
+ if (this.options.lanes > 1 && shouldCacheLane) {
686
+ this.laneAssignments.set(i, lane);
687
+ }
688
+ }
689
+ const measuredSize = itemSizeCache.get(key);
690
+ const size = typeof measuredSize === "number" ? measuredSize : this.options.estimateSize(i);
691
+ const end = start + size;
692
+ measurements[i] = {
693
+ index: i,
694
+ start,
695
+ size,
696
+ end,
697
+ key,
698
+ lane
699
+ };
700
+ laneLastIndex[lane] = i;
701
+ }
702
+ this.measurementsCache = measurements;
703
+ return measurements;
704
+ },
705
+ {
706
+ key: false,
707
+ debug: () => this.options.debug
708
+ }
709
+ );
710
+ this.calculateRange = memo(
711
+ () => [
712
+ this.getMeasurements(),
713
+ this.getSize(),
714
+ this.getScrollOffset(),
715
+ this.options.lanes
716
+ ],
717
+ (measurements, outerSize, scrollOffset, lanes) => {
718
+ return this.range = measurements.length > 0 && outerSize > 0 ? calculateRange({
719
+ measurements,
720
+ outerSize,
721
+ scrollOffset,
722
+ lanes,
723
+ // Pass the typed array so binary search + forward-walk can
724
+ // read start/end directly from Float64Array, skipping the
725
+ // Proxy traps that materialize a full VirtualItem per probe.
726
+ flat: lanes === 1 && this._flatMeasurements != null ? this._flatMeasurements : null
727
+ }) : null;
728
+ },
729
+ {
730
+ key: false,
731
+ debug: () => this.options.debug
732
+ }
733
+ );
734
+ this.getVirtualIndexes = memo(
735
+ () => {
736
+ let startIndex = null;
737
+ let endIndex = null;
738
+ const range = this.calculateRange();
739
+ if (range) {
740
+ startIndex = range.startIndex;
741
+ endIndex = range.endIndex;
742
+ }
743
+ this.maybeNotify.updateDeps([this.isScrolling, startIndex, endIndex]);
744
+ return [
745
+ this.options.rangeExtractor,
746
+ this.options.overscan,
747
+ this.options.count,
748
+ startIndex,
749
+ endIndex
750
+ ];
751
+ },
752
+ (rangeExtractor, overscan, count, startIndex, endIndex) => {
753
+ return startIndex === null || endIndex === null ? [] : rangeExtractor({
754
+ startIndex,
755
+ endIndex,
756
+ overscan,
757
+ count
758
+ });
759
+ },
760
+ {
761
+ key: false,
762
+ debug: () => this.options.debug
763
+ }
764
+ );
765
+ this.indexFromElement = (node) => {
766
+ const attributeName = this.options.indexAttribute;
767
+ const indexStr = node.getAttribute(attributeName);
768
+ if (!indexStr) {
769
+ console.warn(
770
+ `Missing attribute name '${attributeName}={index}' on measured element.`
771
+ );
772
+ return -1;
773
+ }
774
+ return parseInt(indexStr, 10);
775
+ };
776
+ this.shouldMeasureDuringScroll = (index) => {
777
+ var _a;
778
+ if (!this.scrollState || this.scrollState.behavior !== "smooth") {
779
+ return true;
780
+ }
781
+ const scrollIndex = this.scrollState.index ?? ((_a = this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)) == null ? void 0 : _a.index);
782
+ if (scrollIndex !== void 0 && this.range) {
783
+ const bufferSize = Math.max(
784
+ this.options.overscan,
785
+ Math.ceil((this.range.endIndex - this.range.startIndex) / 2)
786
+ );
787
+ const minIndex = Math.max(0, scrollIndex - bufferSize);
788
+ const maxIndex = Math.min(
789
+ this.options.count - 1,
790
+ scrollIndex + bufferSize
791
+ );
792
+ return index >= minIndex && index <= maxIndex;
793
+ }
794
+ return true;
795
+ };
796
+ this.measureElement = (node) => {
797
+ if (!node) {
798
+ this.elementsCache.forEach((cached, key2) => {
799
+ if (!cached.isConnected) {
800
+ this.observer.unobserve(cached);
801
+ this.elementsCache.delete(key2);
802
+ }
803
+ });
804
+ return;
805
+ }
806
+ const index = this.indexFromElement(node);
807
+ const key = this.options.getItemKey(index);
808
+ const prevNode = this.elementsCache.get(key);
809
+ if (prevNode !== node) {
810
+ if (prevNode) {
811
+ this.observer.unobserve(prevNode);
812
+ }
813
+ this.observer.observe(node);
814
+ this.elementsCache.set(key, node);
815
+ }
816
+ if ((!this.isScrolling || this.scrollState) && this.shouldMeasureDuringScroll(index)) {
817
+ this.resizeItem(index, this.options.measureElement(node, void 0, this));
818
+ }
819
+ };
820
+ this.resizeItem = (index, size) => {
821
+ var _a, _b;
822
+ if (index < 0 || index >= this.options.count) return;
823
+ let cachedSize;
824
+ let itemStart;
825
+ let key;
826
+ const flat = this._flatMeasurements;
827
+ if (this.options.lanes === 1 && flat !== null) {
828
+ key = this.options.getItemKey(index);
829
+ itemStart = flat[index * 2];
830
+ cachedSize = flat[index * 2 + 1];
831
+ } else {
832
+ const item = this.measurementsCache[index];
833
+ if (!item) return;
834
+ key = item.key;
835
+ itemStart = item.start;
836
+ cachedSize = item.size;
837
+ }
838
+ const itemSize = this.itemSizeCache.get(key) ?? cachedSize;
839
+ const delta = size - itemSize;
840
+ if (delta !== 0) {
841
+ const wasAtEnd = this.options.anchorTo === "end" && ((_a = this.scrollState) == null ? void 0 : _a.behavior) !== "smooth" && this.getVirtualDistanceFromEnd() <= this.options.scrollEndThreshold;
842
+ const prevTotalSize = wasAtEnd ? this.getTotalSize() : 0;
843
+ const shouldAdjustScroll = ((_b = this.scrollState) == null ? void 0 : _b.behavior) !== "smooth" && (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(
844
+ // The callback expects a VirtualItem; build one lazily only
845
+ // when the consumer actually supplied a custom predicate.
846
+ this.measurementsCache[index] ?? {
847
+ index,
848
+ key,
849
+ start: itemStart,
850
+ size: cachedSize,
851
+ end: itemStart + cachedSize,
852
+ lane: 0
853
+ },
854
+ delta,
855
+ this
856
+ ) : (
857
+ // Default: adjust scrollTop only when the resize is an above-
858
+ // viewport item AND we're not actively scrolling backward.
859
+ // Adjusting during backward scroll fights the user's scroll
860
+ // direction and produces the "items jump while scrolling up"
861
+ // jank reported across many issues. Users who want the old
862
+ // behavior can pass shouldAdjustScrollPositionOnItemSizeChange.
863
+ itemStart < this.getScrollOffset() + this.scrollAdjustments && this.scrollDirection !== "backward"
864
+ ));
865
+ if (this.pendingMin === null || index < this.pendingMin) {
866
+ this.pendingMin = index;
867
+ }
868
+ this.itemSizeCache.set(key, size);
869
+ this.itemSizeCacheVersion++;
870
+ if (wasAtEnd) {
871
+ this.applyScrollAdjustment(this.getTotalSize() - prevTotalSize);
872
+ } else if (shouldAdjustScroll) {
873
+ this.applyScrollAdjustment(delta);
874
+ }
875
+ this.notify(false);
876
+ }
877
+ };
878
+ this.getVirtualItems = memo(
879
+ () => [this.getVirtualIndexes(), this.getMeasurements()],
880
+ (indexes, measurements) => {
881
+ const virtualItems = [];
882
+ for (let k = 0, len = indexes.length; k < len; k++) {
883
+ const i = indexes[k];
884
+ const measurement = measurements[i];
885
+ virtualItems.push(measurement);
886
+ }
887
+ return virtualItems;
888
+ },
889
+ {
890
+ key: false,
891
+ debug: () => this.options.debug
892
+ }
893
+ );
894
+ this.getVirtualItemForOffset = (offset) => {
895
+ const measurements = this.getMeasurements();
896
+ if (measurements.length === 0) {
897
+ return void 0;
898
+ }
899
+ const flat = this._flatMeasurements;
900
+ const useFlat = this.options.lanes === 1 && flat != null;
901
+ const idx = findNearestBinarySearch(
902
+ 0,
903
+ measurements.length - 1,
904
+ useFlat ? (i) => flat[i * 2] : (i) => notUndefined(measurements[i]).start,
905
+ offset
906
+ );
907
+ return notUndefined(measurements[idx]);
908
+ };
909
+ this.getMaxScrollOffset = () => {
910
+ if (!this.scrollElement) return 0;
911
+ if ("scrollHeight" in this.scrollElement) {
912
+ return this.options.horizontal ? this.scrollElement.scrollWidth - this.scrollElement.clientWidth : this.scrollElement.scrollHeight - this.scrollElement.clientHeight;
913
+ } else {
914
+ const doc = this.scrollElement.document.documentElement;
915
+ return this.options.horizontal ? doc.scrollWidth - this.scrollElement.innerWidth : doc.scrollHeight - this.scrollElement.innerHeight;
916
+ }
917
+ };
918
+ this.getVirtualDistanceFromEnd = () => {
919
+ return Math.max(
920
+ this.getTotalSize() - this.getSize() - this.getScrollOffset(),
921
+ 0
922
+ );
923
+ };
924
+ this.getDistanceFromEnd = () => {
925
+ return Math.max(this.getMaxScrollOffset() - this.getScrollOffset(), 0);
926
+ };
927
+ this.isAtEnd = (threshold = this.options.scrollEndThreshold) => {
928
+ return this.getDistanceFromEnd() <= threshold;
929
+ };
930
+ this.getOffsetForAlignment = (toOffset, align, itemSize = 0) => {
931
+ if (!this.scrollElement) return 0;
932
+ const size = this.getSize();
933
+ const scrollOffset = this.getScrollOffset();
934
+ if (align === "auto") {
935
+ align = toOffset >= scrollOffset + size ? "end" : "start";
936
+ }
937
+ if (align === "center") {
938
+ toOffset += (itemSize - size) / 2;
939
+ } else if (align === "end") {
940
+ toOffset -= size;
941
+ }
942
+ const maxOffset = this.getMaxScrollOffset();
943
+ return Math.max(Math.min(maxOffset, toOffset), 0);
944
+ };
945
+ this.getOffsetForIndex = (index, align = "auto") => {
946
+ index = Math.max(0, Math.min(index, this.options.count - 1));
947
+ const size = this.getSize();
948
+ const scrollOffset = this.getScrollOffset();
949
+ const item = this.measurementsCache[index];
950
+ if (!item) return;
951
+ if (align === "auto") {
952
+ if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {
953
+ align = "end";
954
+ } else if (item.start <= scrollOffset + this.options.scrollPaddingStart) {
955
+ align = "start";
956
+ } else {
957
+ return [scrollOffset, align];
958
+ }
959
+ }
960
+ if (align === "end" && index === this.options.count - 1) {
961
+ return [this.getMaxScrollOffset(), align];
962
+ }
963
+ const toOffset = align === "end" ? item.end + this.options.scrollPaddingEnd : item.start - this.options.scrollPaddingStart;
964
+ return [
965
+ this.getOffsetForAlignment(toOffset, align, item.size),
966
+ align
967
+ ];
968
+ };
969
+ this.scrollToOffset = (toOffset, { align = "start", behavior = "auto" } = {}) => {
970
+ const offset = this.getOffsetForAlignment(toOffset, align);
971
+ const now = this.now();
972
+ this.scrollState = {
973
+ index: null,
974
+ align,
975
+ behavior,
976
+ startedAt: now,
977
+ lastTargetOffset: offset,
978
+ stableFrames: 0
979
+ };
980
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
981
+ this.scheduleScrollReconcile();
982
+ };
983
+ this.scrollToIndex = (index, {
984
+ align: initialAlign = "auto",
985
+ behavior = "auto"
986
+ } = {}) => {
987
+ index = Math.max(0, Math.min(index, this.options.count - 1));
988
+ const offsetInfo = this.getOffsetForIndex(index, initialAlign);
989
+ if (!offsetInfo) {
990
+ return;
991
+ }
992
+ const [offset, align] = offsetInfo;
993
+ const now = this.now();
994
+ this.scrollState = {
995
+ index,
996
+ align,
997
+ behavior,
998
+ startedAt: now,
999
+ lastTargetOffset: offset,
1000
+ stableFrames: 0
1001
+ };
1002
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
1003
+ this.scheduleScrollReconcile();
1004
+ };
1005
+ this.scrollBy = (delta, { behavior = "auto" } = {}) => {
1006
+ const offset = this.getScrollOffset() + delta;
1007
+ const now = this.now();
1008
+ this.scrollState = {
1009
+ index: null,
1010
+ align: "start",
1011
+ behavior,
1012
+ startedAt: now,
1013
+ lastTargetOffset: offset,
1014
+ stableFrames: 0
1015
+ };
1016
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
1017
+ this.scheduleScrollReconcile();
1018
+ };
1019
+ this.scrollToEnd = ({ behavior = "auto" } = {}) => {
1020
+ if (this.options.count > 0) {
1021
+ this.scrollToIndex(this.options.count - 1, {
1022
+ align: "end",
1023
+ behavior
1024
+ });
1025
+ return;
1026
+ }
1027
+ this.scrollToOffset(Math.max(this.getTotalSize() - this.getSize(), 0), {
1028
+ behavior
1029
+ });
1030
+ };
1031
+ this.getTotalSize = () => {
1032
+ var _a;
1033
+ const measurements = this.getMeasurements();
1034
+ let end;
1035
+ if (measurements.length === 0) {
1036
+ end = this.options.paddingStart;
1037
+ } else if (this.options.lanes === 1) {
1038
+ const lastIdx = measurements.length - 1;
1039
+ const flat = this._flatMeasurements;
1040
+ if (flat != null) {
1041
+ end = flat[lastIdx * 2] + flat[lastIdx * 2 + 1];
1042
+ } else {
1043
+ end = ((_a = measurements[lastIdx]) == null ? void 0 : _a.end) ?? 0;
1044
+ }
1045
+ } else {
1046
+ const endByLane = Array(this.options.lanes).fill(null);
1047
+ let endIndex = measurements.length - 1;
1048
+ while (endIndex >= 0 && endByLane.some((val) => val === null)) {
1049
+ const item = measurements[endIndex];
1050
+ if (endByLane[item.lane] === null) {
1051
+ endByLane[item.lane] = item.end;
1052
+ }
1053
+ endIndex--;
1054
+ }
1055
+ end = Math.max(...endByLane.filter((val) => val !== null));
1056
+ }
1057
+ return Math.max(
1058
+ end - this.options.scrollMargin + this.options.paddingEnd,
1059
+ 0
1060
+ );
1061
+ };
1062
+ this.takeSnapshot = () => {
1063
+ const snapshot = [];
1064
+ if (this.itemSizeCache.size === 0) return snapshot;
1065
+ const m = this.getMeasurements();
1066
+ for (const item of m) {
1067
+ if (item && this.itemSizeCache.has(item.key)) {
1068
+ snapshot.push({
1069
+ index: item.index,
1070
+ key: item.key,
1071
+ start: item.start,
1072
+ size: item.size,
1073
+ end: item.end,
1074
+ lane: item.lane
1075
+ });
1076
+ }
1077
+ }
1078
+ return snapshot;
1079
+ };
1080
+ this._scrollToOffset = (offset, {
1081
+ adjustments,
1082
+ behavior
1083
+ }) => {
1084
+ this._intendedScrollOffset = offset + (adjustments ?? 0);
1085
+ this.options.scrollToFn(offset, { behavior, adjustments }, this);
1086
+ };
1087
+ this.measure = () => {
1088
+ this.pendingMin = null;
1089
+ this.itemSizeCache.clear();
1090
+ this.laneAssignments.clear();
1091
+ this.itemSizeCacheVersion++;
1092
+ this.notify(false);
1093
+ };
1094
+ this.setOptions(opts);
1095
+ }
1096
+ applyScrollAdjustment(delta, behavior) {
1097
+ if (delta === 0) return;
1098
+ if (isIOSWebKit() && (this.isScrolling || this._iosTouching || this._iosJustTouchEnded)) {
1099
+ this._iosDeferredAdjustment += delta;
1100
+ } else {
1101
+ this._scrollToOffset(this.getScrollOffset(), {
1102
+ adjustments: this.scrollAdjustments += delta,
1103
+ behavior
1104
+ });
1105
+ }
1106
+ }
1107
+ scheduleScrollReconcile() {
1108
+ if (!this.targetWindow) {
1109
+ this.scrollState = null;
1110
+ return;
1111
+ }
1112
+ if (this.rafId != null) return;
1113
+ this.rafId = this.targetWindow.requestAnimationFrame(() => {
1114
+ this.rafId = null;
1115
+ this.reconcileScroll();
1116
+ });
1117
+ }
1118
+ reconcileScroll() {
1119
+ if (!this.scrollState) return;
1120
+ const el = this.scrollElement;
1121
+ if (!el) return;
1122
+ const MAX_RECONCILE_MS = 5e3;
1123
+ if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {
1124
+ this.scrollState = null;
1125
+ return;
1126
+ }
1127
+ const offsetInfo = this.scrollState.index != null ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align) : void 0;
1128
+ const targetOffset = offsetInfo ? offsetInfo[0] : this.scrollState.lastTargetOffset;
1129
+ const STABLE_FRAMES = 1;
1130
+ const targetChanged = targetOffset !== this.scrollState.lastTargetOffset;
1131
+ if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {
1132
+ this.scrollState.stableFrames++;
1133
+ if (this.scrollState.stableFrames >= STABLE_FRAMES) {
1134
+ if (this.getScrollOffset() !== targetOffset) {
1135
+ this._scrollToOffset(targetOffset, {
1136
+ adjustments: void 0,
1137
+ behavior: "auto"
1138
+ });
1139
+ }
1140
+ this.scrollState = null;
1141
+ return;
1142
+ }
1143
+ } else {
1144
+ this.scrollState.stableFrames = 0;
1145
+ if (targetChanged) {
1146
+ const viewport = this.getSize() || 600;
1147
+ const distance = Math.abs(targetOffset - this.getScrollOffset());
1148
+ const keepSmooth = this.scrollState.behavior === "smooth" && distance > viewport;
1149
+ this.scrollState.lastTargetOffset = targetOffset;
1150
+ if (!keepSmooth) {
1151
+ this.scrollState.behavior = "auto";
1152
+ }
1153
+ this._scrollToOffset(targetOffset, {
1154
+ adjustments: void 0,
1155
+ behavior: keepSmooth ? "smooth" : "auto"
1156
+ });
1157
+ }
1158
+ }
1159
+ this.scheduleScrollReconcile();
1160
+ }
1161
+ }
1162
+ const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
1163
+ while (low <= high) {
1164
+ const middle = (low + high) / 2 | 0;
1165
+ const currentValue = getCurrentValue(middle);
1166
+ if (currentValue < value) {
1167
+ low = middle + 1;
1168
+ } else if (currentValue > value) {
1169
+ high = middle - 1;
1170
+ } else {
1171
+ return middle;
1172
+ }
1173
+ }
1174
+ if (low > 0) {
1175
+ return low - 1;
1176
+ } else {
1177
+ return 0;
1178
+ }
1179
+ };
1180
+ function calculateRange({
1181
+ measurements,
1182
+ outerSize,
1183
+ scrollOffset,
1184
+ lanes,
1185
+ flat
1186
+ }) {
1187
+ const lastIndex = measurements.length - 1;
1188
+ const getStart = flat ? (index) => flat[index * 2] : (index) => measurements[index].start;
1189
+ const getEnd = flat ? (index) => flat[index * 2] + flat[index * 2 + 1] : (index) => measurements[index].end;
1190
+ if (measurements.length <= lanes) {
1191
+ return {
1192
+ startIndex: 0,
1193
+ endIndex: lastIndex
1194
+ };
1195
+ }
1196
+ let startIndex = findNearestBinarySearch(0, lastIndex, getStart, scrollOffset);
1197
+ let endIndex = startIndex;
1198
+ if (lanes === 1) {
1199
+ while (endIndex < lastIndex && getEnd(endIndex) < scrollOffset + outerSize) {
1200
+ endIndex++;
1201
+ }
1202
+ } else if (lanes > 1) {
1203
+ const endPerLane = Array(lanes).fill(0);
1204
+ while (endIndex < lastIndex && endPerLane.some((pos) => pos < scrollOffset + outerSize)) {
1205
+ const item = measurements[endIndex];
1206
+ endPerLane[item.lane] = item.end;
1207
+ endIndex++;
1208
+ }
1209
+ const startPerLane = Array(lanes).fill(scrollOffset + outerSize);
1210
+ while (startIndex >= 0 && startPerLane.some((pos) => pos >= scrollOffset)) {
1211
+ const item = measurements[startIndex];
1212
+ startPerLane[item.lane] = item.start;
1213
+ startIndex--;
1214
+ }
1215
+ startIndex = Math.max(0, startIndex - startIndex % lanes);
1216
+ endIndex = Math.min(lastIndex, endIndex + (lanes - 1 - endIndex % lanes));
1217
+ }
1218
+ return { startIndex, endIndex };
1219
+ }
1220
+ export {
1221
+ Virtualizer as V,
1222
+ observeElementRect as a,
1223
+ elementScroll as e,
1224
+ observeElementOffset as o
1225
+ };