lkd-web-kit 0.7.31 → 0.8.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.
@@ -10,6 +10,7 @@ const MyNotifications = (props) => /* @__PURE__ */ jsxRuntime.jsx(
10
10
  notifications.Notifications,
11
11
  {
12
12
  position: "top-center",
13
+ pauseResetOnHover: "notification",
13
14
  ...props
14
15
  }
15
16
  );
@@ -6,6 +6,7 @@ const MyNotifications = (props) => /* @__PURE__ */ jsx(
6
6
  Notifications,
7
7
  {
8
8
  position: "top-center",
9
+ pauseResetOnHover: "notification",
9
10
  ...props
10
11
  }
11
12
  );
@@ -6,12 +6,6 @@ const jsxRuntime = require('react/jsx-runtime');
6
6
  const index = require('../../components/MyMultiSelect/index.cjs');
7
7
  const withController = require('../../hocs/withController.cjs');
8
8
 
9
- const FormMultiSelect = withController.withController(({ field, props }) => /* @__PURE__ */ jsxRuntime.jsx(
10
- index.MyMultiSelect,
11
- {
12
- ...field,
13
- ...props
14
- }
15
- ));
9
+ const FormMultiSelect = withController.withController(({ field, props }) => /* @__PURE__ */ jsxRuntime.jsx(index.MyMultiSelect, { ...field, ...props }));
16
10
 
17
11
  exports.FormMultiSelect = FormMultiSelect;
@@ -2,12 +2,6 @@ import { jsx } from 'react/jsx-runtime';
2
2
  import { MyMultiSelect } from '../../components/MyMultiSelect/index.js';
3
3
  import { withController } from '../../hocs/withController.js';
4
4
 
5
- const FormMultiSelect = withController(({ field, props }) => /* @__PURE__ */ jsx(
6
- MyMultiSelect,
7
- {
8
- ...field,
9
- ...props
10
- }
11
- ));
5
+ const FormMultiSelect = withController(({ field, props }) => /* @__PURE__ */ jsx(MyMultiSelect, { ...field, ...props }));
12
6
 
13
7
  export { FormMultiSelect };
@@ -6,12 +6,8 @@ const jsxRuntime = require('react/jsx-runtime');
6
6
  const index = require('../../components/MyNumberInput/index.cjs');
7
7
  const withController = require('../../hocs/withController.cjs');
8
8
 
9
- const FormNumberInput = withController.withController(({ field, props }) => /* @__PURE__ */ jsxRuntime.jsx(
10
- index.MyNumberInput,
11
- {
12
- ...field,
13
- ...props
14
- }
15
- ));
9
+ const FormNumberInput = withController.withController(
10
+ ({ field, props }) => /* @__PURE__ */ jsxRuntime.jsx(index.MyNumberInput, { ...field, ...props })
11
+ );
16
12
 
17
13
  exports.FormNumberInput = FormNumberInput;
@@ -2,12 +2,8 @@ import { jsx } from 'react/jsx-runtime';
2
2
  import { MyNumberInput } from '../../components/MyNumberInput/index.js';
3
3
  import { withController } from '../../hocs/withController.js';
4
4
 
5
- const FormNumberInput = withController(({ field, props }) => /* @__PURE__ */ jsx(
6
- MyNumberInput,
7
- {
8
- ...field,
9
- ...props
10
- }
11
- ));
5
+ const FormNumberInput = withController(
6
+ ({ field, props }) => /* @__PURE__ */ jsx(MyNumberInput, { ...field, ...props })
7
+ );
12
8
 
13
9
  export { FormNumberInput };
package/dist/index.d.ts CHANGED
@@ -113,7 +113,7 @@ export declare const Form: <T extends FieldValues, TContext = any, TT extends T
113
113
  export declare function formatBytes(bytes: number, decimals?: number): string;
114
114
 
115
115
  export declare const FormCheckbox: FC<CheckboxProps & WithControllerProps & {
116
- onValueChange?: ChangeEventHandler<HTMLInputElement> | undefined;
116
+ onValueChange?: ChangeEventHandler<HTMLInputElement, HTMLInputElement> | undefined;
117
117
  }>;
118
118
 
119
119
  export declare const FormCheckboxGroup: FC<MyCheckboxGroupProps & WithControllerProps & {
@@ -168,9 +168,7 @@ onValueChange?: ((value: string[]) => void) | undefined;
168
168
 
169
169
  export declare type FormMultiSelectProps = MyMultiSelectProps & WithControllerProps;
170
170
 
171
- export declare const FormNumberInput: FC<MyNumberInputProps & WithControllerProps & {
172
- onValueChange?: ((value: number | string) => void) | undefined;
173
- }>;
171
+ export declare const FormNumberInput: default_2.FC<FormNumberInputProps>;
174
172
 
175
173
  export declare type FormNumberInputProps = MyNumberInputProps & WithControllerProps;
176
174
 
@@ -187,7 +185,7 @@ onValueChange?: ((value: string) => void) | undefined;
187
185
  export declare type FormRadioGroupProps = MyRadioGroupProps & WithControllerProps;
188
186
 
189
187
  export declare const FormSelect: FC<MySelectProps & WithControllerProps & {
190
- onValueChange?: ((value: string | null, option: ComboboxItem) => void) | undefined;
188
+ onValueChange?: ((value: string | null, option: ComboboxItem<string>) => void) | undefined;
191
189
  }>;
192
190
 
193
191
  export declare type FormSelectProps = MySelectProps & WithControllerProps;
@@ -199,13 +197,13 @@ export declare interface FormSubmitButtonProps extends ButtonProps, ElementProps
199
197
  }
200
198
 
201
199
  export declare const FormTextarea: FC<TextareaProps & WithControllerProps & {
202
- onValueChange?: ChangeEventHandler<HTMLTextAreaElement> | undefined;
200
+ onValueChange?: ChangeEventHandler<HTMLTextAreaElement, HTMLTextAreaElement> | undefined;
203
201
  }>;
204
202
 
205
203
  export declare type FormTextareaProps = MyTextareaProps & WithControllerProps;
206
204
 
