@vobs/ui 0.2.0 → 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.
@@ -90,6 +90,7 @@ export function createVirtualListResizeMeasurementContract(options) {
90
90
  }))
91
91
  .filter((entry) => entry.height !== undefined && Number.isFinite(entry.height) && entry.height > 0)
92
92
  .map((entry) => entry.key);
93
+ const measuredKeySet = new Set(measuredKeys);
93
94
  const measuringKeys = uniqueKeys(options.measuringIds ?? []);
94
95
  const plans = createDynamicVirtualListPlans(options.getMeasuredItemHeight === undefined
95
96
  ? options
@@ -99,7 +100,7 @@ export function createVirtualListResizeMeasurementContract(options) {
99
100
  });
100
101
  const estimatedKeys = options.items
101
102
  .map((_, index) => keyFor(options, index))
102
- .filter((key) => !measuredKeys.includes(key));
103
+ .filter((key) => !measuredKeySet.has(key));
103
104
  return {
104
105
  plans,
105
106
  measuredKeys,
@@ -174,8 +175,7 @@ export function calculateDynamicVirtualListState(options) {
174
175
  if (count === 0) {
175
176
  return createDynamicState(options, 0, 0, 0, -1, 0, []);
176
177
  }
177
- const metrics = dynamicItemMetrics(options, estimatedItemHeight);
178
- const totalSize = metrics.at(-1)?.end ?? 0;
178
+ const { metrics, measuredCount, totalSize } = dynamicItemMetrics(options, estimatedItemHeight);
179
179
  const viewportHeight = Math.max(0, options.viewportHeight);
180
180
  const scrollOffset = clamp(options.scrollOffset ?? 0, 0, Math.max(totalSize - viewportHeight, 0));
181
181
  const visibleStart = firstDynamicIndexAfter(metrics, scrollOffset);
@@ -186,7 +186,7 @@ export function calculateDynamicVirtualListState(options) {
186
186
  const end = ssrCount === undefined
187
187
  ? Math.min(count - 1, visibleEnd + (options.overscan ?? 2))
188
188
  : fallbackEnd;
189
- return createDynamicState(options, totalSize, scrollOffset, visibleStart, visibleEnd, metrics.filter((metric) => metric.measured).length, dynamicRangeItems(options, metrics, start, end));
189
+ return createDynamicState(options, totalSize, scrollOffset, visibleStart, visibleEnd, measuredCount, dynamicRangeItems(options, metrics, start, end));
190
190
  }
191
191
  export function createFixedVirtualListController(options) {
192
192
  let current = normalizeControllerOptions(options);
@@ -398,14 +398,17 @@ function dynamicItemFromMetric(options, index, metric) {
398
398
  function dynamicItemMetrics(options, estimatedItemHeight) {
399
399
  const metrics = [];
400
400
  let start = 0;
401
+ let measuredCount = 0;
401
402
  for (let index = 0; index < options.items.length; index++) {
402
403
  const measuredHeight = options.getItemHeight?.(options.items[index], index);
403
404
  const measured = measuredHeight !== undefined && Number.isFinite(measuredHeight) && measuredHeight > 0;
404
405
  const size = measured ? measuredHeight : estimatedItemHeight;
405
406
  metrics.push({ start, size, measured, end: start + size });
406
407
  start += size;
408
+ if (measured)
409
+ measuredCount += 1;
407
410
  }
408
- return metrics;
411
+ return { metrics, measuredCount, totalSize: start };
409
412
  }
410
413
  function createLayoutState(options, rowCount, columnCount, totalWidth, totalHeight, scrollLeft, scrollTop, visibleStartIndex, visibleEndIndex, visibleRowStart, visibleRowEnd, items, visibleColumnStart = 0, visibleColumnEnd = -1) {
411
414
  return {
@@ -468,14 +471,28 @@ function layoutItemFromRange(options, index, rowIndex, columnIndex, width, heigh
468
471
  };
469
472
  }
470
473
  function firstDynamicIndexAfter(metrics, offset) {
471
- const index = metrics.findIndex((metric) => metric.end > offset);
472
- return index === -1 ? Math.max(0, metrics.length - 1) : index;
474
+ let low = 0;
475
+ let high = metrics.length;
476
+ while (low < high) {
477
+ const mid = low + Math.floor((high - low) / 2);
478
+ if (metrics[mid].end > offset)
479
+ high = mid;
480
+ else
481
+ low = mid + 1;
482
+ }
483
+ return low === metrics.length ? Math.max(0, metrics.length - 1) : low;
473
484
  }
474
485
  function lastDynamicIndexBefore(metrics, offset) {
475
- const index = metrics.findIndex((metric) => metric.start >= offset);
476
- if (index === -1)
477
- return metrics.length - 1;
478
- return Math.max(0, index);
486
+ let low = 0;
487
+ let high = metrics.length;
488
+ while (low < high) {
489
+ const mid = low + Math.floor((high - low) / 2);
490
+ if (metrics[mid].start >= offset)
491
+ high = mid;
492
+ else
493
+ low = mid + 1;
494
+ }
495
+ return low === metrics.length ? metrics.length - 1 : Math.max(0, low);
479
496
  }
480
497
  function normalizeControllerOptions(options) {
481
498
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vobs/ui",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Optional design tokens, layouts and UI components for vobs.",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -41,6 +41,14 @@
41
41
  "types": "./dist/data-display.d.ts",
42
42
  "import": "./dist/data-display.js"
43
43
  },
44
+ "./page-state": {
45
+ "types": "./dist/page-state.d.ts",
46
+ "import": "./dist/page-state.js"
47
+ },
48
+ "./dialog": {
49
+ "types": "./dist/dialog.d.ts",
50
+ "import": "./dist/dialog.js"
51
+ },
44
52
  "./icons": {
45
53
  "types": "./dist/icons.d.ts",
46
54
  "import": "./dist/icons.js"
@@ -96,18 +104,18 @@
96
104
  "main": "./dist/index.js",
97
105
  "dependencies": {
98
106
  "@tanstack/virtual-core": "^3.17.7",
99
- "@vobs/forms": "0.1.0",
100
- "@vobs/runtime-dom": "0.1.0",
101
- "@vobs/icons": "0.1.0",
102
- "@vobs/i18n": "0.1.0",
103
- "@vobs/reactivity": "0.1.0",
104
- "@vobs/server-renderer": "0.1.0",
105
- "@vobs/router": "0.1.0"
107
+ "@vobs/icons": "0.3.0",
108
+ "@vobs/i18n": "0.3.0",
109
+ "@vobs/forms": "0.3.0",
110
+ "@vobs/runtime-dom": "0.3.0",
111
+ "@vobs/router": "0.3.0",
112
+ "@vobs/reactivity": "0.3.0",
113
+ "@vobs/server-renderer": "0.3.0"
106
114
  },
107
115
  "sideEffects": [
108
116
  "./dist/*.css"
109
117
  ],
110
118
  "engines": {
111
- "node": ">=20.19.0"
119
+ "node": ">=22.12.0"
112
120
  }
113
121
  }