@skygraph/core 0.0.0-placeholder.0 → 0.4.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 (70) hide show
  1. package/LICENSE +21 -0
  2. package/dist/calendar.cjs +404 -0
  3. package/dist/calendar.cjs.map +1 -0
  4. package/dist/calendar.d.cts +209 -0
  5. package/dist/calendar.d.ts +209 -0
  6. package/dist/calendar.js +12 -0
  7. package/dist/calendar.js.map +1 -0
  8. package/dist/chunk-5CCD5Q4B.js +36 -0
  9. package/dist/chunk-5CCD5Q4B.js.map +1 -0
  10. package/dist/chunk-AB3RLBLW.js +357 -0
  11. package/dist/chunk-AB3RLBLW.js.map +1 -0
  12. package/dist/chunk-GEMALROQ.js +258 -0
  13. package/dist/chunk-GEMALROQ.js.map +1 -0
  14. package/dist/chunk-IY6LJU3L.js +256 -0
  15. package/dist/chunk-IY6LJU3L.js.map +1 -0
  16. package/dist/chunk-KMGRNPLG.js +453 -0
  17. package/dist/chunk-KMGRNPLG.js.map +1 -0
  18. package/dist/chunk-KP75DEA4.js +1012 -0
  19. package/dist/chunk-KP75DEA4.js.map +1 -0
  20. package/dist/chunk-Y7FTBBYX.js +397 -0
  21. package/dist/chunk-Y7FTBBYX.js.map +1 -0
  22. package/dist/chunk-ZWB7JGAJ.js +488 -0
  23. package/dist/chunk-ZWB7JGAJ.js.map +1 -0
  24. package/dist/form.cjs +498 -0
  25. package/dist/form.cjs.map +1 -0
  26. package/dist/form.d.cts +130 -0
  27. package/dist/form.d.ts +130 -0
  28. package/dist/form.js +8 -0
  29. package/dist/form.js.map +1 -0
  30. package/dist/graph.cjs +1065 -0
  31. package/dist/graph.cjs.map +1 -0
  32. package/dist/graph.d.cts +542 -0
  33. package/dist/graph.d.ts +542 -0
  34. package/dist/graph.js +24 -0
  35. package/dist/graph.js.map +1 -0
  36. package/dist/index.cjs +3656 -0
  37. package/dist/index.cjs.map +1 -0
  38. package/dist/index.d.cts +144 -0
  39. package/dist/index.d.ts +144 -0
  40. package/dist/index.js +467 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/runtime-internal.cjs +339 -0
  43. package/dist/runtime-internal.cjs.map +1 -0
  44. package/dist/runtime-internal.d.cts +130 -0
  45. package/dist/runtime-internal.d.ts +130 -0
  46. package/dist/runtime-internal.js +67 -0
  47. package/dist/runtime-internal.js.map +1 -0
  48. package/dist/table.cjs +537 -0
  49. package/dist/table.cjs.map +1 -0
  50. package/dist/table.d.cts +215 -0
  51. package/dist/table.d.ts +215 -0
  52. package/dist/table.js +16 -0
  53. package/dist/table.js.map +1 -0
  54. package/dist/tree.cjs +442 -0
  55. package/dist/tree.cjs.map +1 -0
  56. package/dist/tree.d.cts +76 -0
  57. package/dist/tree.d.ts +76 -0
  58. package/dist/tree.js +8 -0
  59. package/dist/tree.js.map +1 -0
  60. package/dist/types-B-rKQJ4R.d.cts +35 -0
  61. package/dist/types-B-rKQJ4R.d.ts +35 -0
  62. package/dist/virtual.cjs +283 -0
  63. package/dist/virtual.cjs.map +1 -0
  64. package/dist/virtual.d.cts +96 -0
  65. package/dist/virtual.d.ts +96 -0
  66. package/dist/virtual.js +9 -0
  67. package/dist/virtual.js.map +1 -0
  68. package/package.json +98 -18
  69. package/README.md +0 -12
  70. package/index.js +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/Node.ts","../src/runtime/Store.ts","../src/runtime/SubscriptionEngine.ts","../src/runtime/Batch.ts","../src/runtime/Transaction.ts","../src/runtime/CycleDetector.ts","../src/runtime/ComputedEngine.ts"],"sourcesContent":["export interface Node {\n readonly id: string\n value: unknown\n version: number\n}\n\nexport function createNode(id: string, value: unknown): Node {\n return { id, value, version: 0 }\n}\n","import { createNode } from './Node'\nimport type { Node } from './Node'\n\nexport class Store {\n private nodes: Map<string, Node> = new Map()\n\n has(path: string): boolean {\n return this.nodes.has(path)\n }\n\n get(path: string): unknown {\n return this.nodes.get(path)?.value\n }\n\n getNode(path: string): Node | undefined {\n return this.nodes.get(path)\n }\n\n set(path: string, value: unknown): Node {\n let node = this.nodes.get(path)\n if (node) {\n node.value = value\n node.version++\n return node\n }\n node = createNode(path, value)\n this.nodes.set(path, node)\n return node\n }\n\n delete(path: string): boolean {\n return this.nodes.delete(path)\n }\n\n paths(): IterableIterator<string> {\n return this.nodes.keys()\n }\n\n size(): number {\n return this.nodes.size\n }\n}\n","export type Listener = (value: unknown) => void\nexport type Unsubscribe = () => void\n\nexport class SubscriptionEngine {\n private listeners: Map<string, Set<Listener>> = new Map()\n\n subscribe(path: string, cb: Listener): Unsubscribe {\n let set = this.listeners.get(path)\n if (!set) {\n set = new Set()\n this.listeners.set(path, set)\n }\n set.add(cb)\n\n return () => {\n set!.delete(cb)\n if (set!.size === 0) {\n this.listeners.delete(path)\n }\n }\n }\n\n notify(path: string, value: unknown): void {\n const set = this.listeners.get(path)\n if (!set) return\n for (const cb of set) {\n cb(value)\n }\n }\n\n notifyMany(changes: Map<string, unknown>): void {\n for (const [path, value] of changes) {\n this.notify(path, value)\n }\n }\n\n hasListeners(path: string): boolean {\n const set = this.listeners.get(path)\n return set !== undefined && set.size > 0\n }\n\n clear(): void {\n this.listeners.clear()\n }\n}\n","/**\n * Batch collects path changes during a batch callback\n * and defers notifications until the callback completes.\n */\nexport class Batch {\n private depth = 0\n private pending: Map<string, unknown> = new Map()\n\n get isActive(): boolean {\n return this.depth > 0\n }\n\n start(): void {\n this.depth++\n }\n\n end(): Map<string, unknown> | null {\n this.depth--\n if (this.depth > 0) return null\n\n if (this.pending.size === 0) return null\n\n const changes = new Map(this.pending)\n this.pending.clear()\n return changes\n }\n\n enqueue(path: string, value: unknown): void {\n this.pending.set(path, value)\n }\n}\n","import type { Store } from './Store'\n\nexport interface StagedWrite {\n path: string\n value: unknown\n prevValue: unknown\n}\n\n/**\n * Transaction implements the pipeline:\n * SET -> STAGE -> RESOLVE -> PROPAGATE -> COMMIT -> NOTIFY\n *\n * PROPAGATE is handled externally by ComputedEngine.\n * NOTIFY is handled externally by SubscriptionEngine via Batch.\n */\nexport class Transaction {\n private active = false\n private staged: StagedWrite[] = []\n\n get isActive(): boolean {\n return this.active\n }\n\n start(): void {\n if (this.active) {\n throw new Error('SkyGraph: nested transactions are not supported')\n }\n this.active = true\n this.staged = []\n }\n\n /** STAGE: record a write without mutating the store */\n stage(path: string, value: unknown, prevValue: unknown): void {\n this.staged.push({ path, value, prevValue })\n }\n\n /**\n * RESOLVE + COMMIT: drop unchanged values, apply the rest to store.\n * Returns the map of actually changed paths and their new values.\n */\n commit(store: Store): Map<string, unknown> {\n const changes = new Map<string, unknown>()\n\n for (const write of this.staged) {\n if (Object.is(write.value, write.prevValue)) continue\n store.set(write.path, write.value)\n changes.set(write.path, write.value)\n }\n\n this.active = false\n this.staged = []\n return changes\n }\n\n getStaged(): readonly StagedWrite[] {\n return this.staged\n }\n\n complete(): void {\n this.active = false\n this.staged = []\n }\n\n rollback(): void {\n this.active = false\n this.staged = []\n }\n}\n","/**\n * Detects cycles in the computed dependency graph using DFS.\n * Throws on cycle detection to prevent infinite recomputation.\n */\nexport class CycleDetector {\n private graph: Map<string, Set<string>> = new Map()\n\n addEdge(from: string, to: string): void {\n let deps = this.graph.get(from)\n if (!deps) {\n deps = new Set()\n this.graph.set(from, deps)\n }\n deps.add(to)\n\n if (this.hasCycle(to, new Set([from]))) {\n deps.delete(to)\n if (deps.size === 0) this.graph.delete(from)\n throw new Error(\n `SkyGraph: circular dependency detected: ${from} -> ${to}`\n )\n }\n }\n\n removeNode(id: string): void {\n this.graph.delete(id)\n for (const deps of this.graph.values()) {\n deps.delete(id)\n }\n }\n\n getDependents(id: string): string[] {\n const targets = this.graph.get(id)\n return targets ? [...targets] : []\n }\n\n private hasCycle(node: string, visited: Set<string>): boolean {\n if (visited.has(node)) return true\n const deps = this.graph.get(node)\n if (!deps) return false\n visited.add(node)\n for (const dep of deps) {\n if (this.hasCycle(dep, new Set(visited))) return true\n }\n return false\n }\n}\n","import { CycleDetector } from './CycleDetector'\nimport type { Store } from './Store'\n\nexport type ComputeFn = (...values: unknown[]) => unknown\n\ninterface ComputedNode {\n target: string\n deps: string[]\n fn: ComputeFn\n}\n\n/**\n * Manages computed (derived) values in the reactive graph.\n * When a dependency changes, the computed value is recomputed\n * and only propagated if the result actually changed.\n */\nexport class ComputedEngine {\n private computedNodes: Map<string, ComputedNode> = new Map()\n private cycleDetector = new CycleDetector()\n\n register(target: string, deps: string[], fn: ComputeFn): void {\n if (this.computedNodes.has(target)) {\n this.remove(target)\n }\n\n for (const dep of deps) {\n this.cycleDetector.addEdge(dep, target)\n }\n\n this.computedNodes.set(target, { target, deps, fn })\n }\n\n remove(target: string): void {\n this.computedNodes.delete(target)\n this.cycleDetector.removeNode(target)\n }\n\n isComputed(path: string): boolean {\n return this.computedNodes.has(path)\n }\n\n /**\n * Like propagate, but returns both new and old values for middleware support.\n * Does NOT write to the store — the caller handles that via dispatchWrite.\n */\n propagateRaw(\n changedPaths: Set<string>,\n store: Store,\n ): Map<string, { value: unknown; oldValue: unknown }> {\n const result = new Map<string, { value: unknown; oldValue: unknown }>()\n const visited = new Set<string>()\n const queue = [...changedPaths]\n\n while (queue.length > 0) {\n const path = queue.shift()!\n if (visited.has(path)) continue\n visited.add(path)\n\n const dependents = this.cycleDetector.getDependents(path)\n\n for (const depTarget of dependents) {\n const computed = this.computedNodes.get(depTarget)\n if (!computed) continue\n\n const depValues = computed.deps.map((d) => {\n const pending = result.get(d)\n return pending ? pending.value : store.get(d)\n })\n const newValue = computed.fn(...depValues)\n const oldValue = result.has(depTarget)\n ? result.get(depTarget)!.oldValue\n : store.get(depTarget)\n\n if (!Object.is(newValue, oldValue)) {\n result.set(depTarget, { value: newValue, oldValue })\n queue.push(depTarget)\n }\n }\n }\n\n return result\n }\n\n /**\n * Initialize all computed values based on current store state.\n */\n initializeAll(store: Store): void {\n for (const computed of this.computedNodes.values()) {\n const depValues = computed.deps.map((d) => store.get(d))\n const value = computed.fn(...depValues)\n store.set(computed.target, value)\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,256 @@
1
+ // src/engines/virtual/measure.ts
2
+ function createMeasureCache(options) {
3
+ let itemCount = options.itemCount;
4
+ let estimate = options.estimate;
5
+ const measured = /* @__PURE__ */ new Map();
6
+ let offsets = null;
7
+ let cachedTotal = 0;
8
+ const listeners = /* @__PURE__ */ new Set();
9
+ const getEstimate = (index) => typeof estimate === "number" ? estimate : estimate(index);
10
+ const getItemSize = (index) => {
11
+ const m = measured.get(index);
12
+ return m !== void 0 ? m : getEstimate(index);
13
+ };
14
+ const rebuildOffsets = () => {
15
+ if (offsets && offsets.length === itemCount) return;
16
+ const arr = new Array(itemCount);
17
+ let acc = 0;
18
+ for (let i = 0; i < itemCount; i++) {
19
+ arr[i] = acc;
20
+ acc += getItemSize(i);
21
+ }
22
+ offsets = arr;
23
+ cachedTotal = acc;
24
+ };
25
+ const getTotalHeight = () => {
26
+ rebuildOffsets();
27
+ return cachedTotal;
28
+ };
29
+ const getItemOffset = (index) => {
30
+ if (index <= 0) return 0;
31
+ if (index >= itemCount) return getTotalHeight();
32
+ rebuildOffsets();
33
+ return offsets[index];
34
+ };
35
+ const getItemAtOffset = (offset) => {
36
+ if (itemCount === 0) return 0;
37
+ rebuildOffsets();
38
+ let lo = 0;
39
+ let hi = itemCount - 1;
40
+ while (lo < hi) {
41
+ const mid = lo + hi + 1 >>> 1;
42
+ if (offsets[mid] <= offset) lo = mid;
43
+ else hi = mid - 1;
44
+ }
45
+ return lo;
46
+ };
47
+ const invalidate = (event) => {
48
+ offsets = null;
49
+ for (const l of listeners) l(event);
50
+ };
51
+ return {
52
+ get itemCount() {
53
+ return itemCount;
54
+ },
55
+ get measuredCount() {
56
+ return measured.size;
57
+ },
58
+ setItemCount(count) {
59
+ if (count === itemCount) return;
60
+ if (count < itemCount && measured.size > 0) {
61
+ for (const k of [...measured.keys()]) {
62
+ if (k >= count) measured.delete(k);
63
+ }
64
+ }
65
+ itemCount = count;
66
+ invalidate("resize");
67
+ },
68
+ setEstimate(e) {
69
+ estimate = e;
70
+ invalidate("reset");
71
+ },
72
+ setMeasuredHeight(index, height) {
73
+ if (index < 0 || index >= itemCount) return false;
74
+ if (!Number.isFinite(height) || height < 0) return false;
75
+ const prev = measured.get(index);
76
+ if (prev === height) return false;
77
+ measured.set(index, height);
78
+ invalidate("measure");
79
+ return true;
80
+ },
81
+ clearMeasured(index) {
82
+ const had = measured.delete(index);
83
+ if (had) invalidate("measure");
84
+ return had;
85
+ },
86
+ reset() {
87
+ if (measured.size === 0) return;
88
+ measured.clear();
89
+ invalidate("reset");
90
+ },
91
+ hasMeasured(index) {
92
+ return measured.has(index);
93
+ },
94
+ getMeasuredHeight(index) {
95
+ return measured.get(index);
96
+ },
97
+ getEstimatedSize: getEstimate,
98
+ getItemSize,
99
+ getItemOffset,
100
+ getItemAtOffset,
101
+ getTotalHeight,
102
+ subscribe(listener) {
103
+ listeners.add(listener);
104
+ return () => {
105
+ listeners.delete(listener);
106
+ };
107
+ }
108
+ };
109
+ }
110
+
111
+ // src/engines/virtual/index.ts
112
+ function createVirtual(options) {
113
+ let itemCount = options.itemCount;
114
+ let itemHeight = options.itemHeight;
115
+ const overscan = options.overscan ?? 5;
116
+ let cache = null;
117
+ const listeners = /* @__PURE__ */ new Set();
118
+ const ensureCache = () => {
119
+ if (cache) return cache;
120
+ cache = createMeasureCache({ itemCount, estimate: itemHeight });
121
+ cache.subscribe((event) => {
122
+ for (const l of listeners) l(event);
123
+ });
124
+ return cache;
125
+ };
126
+ const isFastPath = () => typeof itemHeight === "number" && (cache === null || cache.measuredCount === 0);
127
+ const getEstimate = (index) => typeof itemHeight === "number" ? itemHeight : itemHeight(index);
128
+ const getItemSize = (index) => {
129
+ if (cache) return cache.getItemSize(index);
130
+ return getEstimate(index);
131
+ };
132
+ const getTotalHeight = () => {
133
+ if (isFastPath()) return itemCount * itemHeight;
134
+ return ensureCache().getTotalHeight();
135
+ };
136
+ const getItemOffset = (index) => {
137
+ if (index <= 0) return 0;
138
+ if (index >= itemCount) return getTotalHeight();
139
+ if (isFastPath()) return index * itemHeight;
140
+ return ensureCache().getItemOffset(index);
141
+ };
142
+ const getItemAtOffset = (offset) => {
143
+ if (itemCount === 0) return 0;
144
+ if (isFastPath()) {
145
+ const h = itemHeight;
146
+ return Math.min(Math.floor(offset / h), itemCount - 1);
147
+ }
148
+ return ensureCache().getItemAtOffset(offset);
149
+ };
150
+ const getRange = (scrollTop, viewportHeight) => {
151
+ if (itemCount === 0) {
152
+ return { startIndex: 0, endIndex: 0, offsetTop: 0, totalHeight: 0, visibleItems: [] };
153
+ }
154
+ const total = getTotalHeight();
155
+ const rawStart = getItemAtOffset(scrollTop);
156
+ const startIndex = Math.max(0, rawStart - overscan);
157
+ let endIndex = rawStart;
158
+ let accHeight = getItemOffset(rawStart) + getItemSize(rawStart);
159
+ const bottomEdge = scrollTop + viewportHeight;
160
+ while (endIndex < itemCount - 1 && accHeight < bottomEdge) {
161
+ endIndex++;
162
+ accHeight += getItemSize(endIndex);
163
+ }
164
+ endIndex = Math.min(itemCount - 1, endIndex + overscan);
165
+ const visibleItems = [];
166
+ for (let i = startIndex; i <= endIndex; i++) {
167
+ visibleItems.push({
168
+ index: i,
169
+ offsetTop: getItemOffset(i),
170
+ height: getItemSize(i)
171
+ });
172
+ }
173
+ return {
174
+ startIndex,
175
+ endIndex,
176
+ offsetTop: getItemOffset(startIndex),
177
+ totalHeight: total,
178
+ visibleItems
179
+ };
180
+ };
181
+ const scrollToIndex = (index, viewportHeight, align = "start") => {
182
+ const clamped = Math.max(0, Math.min(index, itemCount - 1));
183
+ const offset = getItemOffset(clamped);
184
+ const h = getItemSize(clamped);
185
+ switch (align) {
186
+ case "center":
187
+ return Math.max(0, offset - viewportHeight / 2 + h / 2);
188
+ case "end":
189
+ return Math.max(0, offset - viewportHeight + h);
190
+ default:
191
+ return offset;
192
+ }
193
+ };
194
+ const emit = (event) => {
195
+ for (const l of listeners) l(event);
196
+ };
197
+ return {
198
+ get itemCount() {
199
+ return itemCount;
200
+ },
201
+ get totalHeight() {
202
+ return getTotalHeight();
203
+ },
204
+ get measuredCount() {
205
+ return cache?.measuredCount ?? 0;
206
+ },
207
+ setItemCount(count) {
208
+ if (count === itemCount) return;
209
+ itemCount = count;
210
+ if (cache) {
211
+ cache.setItemCount(count);
212
+ } else {
213
+ emit("resize");
214
+ }
215
+ },
216
+ setItemHeight(height) {
217
+ itemHeight = height;
218
+ if (cache) {
219
+ cache.setEstimate(height);
220
+ } else {
221
+ emit("reset");
222
+ }
223
+ },
224
+ setMeasuredHeight(index, height) {
225
+ return ensureCache().setMeasuredHeight(index, height);
226
+ },
227
+ clearMeasuredHeight(index) {
228
+ if (!cache) return false;
229
+ return cache.clearMeasured(index);
230
+ },
231
+ resetMeasurements() {
232
+ if (cache) cache.reset();
233
+ },
234
+ hasMeasured(index) {
235
+ return cache ? cache.hasMeasured(index) : false;
236
+ },
237
+ getEstimatedSize: getEstimate,
238
+ getItemSize,
239
+ getRange,
240
+ getItemOffset,
241
+ getItemAtOffset,
242
+ scrollToIndex,
243
+ subscribe(listener) {
244
+ listeners.add(listener);
245
+ return () => {
246
+ listeners.delete(listener);
247
+ };
248
+ }
249
+ };
250
+ }
251
+
252
+ export {
253
+ createMeasureCache,
254
+ createVirtual
255
+ };
256
+ //# sourceMappingURL=chunk-IY6LJU3L.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/engines/virtual/measure.ts","../src/engines/virtual/index.ts"],"sourcesContent":["/**\n * Кэш измерений высоты для VirtualEngine с динамической высотой строк.\n *\n * Хранит реальные измеренные высоты `Map<index, number>` поверх эстимейта.\n * Префикс-сумма (offsets) пересобирается лениво при первом запросе после\n * любой инвалидации (resize / measure / reset). Подписки нужны React-адаптеру,\n * чтобы перерисоваться, когда измерение строки изменилось.\n */\n\nexport type MeasureCacheEvent = 'measure' | 'reset' | 'resize'\nexport type MeasureCacheListener = (event: MeasureCacheEvent) => void\n\nexport interface MeasureCacheOptions {\n itemCount: number\n estimate: number | ((index: number) => number)\n}\n\nexport interface MeasureCache {\n readonly itemCount: number\n /** Сколько строк уже было измерено. */\n readonly measuredCount: number\n\n setItemCount(count: number): void\n setEstimate(estimate: number | ((index: number) => number)): void\n\n /** Записать измеренную высоту. Возвращает `true`, если значение изменилось. */\n setMeasuredHeight(index: number, height: number): boolean\n /** Сбросить измерение для одной строки. */\n clearMeasured(index: number): boolean\n /** Сбросить все измерения. */\n reset(): void\n\n hasMeasured(index: number): boolean\n getMeasuredHeight(index: number): number | undefined\n\n /** Эстимейт высоты — без учёта измерений. */\n getEstimatedSize(index: number): number\n /** Эффективная высота строки (измерение или эстимейт). */\n getItemSize(index: number): number\n\n getItemOffset(index: number): number\n getItemAtOffset(offset: number): number\n getTotalHeight(): number\n\n subscribe(listener: MeasureCacheListener): () => void\n}\n\nexport function createMeasureCache(options: MeasureCacheOptions): MeasureCache {\n let itemCount = options.itemCount\n let estimate = options.estimate\n const measured = new Map<number, number>()\n let offsets: number[] | null = null\n let cachedTotal = 0\n const listeners = new Set<MeasureCacheListener>()\n\n const getEstimate = (index: number): number =>\n typeof estimate === 'number' ? estimate : estimate(index)\n\n const getItemSize = (index: number): number => {\n const m = measured.get(index)\n return m !== undefined ? m : getEstimate(index)\n }\n\n const rebuildOffsets = () => {\n if (offsets && offsets.length === itemCount) return\n const arr = new Array<number>(itemCount)\n let acc = 0\n for (let i = 0; i < itemCount; i++) {\n arr[i] = acc\n acc += getItemSize(i)\n }\n offsets = arr\n cachedTotal = acc\n }\n\n const getTotalHeight = (): number => {\n rebuildOffsets()\n return cachedTotal\n }\n\n const getItemOffset = (index: number): number => {\n if (index <= 0) return 0\n if (index >= itemCount) return getTotalHeight()\n rebuildOffsets()\n return offsets![index]!\n }\n\n const getItemAtOffset = (offset: number): number => {\n if (itemCount === 0) return 0\n rebuildOffsets()\n let lo = 0\n let hi = itemCount - 1\n while (lo < hi) {\n const mid = (lo + hi + 1) >>> 1\n if (offsets![mid]! <= offset) lo = mid\n else hi = mid - 1\n }\n return lo\n }\n\n const invalidate = (event: MeasureCacheEvent) => {\n offsets = null\n for (const l of listeners) l(event)\n }\n\n return {\n get itemCount() {\n return itemCount\n },\n get measuredCount() {\n return measured.size\n },\n\n setItemCount(count: number) {\n if (count === itemCount) return\n if (count < itemCount && measured.size > 0) {\n for (const k of [...measured.keys()]) {\n if (k >= count) measured.delete(k)\n }\n }\n itemCount = count\n invalidate('resize')\n },\n\n setEstimate(e: number | ((index: number) => number)) {\n estimate = e\n invalidate('reset')\n },\n\n setMeasuredHeight(index: number, height: number): boolean {\n if (index < 0 || index >= itemCount) return false\n if (!Number.isFinite(height) || height < 0) return false\n const prev = measured.get(index)\n if (prev === height) return false\n measured.set(index, height)\n invalidate('measure')\n return true\n },\n\n clearMeasured(index: number): boolean {\n const had = measured.delete(index)\n if (had) invalidate('measure')\n return had\n },\n\n reset() {\n if (measured.size === 0) return\n measured.clear()\n invalidate('reset')\n },\n\n hasMeasured(index: number) {\n return measured.has(index)\n },\n getMeasuredHeight(index: number) {\n return measured.get(index)\n },\n\n getEstimatedSize: getEstimate,\n getItemSize,\n getItemOffset,\n getItemAtOffset,\n getTotalHeight,\n\n subscribe(listener: MeasureCacheListener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n }\n}\n","import { createMeasureCache, type MeasureCache } from './measure'\n\nexport type {\n MeasureCache,\n MeasureCacheEvent,\n MeasureCacheListener,\n MeasureCacheOptions,\n} from './measure'\nexport { createMeasureCache } from './measure'\n\nexport interface VirtualRange {\n startIndex: number\n endIndex: number\n offsetTop: number\n totalHeight: number\n visibleItems: VirtualItem[]\n}\n\nexport interface VirtualItem {\n index: number\n offsetTop: number\n height: number\n}\n\n/** Событие инвалидации, эмитимое VirtualEngine подписчикам. */\nexport type VirtualEngineEvent = 'measure' | 'reset' | 'resize'\nexport type VirtualEngineListener = (event: VirtualEngineEvent) => void\n\nexport interface VirtualEngineOptions {\n itemCount: number\n itemHeight: number | ((index: number) => number)\n overscan?: number\n}\n\nexport interface VirtualEngine {\n readonly itemCount: number\n readonly totalHeight: number\n /** Сколько строк прошли через `setMeasuredHeight`. */\n readonly measuredCount: number\n\n setItemCount(count: number): void\n setItemHeight(height: number | ((index: number) => number)): void\n\n /**\n * Записать реально измеренную (через ResizeObserver) высоту строки.\n * Возвращает `true`, если значение изменилось — полезно для контроля\n * количества `setState` в адаптере.\n */\n setMeasuredHeight(index: number, height: number): boolean\n /** Сбросить измерение для одной строки (высота вернётся к эстимейту). */\n clearMeasuredHeight(index: number): boolean\n /** Сбросить все измерения (например, при resize контейнера / смене темы). */\n resetMeasurements(): void\n /** Был ли индекс уже измерён. */\n hasMeasured(index: number): boolean\n /** Эстимейт высоты строки без учёта измерений. */\n getEstimatedSize(index: number): number\n /** Эффективная высота строки — измерение, если есть, иначе эстимейт. */\n getItemSize(index: number): number\n\n getRange(scrollTop: number, viewportHeight: number): VirtualRange\n getItemOffset(index: number): number\n getItemAtOffset(offset: number): number\n scrollToIndex(\n index: number,\n viewportHeight: number,\n align?: 'start' | 'center' | 'end',\n ): number\n\n /**\n * Подписаться на инвалидации (resize / measure / reset). Вызывается\n * только после реального изменения — повторные `setMeasuredHeight`\n * с тем же значением событие не эмитят.\n */\n subscribe(listener: VirtualEngineListener): () => void\n}\n\nexport function createVirtual(options: VirtualEngineOptions): VirtualEngine {\n let itemCount = options.itemCount\n let itemHeight = options.itemHeight\n const overscan = options.overscan ?? 5\n\n // Кэш создаётся лениво — для чисто фиксированной высоты без измерений\n // нам он не нужен, и мы сохраняем O(1) арифметику для миллионов строк.\n let cache: MeasureCache | null = null\n const listeners = new Set<VirtualEngineListener>()\n\n const ensureCache = (): MeasureCache => {\n if (cache) return cache\n cache = createMeasureCache({ itemCount, estimate: itemHeight })\n cache.subscribe((event) => {\n for (const l of listeners) l(event)\n })\n return cache\n }\n\n const isFastPath = (): boolean =>\n typeof itemHeight === 'number' && (cache === null || cache.measuredCount === 0)\n\n const getEstimate = (index: number): number =>\n typeof itemHeight === 'number' ? itemHeight : itemHeight(index)\n\n const getItemSize = (index: number): number => {\n if (cache) return cache.getItemSize(index)\n return getEstimate(index)\n }\n\n const getTotalHeight = (): number => {\n if (isFastPath()) return itemCount * (itemHeight as number)\n return ensureCache().getTotalHeight()\n }\n\n const getItemOffset = (index: number): number => {\n if (index <= 0) return 0\n if (index >= itemCount) return getTotalHeight()\n if (isFastPath()) return index * (itemHeight as number)\n return ensureCache().getItemOffset(index)\n }\n\n const getItemAtOffset = (offset: number): number => {\n if (itemCount === 0) return 0\n if (isFastPath()) {\n const h = itemHeight as number\n return Math.min(Math.floor(offset / h), itemCount - 1)\n }\n return ensureCache().getItemAtOffset(offset)\n }\n\n const getRange = (scrollTop: number, viewportHeight: number): VirtualRange => {\n if (itemCount === 0) {\n return { startIndex: 0, endIndex: 0, offsetTop: 0, totalHeight: 0, visibleItems: [] }\n }\n\n const total = getTotalHeight()\n const rawStart = getItemAtOffset(scrollTop)\n const startIndex = Math.max(0, rawStart - overscan)\n\n let endIndex = rawStart\n let accHeight = getItemOffset(rawStart) + getItemSize(rawStart)\n const bottomEdge = scrollTop + viewportHeight\n\n while (endIndex < itemCount - 1 && accHeight < bottomEdge) {\n endIndex++\n accHeight += getItemSize(endIndex)\n }\n endIndex = Math.min(itemCount - 1, endIndex + overscan)\n\n const visibleItems: VirtualItem[] = []\n for (let i = startIndex; i <= endIndex; i++) {\n visibleItems.push({\n index: i,\n offsetTop: getItemOffset(i),\n height: getItemSize(i),\n })\n }\n\n return {\n startIndex,\n endIndex,\n offsetTop: getItemOffset(startIndex),\n totalHeight: total,\n visibleItems,\n }\n }\n\n const scrollToIndex = (\n index: number,\n viewportHeight: number,\n align: 'start' | 'center' | 'end' = 'start',\n ): number => {\n const clamped = Math.max(0, Math.min(index, itemCount - 1))\n const offset = getItemOffset(clamped)\n const h = getItemSize(clamped)\n\n switch (align) {\n case 'center':\n return Math.max(0, offset - viewportHeight / 2 + h / 2)\n case 'end':\n return Math.max(0, offset - viewportHeight + h)\n default:\n return offset\n }\n }\n\n const emit = (event: VirtualEngineEvent) => {\n for (const l of listeners) l(event)\n }\n\n return {\n get itemCount() {\n return itemCount\n },\n get totalHeight() {\n return getTotalHeight()\n },\n get measuredCount() {\n return cache?.measuredCount ?? 0\n },\n\n setItemCount(count: number) {\n if (count === itemCount) return\n itemCount = count\n if (cache) {\n cache.setItemCount(count)\n } else {\n emit('resize')\n }\n },\n\n setItemHeight(height: number | ((index: number) => number)) {\n itemHeight = height\n if (cache) {\n cache.setEstimate(height)\n } else {\n emit('reset')\n }\n },\n\n setMeasuredHeight(index: number, height: number) {\n return ensureCache().setMeasuredHeight(index, height)\n },\n\n clearMeasuredHeight(index: number) {\n if (!cache) return false\n return cache.clearMeasured(index)\n },\n\n resetMeasurements() {\n if (cache) cache.reset()\n },\n\n hasMeasured(index: number) {\n return cache ? cache.hasMeasured(index) : false\n },\n\n getEstimatedSize: getEstimate,\n getItemSize,\n\n getRange,\n getItemOffset,\n getItemAtOffset,\n scrollToIndex,\n\n subscribe(listener: VirtualEngineListener) {\n listeners.add(listener)\n return () => {\n listeners.delete(listener)\n }\n },\n }\n}\n"],"mappings":"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","names":[]}