207
205
  export declare const FormTextInput: FC<WithControllerProps & MyTextInputProps & {
208
- onValueChange?: ChangeEventHandler<HTMLInputElement> | undefined;
206
+ onValueChange?: ChangeEventHandler<HTMLInputElement, HTMLInputElement> | undefined;
209
207
  }>;
210
208
 
211
209
  export declare type FormTextInputProps = WithControllerProps & MyTextInputProps;
@@ -213,7 +211,7 @@ export declare type FormTextInputProps = WithControllerProps & MyTextInputProps;
213
211
  export declare type FormTimeInput = MyTimeInputProps & WithControllerProps;
214
212
 
215
213
  export declare const FormTimeInput: FC<TimeInputProps & WithControllerProps & {
216
- onValueChange?: ChangeEventHandler<HTMLInputElement> | undefined;
214
+ onValueChange?: ChangeEventHandler<HTMLInputElement, HTMLInputElement> | undefined;
217
215
  }>;
218
216
 
219
217
  export declare const getVirtualContainerProps: (virtualizer: {
@@ -8,6 +8,7 @@ const breakpointsWithPx = require('./breakpoints-with-px.cjs');
8
8
  const myDefaultTheme = {
9
9
  breakpoints: breakpointsWithPx.breakpointsWithPx,
10
10
  cursorType: "pointer",
11
+ defaultRadius: "sm",
11
12
  components: {
12
13
  Notification: core.Notification.extend({
13
14
  defaultProps: {
@@ -4,6 +4,7 @@ import { breakpointsWithPx } from './breakpoints-with-px.js';
4
4
  const myDefaultTheme = {
5
5
  breakpoints: breakpointsWithPx,
6
6
  cursorType: "pointer",
7
+ defaultRadius: "sm",
7
8
  components: {
8
9
  Notification: Notification.extend({
9
10
  defaultProps: {
@@ -125,7 +125,7 @@ class Virtualizer {
125
125
  this.scrollElement = null;
126
126
  this.targetWindow = null;
127
127
  this.isScrolling = false;
128
- this.currentScrollToIndex = null;
128
+ this.scrollState = null;
129
129
  this.measurementsCache = [];
130
130
  this.itemSizeCache = /* @__PURE__ */ new Map();
131
131
  this.laneAssignments = /* @__PURE__ */ new Map();
@@ -138,6 +138,10 @@ class Virtualizer {
138
138
  this.scrollDirection = null;
139
139
  this.scrollAdjustments = 0;
140
140
  this.elementsCache = /* @__PURE__ */ new Map();
141
+ this.now = () => {
142
+ var _a, _b, _c;
143
+ return ((_c = (_b = (_a = this.targetWindow) == null ? void 0 : _a.performance) == null ? void 0 : _b.now) == null ? void 0 : _c.call(_b)) ?? Date.now();
144
+ };
141
145
  this.observer = /* @__PURE__ */ (() => {
142
146
  let _ro = null;
143
147
  const get = () => {
@@ -150,7 +154,18 @@ class Virtualizer {
150
154
  return _ro = new this.targetWindow.ResizeObserver((entries) => {
151
155
  entries.forEach((entry) => {
152
156
  const run = () => {
153
- this._measureElement(entry.target, entry);
157
+ const node = entry.target;
158
+ const index = this.indexFromElement(node);
159
+ if (!node.isConnected) {
160
+ this.observer.unobserve(node);
161
+ return;
162
+ }
163
+ if (this.shouldMeasureDuringScroll(index)) {
164
+ this.resizeItem(
165
+ index,
166
+ this.options.measureElement(node, entry, this)
167
+ );
168
+ }
154
169
  };
155
170
  this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
156
171
  });
@@ -202,6 +217,7 @@ class Virtualizer {
202
217
  isRtl: false,
203
218
  useScrollendEvent: false,
204
219
  useAnimationFrameWithResizeObserver: false,
220
+ laneAssignmentMode: "estimate",
205
221
  ...opts2
206
222
  };
207
223
  };
@@ -235,6 +251,11 @@ class Virtualizer {
235
251
  this.unsubs.filter(Boolean).forEach((d) => d());
236
252
  this.unsubs = [];
237
253
  this.observer.disconnect();
254
+ if (this.rafId != null && this.targetWindow) {
255
+ this.targetWindow.cancelAnimationFrame(this.rafId);
256
+ this.rafId = null;
257
+ }
258
+ this.scrollState = null;
238
259
  this.scrollElement = null;
239
260
  this.targetWindow = null;
240
261
  };
@@ -273,6 +294,9 @@ class Virtualizer {
273
294
  this.scrollDirection = isScrolling ? this.getScrollOffset() < offset ? "forward" : "backward" : null;
274
295
  this.scrollOffset = offset;
275
296
  this.isScrolling = isScrolling;
297
+ if (this.scrollState) {
298
+ this.scheduleScrollReconcile();
299
+ }
276
300
  this.maybeNotify();
277
301
  })
278
302
  );
@@ -282,6 +306,7 @@ class Virtualizer {
282
306
  });
283
307
  }
284
308
  };
309
+ this.rafId = null;
285
310
  this.getSize = () => {
286
311
  if (!this.options.enabled) {
287
312
  this.scrollRect = null;
@@ -332,9 +357,10 @@ class Virtualizer {
332
357
  this.options.scrollMargin,
333
358
  this.options.getItemKey,
334
359
  this.options.enabled,
335
- this.options.lanes
360
+ this.options.lanes,
361
+ this.options.laneAssignmentMode
336
362
  ],
337
- (count, paddingStart, scrollMargin, getItemKey, enabled, lanes) => {
363
+ (count, paddingStart, scrollMargin, getItemKey, enabled, lanes, laneAssignmentMode) => {
338
364
  const lanesChanged = this.prevLanes !== void 0 && this.prevLanes !== lanes;
339
365
  if (lanesChanged) {
340
366
  this.lanesChangedFlag = true;
@@ -347,7 +373,8 @@ class Virtualizer {
347
373
  scrollMargin,
348
374
  getItemKey,
349
375
  enabled,
350
- lanes
376
+ lanes,
377
+ laneAssignmentMode
351
378
  };
352
379
  },
353
380
  {
@@ -356,7 +383,15 @@ class Virtualizer {
356
383
  );
357
384
  this.getMeasurements = utils.memo(
358
385
  () => [this.getMeasurementOptions(), this.itemSizeCache],
359
- ({ count, paddingStart, scrollMargin, getItemKey, enabled, lanes }, itemSizeCache) => {
386
+ ({
387
+ count,
388
+ paddingStart,
389
+ scrollMargin,
390
+ getItemKey,
391
+ enabled,
392
+ lanes,
393
+ laneAssignmentMode
394
+ }, itemSizeCache) => {
360
395
  if (!enabled) {
361
396
  this.measurementsCache = [];
362
397
  this.itemSizeCache.clear();
@@ -404,6 +439,7 @@ class Virtualizer {
404
439
  const cachedLane = this.laneAssignments.get(i);
405
440
  let lane;
406
441
  let start;
442
+ const shouldCacheLane = laneAssignmentMode === "estimate" || itemSizeCache.has(key);
407
443
  if (cachedLane !== void 0 && this.options.lanes > 1) {
408
444
  lane = cachedLane;
409
445
  const prevIndex = laneLastIndex[lane];
@@ -413,7 +449,7 @@ class Virtualizer {
413
449
  const furthestMeasurement = this.options.lanes === 1 ? measurements[i - 1] : this.getFurthestMeasurement(measurements, i);
414
450
  start = furthestMeasurement ? furthestMeasurement.end + this.options.gap : paddingStart + scrollMargin;
415
451
  lane = furthestMeasurement ? furthestMeasurement.lane : i % this.options.lanes;
416
- if (this.options.lanes > 1) {
452
+ if (this.options.lanes > 1 && shouldCacheLane) {
417
453
  this.laneAssignments.set(i, lane);
418
454
  }
419
455
  }
@@ -500,13 +536,38 @@ class Virtualizer {
500
536
  }
501
537
  return parseInt(indexStr, 10);
502
538
  };
503
- this._measureElement = (node, entry) => {
504
- const index = this.indexFromElement(node);
505
- const item = this.measurementsCache[index];
506
- if (!item) {
539
+ this.shouldMeasureDuringScroll = (index) => {
540
+ var _a;
541
+ if (!this.scrollState || this.scrollState.behavior !== "smooth") {
542
+ return true;
543
+ }
544
+ const scrollIndex = this.scrollState.index ?? ((_a = this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)) == null ? void 0 : _a.index);
545
+ if (scrollIndex !== void 0 && this.range) {
546
+ const bufferSize = Math.max(
547
+ this.options.overscan,
548
+ Math.ceil((this.range.endIndex - this.range.startIndex) / 2)
549
+ );
550
+ const minIndex = Math.max(0, scrollIndex - bufferSize);
551
+ const maxIndex = Math.min(
552
+ this.options.count - 1,
553
+ scrollIndex + bufferSize
554
+ );
555
+ return index >= minIndex && index <= maxIndex;
556
+ }
557
+ return true;
558
+ };
559
+ this.measureElement = (node) => {
560
+ if (!node) {
561
+ this.elementsCache.forEach((cached, key2) => {
562
+ if (!cached.isConnected) {
563
+ this.observer.unobserve(cached);
564
+ this.elementsCache.delete(key2);
565
+ }
566
+ });
507
567
  return;
508
568
  }
509
- const key = item.key;
569
+ const index = this.indexFromElement(node);
570
+ const key = this.options.getItemKey(index);
510
571
  const prevNode = this.elementsCache.get(key);
511
572
  if (prevNode !== node) {
512
573
  if (prevNode) {
@@ -515,19 +576,18 @@ class Virtualizer {
515
576
  this.observer.observe(node);
516
577
  this.elementsCache.set(key, node);
517
578
  }
518
- if (node.isConnected) {
519
- this.resizeItem(index, this.options.measureElement(node, entry, this));
579
+ if ((!this.isScrolling || this.scrollState) && this.shouldMeasureDuringScroll(index)) {
580
+ this.resizeItem(index, this.options.measureElement(node, void 0, this));
520
581
  }
521
582
  };
522
583
  this.resizeItem = (index, size) => {
584
+ var _a;
523
585
  const item = this.measurementsCache[index];
524
- if (!item) {
525
- return;
526
- }
586
+ if (!item) return;
527
587
  const itemSize = this.itemSizeCache.get(item.key) ?? item.size;
528
588
  const delta = size - itemSize;
529
589
  if (delta !== 0) {
530
- if (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) : item.start < this.getScrollOffset() + this.scrollAdjustments) {
590
+ if (((_a = this.scrollState) == null ? void 0 : _a.behavior) !== "smooth" && (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) : item.start < this.getScrollOffset() + this.scrollAdjustments)) {
531
591
  if (process.env.NODE_ENV !== "production" && this.options.debug) {
532
592
  console.info("correction", delta);
533
593
  }
@@ -541,18 +601,6 @@ class Virtualizer {
541
601
  this.notify(false);
542
602
  }
543
603
  };
544
- this.measureElement = (node) => {
545
- if (!node) {
546
- this.elementsCache.forEach((cached, key) => {
547
- if (!cached.isConnected) {
548
- this.observer.unobserve(cached);
549
- this.elementsCache.delete(key);
550
- }
551
- });
552
- return;
553
- }
554
- this._measureElement(node, void 0);
555
- };
556
604
  this.getVirtualItems = utils.memo(
557
605
  () => [this.getVirtualIndexes(), this.getMeasurements()],
558
606
  (indexes, measurements) => {
@@ -609,12 +657,10 @@ class Virtualizer {
609
657
  };
610
658
  this.getOffsetForIndex = (index, align = "auto") => {
611
659
  index = Math.max(0, Math.min(index, this.options.count - 1));
612
- const item = this.measurementsCache[index];
613
- if (!item) {
614
- return void 0;
615
- }
616
660
  const size = this.getSize();
617
661
  const scrollOffset = this.getScrollOffset();
662
+ const item = this.measurementsCache[index];
663
+ if (!item) return;
618
664
  if (align === "auto") {
619
665
  if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {
620
666
  align = "end";
@@ -633,85 +679,55 @@ class Virtualizer {
633
679
  align
634
680
  ];
635
681
  };
636
- this.isDynamicMode = () => this.elementsCache.size > 0;
637
- this.scrollToOffset = (toOffset, { align = "start", behavior } = {}) => {
638
- if (behavior === "smooth" && this.isDynamicMode()) {
639
- console.warn(
640
- "The `smooth` scroll behavior is not fully supported with dynamic size."
641
- );
642
- }
643
- this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {
644
- adjustments: void 0,
645
- behavior
646
- });
682
+ this.scrollToOffset = (toOffset, { align = "start", behavior = "auto" } = {}) => {
683
+ const offset = this.getOffsetForAlignment(toOffset, align);
684
+ const now = this.now();
685
+ this.scrollState = {
686
+ index: null,
687
+ align,
688
+ behavior,
689
+ startedAt: now,
690
+ lastTargetOffset: offset,
691
+ stableFrames: 0
692
+ };
693
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
694
+ this.scheduleScrollReconcile();
647
695
  };
648
- this.scrollToIndex = (index, { align: initialAlign = "auto", behavior } = {}) => {
649
- if (behavior === "smooth" && this.isDynamicMode()) {
650
- console.warn(
651
- "The `smooth` scroll behavior is not fully supported with dynamic size."
652
- );
653
- }
696
+ this.scrollToIndex = (index, {
697
+ align: initialAlign = "auto",
698
+ behavior = "auto"
699
+ } = {}) => {
654
700
  index = Math.max(0, Math.min(index, this.options.count - 1));
655
- this.currentScrollToIndex = index;
656
- let attempts = 0;
657
- const maxAttempts = 10;
658
- const tryScroll = (currentAlign) => {
659
- if (!this.targetWindow) return;
660
- const offsetInfo = this.getOffsetForIndex(index, currentAlign);
661
- if (!offsetInfo) {
662
- console.warn("Failed to get offset for index:", index);
663
- return;
664
- }
665
- const [offset, align] = offsetInfo;
666
- this._scrollToOffset(offset, { adjustments: void 0, behavior });
667
- this.targetWindow.requestAnimationFrame(() => {
668
- if (!this.targetWindow) return;
669
- const verify = () => {
670
- if (this.currentScrollToIndex !== index) return;
671
- const currentOffset = this.getScrollOffset();
672
- const afterInfo = this.getOffsetForIndex(index, align);
673
- if (!afterInfo) {
674
- console.warn("Failed to get offset for index:", index);
675
- return;
676
- }
677
- if (!utils.approxEqual(afterInfo[0], currentOffset)) {
678
- scheduleRetry(align);
679
- }
680
- };
681
- if (this.isDynamicMode()) {
682
- this.targetWindow.requestAnimationFrame(verify);
683
- } else {
684
- verify();
685
- }
686
- });
687
- };
688
- const scheduleRetry = (align) => {
689
- if (!this.targetWindow) return;
690
- if (this.currentScrollToIndex !== index) return;
691
- attempts++;
692
- if (attempts < maxAttempts) {
693
- if (process.env.NODE_ENV !== "production" && this.options.debug) {
694
- console.info("Schedule retry", attempts, maxAttempts);
695
- }
696
- this.targetWindow.requestAnimationFrame(() => tryScroll(align));
697
- } else {
698
- console.warn(
699
- `Failed to scroll to index ${index} after ${maxAttempts} attempts.`
700
- );
701
- }
701
+ const offsetInfo = this.getOffsetForIndex(index, initialAlign);
702
+ if (!offsetInfo) {
703
+ return;
704
+ }
705
+ const [offset, align] = offsetInfo;
706
+ const now = this.now();
707
+ this.scrollState = {
708
+ index,
709
+ align,
710
+ behavior,
711
+ startedAt: now,
712
+ lastTargetOffset: offset,
713
+ stableFrames: 0
702
714
  };
703
- tryScroll(initialAlign);
715
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
716
+ this.scheduleScrollReconcile();
704
717
  };
705
- this.scrollBy = (delta, { behavior } = {}) => {
706
- if (behavior === "smooth" && this.isDynamicMode()) {
707
- console.warn(
708
- "The `smooth` scroll behavior is not fully supported with dynamic size."
709
- );
710
- }
711
- this._scrollToOffset(this.getScrollOffset() + delta, {
712
- adjustments: void 0,
713
- behavior
714
- });
718
+ this.scrollBy = (delta, { behavior = "auto" } = {}) => {
719
+ const offset = this.getScrollOffset() + delta;
720
+ const now = this.now();
721
+ this.scrollState = {
722
+ index: null,
723
+ align: "start",
724
+ behavior,
725
+ startedAt: now,
726
+ lastTargetOffset: offset,
727
+ stableFrames: 0
728
+ };
729
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
730
+ this.scheduleScrollReconcile();
715
731
  };
716
732
  this.getTotalSize = () => {
717
733
  var _a;
@@ -751,6 +767,49 @@ class Virtualizer {
751
767
  };
752
768
  this.setOptions(opts);
753
769
  }
770
+ scheduleScrollReconcile() {
771
+ if (!this.targetWindow) {
772
+ this.scrollState = null;
773
+ return;
774
+ }
775
+ if (this.rafId != null) return;
776
+ this.rafId = this.targetWindow.requestAnimationFrame(() => {
777
+ this.rafId = null;
778
+ this.reconcileScroll();
779
+ });
780
+ }
781
+ reconcileScroll() {
782
+ if (!this.scrollState) return;
783
+ const el = this.scrollElement;
784
+ if (!el) return;
785
+ const MAX_RECONCILE_MS = 5e3;
786
+ if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {
787
+ this.scrollState = null;
788
+ return;
789
+ }
790
+ const offsetInfo = this.scrollState.index != null ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align) : void 0;
791
+ const targetOffset = offsetInfo ? offsetInfo[0] : this.scrollState.lastTargetOffset;
792
+ const STABLE_FRAMES = 1;
793
+ const targetChanged = targetOffset !== this.scrollState.lastTargetOffset;
794
+ if (!targetChanged && utils.approxEqual(targetOffset, this.getScrollOffset())) {
795
+ this.scrollState.stableFrames++;
796
+ if (this.scrollState.stableFrames >= STABLE_FRAMES) {
797
+ this.scrollState = null;
798
+ return;
799
+ }
800
+ } else {
801
+ this.scrollState.stableFrames = 0;
802
+ if (targetChanged) {
803
+ this.scrollState.lastTargetOffset = targetOffset;
804
+ this.scrollState.behavior = "auto";
805
+ this._scrollToOffset(targetOffset, {
806
+ adjustments: void 0,
807
+ behavior: "auto"
808
+ });
809
+ }
810
+ }
811
+ this.scheduleScrollReconcile();
812
+ }
754
813
  }
755
814
  const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
756
815
  while (low <= high) {
@@ -121,7 +121,7 @@ class Virtualizer {
121
121
  this.scrollElement = null;
122
122
  this.targetWindow = null;
123
123
  this.isScrolling = false;
124
- this.currentScrollToIndex = null;
124
+ this.scrollState = null;
125
125
  this.measurementsCache = [];
126
126
  this.itemSizeCache = /* @__PURE__ */ new Map();
127
127
  this.laneAssignments = /* @__PURE__ */ new Map();
@@ -134,6 +134,10 @@ class Virtualizer {
134
134
  this.scrollDirection = null;
135
135
  this.scrollAdjustments = 0;
136
136
  this.elementsCache = /* @__PURE__ */ new Map();
137
+ this.now = () => {
138
+ var _a, _b, _c;
139
+ return ((_c = (_b = (_a = this.targetWindow) == null ? void 0 : _a.performance) == null ? void 0 : _b.now) == null ? void 0 : _c.call(_b)) ?? Date.now();
140
+ };
137
141
  this.observer = /* @__PURE__ */ (() => {
138
142
  let _ro = null;
139
143
  const get = () => {
@@ -146,7 +150,18 @@ class Virtualizer {
146
150
  return _ro = new this.targetWindow.ResizeObserver((entries) => {
147
151
  entries.forEach((entry) => {
148
152
  const run = () => {
149
- this._measureElement(entry.target, entry);
153
+ const node = entry.target;
154
+ const index = this.indexFromElement(node);
155
+ if (!node.isConnected) {
156
+ this.observer.unobserve(node);
157
+ return;
158
+ }
159
+ if (this.shouldMeasureDuringScroll(index)) {
160
+ this.resizeItem(
161
+ index,
162
+ this.options.measureElement(node, entry, this)
163
+ );
164
+ }
150
165
  };
151
166
  this.options.useAnimationFrameWithResizeObserver ? requestAnimationFrame(run) : run();
152
167
  });
@@ -198,6 +213,7 @@ class Virtualizer {
198
213
  isRtl: false,
199
214
  useScrollendEvent: false,
200
215
  useAnimationFrameWithResizeObserver: false,
216
+ laneAssignmentMode: "estimate",
201
217
  ...opts2
202
218
  };
203
219
  };
@@ -231,6 +247,11 @@ class Virtualizer {
231
247
  this.unsubs.filter(Boolean).forEach((d) => d());
232
248
  this.unsubs = [];
233
249
  this.observer.disconnect();
250
+ if (this.rafId != null && this.targetWindow) {
251
+ this.targetWindow.cancelAnimationFrame(this.rafId);
252
+ this.rafId = null;
253
+ }
254
+ this.scrollState = null;
234
255
  this.scrollElement = null;
235
256
  this.targetWindow = null;
236
257
  };
@@ -269,6 +290,9 @@ class Virtualizer {
269
290
  this.scrollDirection = isScrolling ? this.getScrollOffset() < offset ? "forward" : "backward" : null;
270
291
  this.scrollOffset = offset;
271
292
  this.isScrolling = isScrolling;
293
+ if (this.scrollState) {
294
+ this.scheduleScrollReconcile();
295
+ }
272
296
  this.maybeNotify();
273
297
  })
274
298
  );
@@ -278,6 +302,7 @@ class Virtualizer {
278
302
  });
279
303
  }
280
304
  };
305
+ this.rafId = null;
281
306
  this.getSize = () => {
282
307
  if (!this.options.enabled) {
283
308
  this.scrollRect = null;
@@ -328,9 +353,10 @@ class Virtualizer {
328
353
  this.options.scrollMargin,
329
354
  this.options.getItemKey,
330
355
  this.options.enabled,
331
- this.options.lanes
356
+ this.options.lanes,
357
+ this.options.laneAssignmentMode
332
358
  ],
333
- (count, paddingStart, scrollMargin, getItemKey, enabled, lanes) => {
359
+ (count, paddingStart, scrollMargin, getItemKey, enabled, lanes, laneAssignmentMode) => {
334
360
  const lanesChanged = this.prevLanes !== void 0 && this.prevLanes !== lanes;
335
361
  if (lanesChanged) {
336
362
  this.lanesChangedFlag = true;
@@ -343,7 +369,8 @@ class Virtualizer {
343
369
  scrollMargin,
344
370
  getItemKey,
345
371
  enabled,
346
- lanes
372
+ lanes,
373
+ laneAssignmentMode
347
374
  };
348
375
  },
349
376
  {
@@ -352,7 +379,15 @@ class Virtualizer {
352
379
  );
353
380
  this.getMeasurements = memo(
354
381
  () => [this.getMeasurementOptions(), this.itemSizeCache],
355
- ({ count, paddingStart, scrollMargin, getItemKey, enabled, lanes }, itemSizeCache) => {
382
+ ({
383
+ count,
384
+ paddingStart,
385
+ scrollMargin,
386
+ getItemKey,
387
+ enabled,
388
+ lanes,
389
+ laneAssignmentMode
390
+ }, itemSizeCache) => {
356
391
  if (!enabled) {
357
392
  this.measurementsCache = [];
358
393
  this.itemSizeCache.clear();
@@ -400,6 +435,7 @@ class Virtualizer {
400
435
  const cachedLane = this.laneAssignments.get(i);
401
436
  let lane;
402
437
  let start;
438
+ const shouldCacheLane = laneAssignmentMode === "estimate" || itemSizeCache.has(key);
403
439
  if (cachedLane !== void 0 && this.options.lanes > 1) {
404
440
  lane = cachedLane;
405
441
  const prevIndex = laneLastIndex[lane];
@@ -409,7 +445,7 @@ class Virtualizer {
409
445
  const furthestMeasurement = this.options.lanes === 1 ? measurements[i - 1] : this.getFurthestMeasurement(measurements, i);
410
446
  start = furthestMeasurement ? furthestMeasurement.end + this.options.gap : paddingStart + scrollMargin;
411
447
  lane = furthestMeasurement ? furthestMeasurement.lane : i % this.options.lanes;
412
- if (this.options.lanes > 1) {
448
+ if (this.options.lanes > 1 && shouldCacheLane) {
413
449
  this.laneAssignments.set(i, lane);
414
450
  }
415
451
  }
@@ -496,13 +532,38 @@ class Virtualizer {
496
532
  }
497
533
  return parseInt(indexStr, 10);
498
534
  };
499
- this._measureElement = (node, entry) => {
500
- const index = this.indexFromElement(node);
501
- const item = this.measurementsCache[index];
502
- if (!item) {
535
+ this.shouldMeasureDuringScroll = (index) => {
536
+ var _a;
537
+ if (!this.scrollState || this.scrollState.behavior !== "smooth") {
538
+ return true;
539
+ }
540
+ const scrollIndex = this.scrollState.index ?? ((_a = this.getVirtualItemForOffset(this.scrollState.lastTargetOffset)) == null ? void 0 : _a.index);
541
+ if (scrollIndex !== void 0 && this.range) {
542
+ const bufferSize = Math.max(
543
+ this.options.overscan,
544
+ Math.ceil((this.range.endIndex - this.range.startIndex) / 2)
545
+ );
546
+ const minIndex = Math.max(0, scrollIndex - bufferSize);
547
+ const maxIndex = Math.min(
548
+ this.options.count - 1,
549
+ scrollIndex + bufferSize
550
+ );
551
+ return index >= minIndex && index <= maxIndex;
552
+ }
553
+ return true;
554
+ };
555
+ this.measureElement = (node) => {
556
+ if (!node) {
557
+ this.elementsCache.forEach((cached, key2) => {
558
+ if (!cached.isConnected) {
559
+ this.observer.unobserve(cached);
560
+ this.elementsCache.delete(key2);
561
+ }
562
+ });
503
563
  return;
504
564
  }
505
- const key = item.key;
565
+ const index = this.indexFromElement(node);
566
+ const key = this.options.getItemKey(index);
506
567
  const prevNode = this.elementsCache.get(key);
507
568
  if (prevNode !== node) {
508
569
  if (prevNode) {
@@ -511,19 +572,18 @@ class Virtualizer {
511
572
  this.observer.observe(node);
512
573
  this.elementsCache.set(key, node);
513
574
  }
514
- if (node.isConnected) {
515
- this.resizeItem(index, this.options.measureElement(node, entry, this));
575
+ if ((!this.isScrolling || this.scrollState) && this.shouldMeasureDuringScroll(index)) {
576
+ this.resizeItem(index, this.options.measureElement(node, void 0, this));
516
577
  }
517
578
  };
518
579
  this.resizeItem = (index, size) => {
580
+ var _a;
519
581
  const item = this.measurementsCache[index];
520
- if (!item) {
521
- return;
522
- }
582
+ if (!item) return;
523
583
  const itemSize = this.itemSizeCache.get(item.key) ?? item.size;
524
584
  const delta = size - itemSize;
525
585
  if (delta !== 0) {
526
- if (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) : item.start < this.getScrollOffset() + this.scrollAdjustments) {
586
+ if (((_a = this.scrollState) == null ? void 0 : _a.behavior) !== "smooth" && (this.shouldAdjustScrollPositionOnItemSizeChange !== void 0 ? this.shouldAdjustScrollPositionOnItemSizeChange(item, delta, this) : item.start < this.getScrollOffset() + this.scrollAdjustments)) {
527
587
  if (process.env.NODE_ENV !== "production" && this.options.debug) {
528
588
  console.info("correction", delta);
529
589
  }
@@ -537,18 +597,6 @@ class Virtualizer {
537
597
  this.notify(false);
538
598
  }
539
599
  };
540
- this.measureElement = (node) => {
541
- if (!node) {
542
- this.elementsCache.forEach((cached, key) => {
543
- if (!cached.isConnected) {
544
- this.observer.unobserve(cached);
545
- this.elementsCache.delete(key);
546
- }
547
- });
548
- return;
549
- }
550
- this._measureElement(node, void 0);
551
- };
552
600
  this.getVirtualItems = memo(
553
601
  () => [this.getVirtualIndexes(), this.getMeasurements()],
554
602
  (indexes, measurements) => {
@@ -605,12 +653,10 @@ class Virtualizer {
605
653
  };
606
654
  this.getOffsetForIndex = (index, align = "auto") => {
607
655
  index = Math.max(0, Math.min(index, this.options.count - 1));
608
- const item = this.measurementsCache[index];
609
- if (!item) {
610
- return void 0;
611
- }
612
656
  const size = this.getSize();
613
657
  const scrollOffset = this.getScrollOffset();
658
+ const item = this.measurementsCache[index];
659
+ if (!item) return;
614
660
  if (align === "auto") {
615
661
  if (item.end >= scrollOffset + size - this.options.scrollPaddingEnd) {
616
662
  align = "end";
@@ -629,85 +675,55 @@ class Virtualizer {
629
675
  align
630
676
  ];
631
677
  };
632
- this.isDynamicMode = () => this.elementsCache.size > 0;
633
- this.scrollToOffset = (toOffset, { align = "start", behavior } = {}) => {
634
- if (behavior === "smooth" && this.isDynamicMode()) {
635
- console.warn(
636
- "The `smooth` scroll behavior is not fully supported with dynamic size."
637
- );
638
- }
639
- this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {
640
- adjustments: void 0,
641
- behavior
642
- });
678
+ this.scrollToOffset = (toOffset, { align = "start", behavior = "auto" } = {}) => {
679
+ const offset = this.getOffsetForAlignment(toOffset, align);
680
+ const now = this.now();
681
+ this.scrollState = {
682
+ index: null,
683
+ align,
684
+ behavior,
685
+ startedAt: now,
686
+ lastTargetOffset: offset,
687
+ stableFrames: 0
688
+ };
689
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
690
+ this.scheduleScrollReconcile();
643
691
  };
644
- this.scrollToIndex = (index, { align: initialAlign = "auto", behavior } = {}) => {
645
- if (behavior === "smooth" && this.isDynamicMode()) {
646
- console.warn(
647
- "The `smooth` scroll behavior is not fully supported with dynamic size."
648
- );
649
- }
692
+ this.scrollToIndex = (index, {
693
+ align: initialAlign = "auto",
694
+ behavior = "auto"
695
+ } = {}) => {
650
696
  index = Math.max(0, Math.min(index, this.options.count - 1));
651
- this.currentScrollToIndex = index;
652
- let attempts = 0;
653
- const maxAttempts = 10;
654
- const tryScroll = (currentAlign) => {
655
- if (!this.targetWindow) return;
656
- const offsetInfo = this.getOffsetForIndex(index, currentAlign);
657
- if (!offsetInfo) {
658
- console.warn("Failed to get offset for index:", index);
659
- return;
660
- }
661
- const [offset, align] = offsetInfo;
662
- this._scrollToOffset(offset, { adjustments: void 0, behavior });
663
- this.targetWindow.requestAnimationFrame(() => {
664
- if (!this.targetWindow) return;
665
- const verify = () => {
666
- if (this.currentScrollToIndex !== index) return;
667
- const currentOffset = this.getScrollOffset();
668
- const afterInfo = this.getOffsetForIndex(index, align);
669
- if (!afterInfo) {
670
- console.warn("Failed to get offset for index:", index);
671
- return;
672
- }
673
- if (!approxEqual(afterInfo[0], currentOffset)) {
674
- scheduleRetry(align);
675
- }
676
- };
677
- if (this.isDynamicMode()) {
678
- this.targetWindow.requestAnimationFrame(verify);
679
- } else {
680
- verify();
681
- }
682
- });
683
- };
684
- const scheduleRetry = (align) => {
685
- if (!this.targetWindow) return;
686
- if (this.currentScrollToIndex !== index) return;
687
- attempts++;
688
- if (attempts < maxAttempts) {
689
- if (process.env.NODE_ENV !== "production" && this.options.debug) {
690
- console.info("Schedule retry", attempts, maxAttempts);
691
- }
692
- this.targetWindow.requestAnimationFrame(() => tryScroll(align));
693
- } else {
694
- console.warn(
695
- `Failed to scroll to index ${index} after ${maxAttempts} attempts.`
696
- );
697
- }
697
+ const offsetInfo = this.getOffsetForIndex(index, initialAlign);
698
+ if (!offsetInfo) {
699
+ return;
700
+ }
701
+ const [offset, align] = offsetInfo;
702
+ const now = this.now();
703
+ this.scrollState = {
704
+ index,
705
+ align,
706
+ behavior,
707
+ startedAt: now,
708
+ lastTargetOffset: offset,
709
+ stableFrames: 0
698
710
  };
699
- tryScroll(initialAlign);
711
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
712
+ this.scheduleScrollReconcile();
700
713
  };
701
- this.scrollBy = (delta, { behavior } = {}) => {
702
- if (behavior === "smooth" && this.isDynamicMode()) {
703
- console.warn(
704
- "The `smooth` scroll behavior is not fully supported with dynamic size."
705
- );
706
- }
707
- this._scrollToOffset(this.getScrollOffset() + delta, {
708
- adjustments: void 0,
709
- behavior
710
- });
714
+ this.scrollBy = (delta, { behavior = "auto" } = {}) => {
715
+ const offset = this.getScrollOffset() + delta;
716
+ const now = this.now();
717
+ this.scrollState = {
718
+ index: null,
719
+ align: "start",
720
+ behavior,
721
+ startedAt: now,
722
+ lastTargetOffset: offset,
723
+ stableFrames: 0
724
+ };
725
+ this._scrollToOffset(offset, { adjustments: void 0, behavior });
726
+ this.scheduleScrollReconcile();
711
727
  };
712
728
  this.getTotalSize = () => {
713
729
  var _a;
@@ -747,6 +763,49 @@ class Virtualizer {
747
763
  };
748
764
  this.setOptions(opts);
749
765
  }
766
+ scheduleScrollReconcile() {
767
+ if (!this.targetWindow) {
768
+ this.scrollState = null;
769
+ return;
770
+ }
771
+ if (this.rafId != null) return;
772
+ this.rafId = this.targetWindow.requestAnimationFrame(() => {
773
+ this.rafId = null;
774
+ this.reconcileScroll();
775
+ });
776
+ }
777
+ reconcileScroll() {
778
+ if (!this.scrollState) return;
779
+ const el = this.scrollElement;
780
+ if (!el) return;
781
+ const MAX_RECONCILE_MS = 5e3;
782
+ if (this.now() - this.scrollState.startedAt > MAX_RECONCILE_MS) {
783
+ this.scrollState = null;
784
+ return;
785
+ }
786
+ const offsetInfo = this.scrollState.index != null ? this.getOffsetForIndex(this.scrollState.index, this.scrollState.align) : void 0;
787
+ const targetOffset = offsetInfo ? offsetInfo[0] : this.scrollState.lastTargetOffset;
788
+ const STABLE_FRAMES = 1;
789
+ const targetChanged = targetOffset !== this.scrollState.lastTargetOffset;
790
+ if (!targetChanged && approxEqual(targetOffset, this.getScrollOffset())) {
791
+ this.scrollState.stableFrames++;
792
+ if (this.scrollState.stableFrames >= STABLE_FRAMES) {
793
+ this.scrollState = null;
794
+ return;
795
+ }
796
+ } else {
797
+ this.scrollState.stableFrames = 0;
798
+ if (targetChanged) {
799
+ this.scrollState.lastTargetOffset = targetOffset;
800
+ this.scrollState.behavior = "auto";
801
+ this._scrollToOffset(targetOffset, {
802
+ adjustments: void 0,
803
+ behavior: "auto"
804
+ });
805
+ }
806
+ }
807
+ this.scheduleScrollReconcile();
808
+ }
750
809
  }
751
810
  const findNearestBinarySearch = (low, high, getCurrentValue, value) => {
752
811
  while (low <= high) {
@@ -2,10 +2,14 @@
2
2
 
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
- const parseJson = require('./parseJson.cjs');
5
+ const ky = require('ky');
6
6
 
7
- const addBodyJsonHook = async (error) => {
8
- error.response.bodyJson = await parseJson.parseJSON(error.response);
7
+ const addBodyJsonHook = async ({ error }) => {
8
+ if (!ky.isHTTPError(error)) {
9
+ return error;
10
+ }
11
+ const bodyJson = error.data ?? {};
12
+ error.response.bodyJson = bodyJson;
9
13
  return error;
10
14
  };
11
15
 
@@ -1,7 +1,11 @@
1
- import { parseJSON } from './parseJson.js';
1
+ import { isHTTPError } from 'ky';
2
2
 
3
- const addBodyJsonHook = async (error) => {
4
- error.response.bodyJson = await parseJSON(error.response);
3
+ const addBodyJsonHook = async ({ error }) => {
4
+ if (!isHTTPError(error)) {
5
+ return error;
6
+ }
7
+ const bodyJson = error.data ?? {};
8
+ error.response.bodyJson = bodyJson;
5
9
  return error;
6
10
  };
7
11
 
package/package.json CHANGED
@@ -1,65 +1,66 @@
1
- {
2
- "name": "lkd-web-kit",
3
- "version": "0.7.31",
4
- "description": "A template for creating React component libraries with Vite.",
5
- "author": "LKD",
6
- "license": "MIT",
7
- "type": "module",
8
- "main": "./dist/index.cjs",
9
- "module": "./dist/index.js",
10
- "types": "./dist/index.d.ts",
11
- "exports": {
12
- ".": {
13
- "types": "./dist/index.d.ts",
14
- "require": "./dist/index.cjs",
15
- "import": "./dist/index.js"
16
- }
17
- },
18
- "sideEffects": false,
19
- "files": [
20
- "dist"
21
- ],
22
- "scripts": {
23
- "test": "vitest run",
24
- "test:watch": "vitest",
25
- "build": "tsc && vite build",
26
- "lint": "biome check",
27
- "format": "biome format --write",
28
- "prepublishOnly": "npm run build"
29
- },
30
- "devDependencies": {
31
- "@biomejs/biome": "2.3.8",
32
- "@testing-library/jest-dom": "^6.8.0",
33
- "@testing-library/react": "^16.3.0",
34
- "@testing-library/user-event": "^14.6.1",
35
- "@types/node": "^22.17.2",
36
- "@types/react": "^19.1.10",
37
- "@types/react-dom": "^19.1.7",
38
- "@vitejs/plugin-react-swc": "^3.11.0",
39
- "@vitest/coverage-v8": "^3.2.4",
40
- "jsdom": "^26.1.0",
41
- "rollup-preserve-directives": "^1.1.3",
42
- "typescript": "^5.9.2",
43
- "vite": "^7.1.3",
44
- "vite-plugin-dts": "^4.5.4",
45
- "vitest": "^3.2.4"
46
- },
47
- "peerDependencies": {
48
- "@mantine/core": "^8.3.18",
49
- "@mantine/dates": "^8.3.18",
50
- "@mantine/hooks": "^8.3.18",
51
- "@mantine/notifications": "^8.3.18",
52
- "@tanstack/react-query": "^5.91.2",
53
- "clsx": "^2.1.1",
54
- "ky": "^1.14.3",
55
- "next": "^16.2.0",
56
- "react": "^19.2.4",
57
- "react-dom": "^19.2.4",
58
- "react-hook-form": "^7.71.2",
59
- "react-query-kit": "^3.3.2",
60
- "zod": "^4.3.6"
61
- },
62
- "dependencies": {
63
- "@tanstack/react-virtual": "^3.13.19"
64
- }
65
- }
1
+ {
2
+ "name": "lkd-web-kit",
3
+ "version": "0.8.0",
4
+ "description": "A template for creating React component libraries with Vite.",
5
+ "author": "LKD",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "main": "./dist/index.cjs",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "require": "./dist/index.cjs",
15
+ "import": "./dist/index.js"
16
+ }
17
+ },
18
+ "sideEffects": false,
19
+ "engines": {
20
+ "node": ">=22"
21
+ },
22
+ "files": ["dist"],
23
+ "scripts": {
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "build": "tsc && vite build",
27
+ "lint": "biome check",
28
+ "format": "biome format --write",
29
+ "prepublishOnly": "npm run build"
30
+ },
31
+ "devDependencies": {
32
+ "@biomejs/biome": "2.3.8",
33
+ "@testing-library/jest-dom": "^6.8.0",
34
+ "@testing-library/react": "^16.3.0",
35
+ "@testing-library/user-event": "^14.6.1",
36
+ "@types/node": "^22.17.2",
37
+ "@types/react": "^19.2.14",
38
+ "@types/react-dom": "^19.2.3",
39
+ "@vitejs/plugin-react-swc": "^3.11.0",
40
+ "@vitest/coverage-v8": "^3.2.4",
41
+ "jsdom": "^26.1.0",
42
+ "rollup-preserve-directives": "^1.1.3",
43
+ "typescript": "^5.9.2",
44
+ "vite": "^7.1.3",
45
+ "vite-plugin-dts": "^4.5.4",
46
+ "vitest": "^3.2.4"
47
+ },
48
+ "peerDependencies": {
49
+ "@mantine/core": "^9.1.0",
50
+ "@mantine/dates": "^9.1.0",
51
+ "@mantine/hooks": "^9.1.0",
52
+ "@mantine/notifications": "^9.1.0",
53
+ "@tanstack/react-query": "^5.100.0",
54
+ "clsx": "^2.1.1",
55
+ "ky": "^2.0.2",
56
+ "next": "^16.2.4",
57
+ "react": "^19.2.5",
58
+ "react-dom": "^19.2.5",
59
+ "react-hook-form": "^7.73.1",
60
+ "react-query-kit": "^3.3.2",
61
+ "zod": "^4.3.6"
62
+ },
63
+ "dependencies": {
64
+ "@tanstack/react-virtual": "^3.13.24"
65
+ }
66
+ }