selective-ui 1.3.1 → 1.4.1

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/dist/selective-ui.css +0 -6
  2. package/dist/selective-ui.css.map +1 -1
  3. package/dist/selective-ui.esm.js +271 -559
  4. package/dist/selective-ui.esm.js.map +1 -1
  5. package/dist/selective-ui.esm.min.js +2 -2
  6. package/dist/selective-ui.esm.min.js.br +0 -0
  7. package/dist/selective-ui.min.css +1 -1
  8. package/dist/selective-ui.min.css.br +0 -0
  9. package/dist/selective-ui.min.js +2 -2
  10. package/dist/selective-ui.min.js.br +0 -0
  11. package/dist/selective-ui.umd.js +273 -561
  12. package/dist/selective-ui.umd.js.map +1 -1
  13. package/package.json +12 -12
  14. package/src/ts/adapter/mixed-adapter.ts +147 -68
  15. package/src/ts/components/accessorybox.ts +14 -11
  16. package/src/ts/components/directive.ts +1 -1
  17. package/src/ts/components/option-handle.ts +12 -9
  18. package/src/ts/components/placeholder.ts +5 -5
  19. package/src/ts/components/popup/empty-state.ts +5 -5
  20. package/src/ts/components/popup/loading-state.ts +5 -5
  21. package/src/ts/components/popup/popup.ts +138 -76
  22. package/src/ts/components/searchbox.ts +17 -13
  23. package/src/ts/components/selectbox.ts +258 -83
  24. package/src/ts/core/base/adapter.ts +39 -14
  25. package/src/ts/core/base/fenwick.ts +3 -2
  26. package/src/ts/core/base/lifecycle.ts +14 -4
  27. package/src/ts/core/base/model.ts +17 -15
  28. package/src/ts/core/base/recyclerview.ts +7 -5
  29. package/src/ts/core/base/view.ts +10 -5
  30. package/src/ts/core/base/virtual-recyclerview.ts +89 -37
  31. package/src/ts/core/model-manager.ts +48 -21
  32. package/src/ts/core/search-controller.ts +174 -56
  33. package/src/ts/global.ts +5 -8
  34. package/src/ts/index.ts +2 -2
  35. package/src/ts/models/group-model.ts +33 -8
  36. package/src/ts/models/option-model.ts +60 -19
  37. package/src/ts/services/dataset-observer.ts +6 -3
  38. package/src/ts/services/ea-observer.ts +1 -1
  39. package/src/ts/services/effector.ts +22 -12
  40. package/src/ts/services/refresher.ts +7 -3
  41. package/src/ts/services/resize-observer.ts +24 -11
  42. package/src/ts/services/select-observer.ts +2 -2
  43. package/src/ts/types/components/popup.type.ts +18 -1
  44. package/src/ts/types/components/searchbox.type.ts +43 -30
  45. package/src/ts/types/components/state.box.type.ts +1 -1
  46. package/src/ts/types/core/base/adapter.type.ts +13 -5
  47. package/src/ts/types/core/base/lifecycle.type.ts +1 -2
  48. package/src/ts/types/core/base/model.type.ts +3 -3
  49. package/src/ts/types/core/base/recyclerview.type.ts +7 -5
  50. package/src/ts/types/core/base/view.type.ts +6 -6
  51. package/src/ts/types/core/base/virtual-recyclerview.type.ts +45 -46
  52. package/src/ts/types/core/search-controller.type.ts +18 -2
  53. package/src/ts/types/css.d.ts +1 -0
  54. package/src/ts/types/plugins/plugin.type.ts +2 -2
  55. package/src/ts/types/services/effector.type.ts +25 -25
  56. package/src/ts/types/services/resize-observer.type.ts +23 -12
  57. package/src/ts/types/utils/callback-scheduler.type.ts +2 -2
  58. package/src/ts/types/utils/ievents.type.ts +1 -1
  59. package/src/ts/types/utils/istorage.type.ts +62 -60
  60. package/src/ts/types/utils/libs.type.ts +19 -17
  61. package/src/ts/types/utils/selective.type.ts +6 -3
  62. package/src/ts/types/views/view.group.type.ts +9 -5
  63. package/src/ts/types/views/view.option.type.ts +39 -17
  64. package/src/ts/utils/callback-scheduler.ts +12 -7
  65. package/src/ts/utils/ievents.ts +12 -5
  66. package/src/ts/utils/istorage.ts +5 -3
  67. package/src/ts/utils/libs.ts +122 -43
  68. package/src/ts/utils/selective.ts +15 -8
  69. package/src/ts/views/group-view.ts +11 -9
  70. package/src/ts/views/option-view.ts +37 -18
@@ -62,9 +62,12 @@ import { LifecycleState } from "src/ts/types/core/base/lifecycle.type";
62
62
  * @see {@link ModelContract}
63
63
  */
64
64
  export class Adapter<
65
- TItem extends ModelContract<any, any> & { view: TViewer | null; isInit: boolean },
66
- TViewer extends ViewContract<any>
67
- > extends Lifecycle implements AdapterContract<TItem> {
65
+ TItem extends ModelContract<any, any> & { view?: TViewer; isInit: boolean },
66
+ TViewer extends ViewContract<any>,
67
+ >
68
+ extends Lifecycle
69
+ implements AdapterContract<TItem>
70
+ {
68
71
  /**
69
72
  * Current list of items managed by the adapter.
70
73
  *
@@ -118,7 +121,11 @@ export class Adapter<
118
121
  * @param {number} position - Index of the item within the adapter item list.
119
122
  * @returns {void}
120
123
  */
121
- public onViewHolder(item: TItem, viewer: TViewer | null, position: number): void {
124
+ public onViewHolder(
125
+ item: TItem,
126
+ viewer?: TViewer,
127
+ position?: number,
128
+ ): void {
122
129
  void position;
123
130
 
124
131
  const v = viewer;
@@ -142,8 +149,15 @@ export class Adapter<
142
149
  * @returns {void}
143
150
  * @see {@link changingProp}
144
151
  */
145
- public onPropChanging(propName: string, callback: (...args: unknown[]) => void): void {
146
- Libs.callbackScheduler.on(`${propName}ing_${this.adapterKey}`, callback, { debounce: 0 });
152
+ public onPropChanging(
153
+ propName: string,
154
+ callback: (...args: unknown[]) => void,
155
+ ): void {
156
+ Libs.callbackScheduler.on(
157
+ `${propName}ing_${this.adapterKey}`,
158
+ callback,
159
+ { debounce: 0 },
160
+ );
147
161
  }
148
162
 
149
163
  /**
@@ -159,8 +173,13 @@ export class Adapter<
159
173
  * @returns {void}
160
174
  * @see {@link changeProp}
161
175
  */
162
- public onPropChanged(propName: string, callback: (...args: unknown[]) => void): void {
163
- Libs.callbackScheduler.on(`${propName}_${this.adapterKey}`, callback, { debounce: 0 });
176
+ public onPropChanged(
177
+ propName: string,
178
+ callback: (...args: unknown[]) => void,
179
+ ): void {
180
+ Libs.callbackScheduler.on(`${propName}_${this.adapterKey}`, callback, {
181
+ debounce: 0,
182
+ });
164
183
  }
165
184
 
166
185
  /**
@@ -174,7 +193,10 @@ export class Adapter<
174
193
  * @returns {Promise<void>} Resolves when scheduled callbacks complete.
175
194
  */
176
195
  public changeProp(propName: string, ...params: unknown[]): Promise<void> {
177
- return Libs.callbackScheduler.run(`${propName}_${this.adapterKey}`, ...params);
196
+ return Libs.callbackScheduler.run(
197
+ `${propName}_${this.adapterKey}`,
198
+ ...params,
199
+ );
178
200
  }
179
201
 
180
202
  /**
@@ -188,7 +210,10 @@ export class Adapter<
188
210
  * @returns {Promise<void>} Resolves when scheduled callbacks complete.
189
211
  */
190
212
  public changingProp(propName: string, ...params: unknown[]): Promise<void> {
191
- return Libs.callbackScheduler.run(`${propName}ing_${this.adapterKey}`, ...params);
213
+ return Libs.callbackScheduler.run(
214
+ `${propName}ing_${this.adapterKey}`,
215
+ ...params,
216
+ );
192
217
  }
193
218
 
194
219
  /**
@@ -198,9 +223,9 @@ export class Adapter<
198
223
  *
199
224
  * @param {HTMLElement} parent - Container element that will host the viewer.
200
225
  * @param {TItem} item - The model for which the viewer is created.
201
- * @returns {TViewer | null} The created viewer instance; `null` by default.
226
+ * @returns {TViewer} The created viewer instance; `null` by default.
202
227
  */
203
- public viewHolder(parent: HTMLElement, item: TItem): TViewer | null {
228
+ public viewHolder?(parent: HTMLElement, item: TItem): TViewer {
204
229
  void parent;
205
230
  void item;
206
231
  return null;
@@ -317,9 +342,9 @@ export class Adapter<
317
342
  }
318
343
 
319
344
  this.recyclerView = null;
320
- this.items.forEach(item => {
345
+ this.items.forEach((item) => {
321
346
  item?.destroy?.();
322
347
  });
323
348
  this.items = [];
324
349
  }
325
- }
350
+ }
@@ -131,7 +131,8 @@ export class Fenwick extends Lifecycle {
131
131
  * Returns 0 if the first element already exceeds `target`.
132
132
  */
133
133
  public lowerBoundPrefix(target: number): number {
134
- let idx = 0, bitMask = 1;
134
+ let idx = 0,
135
+ bitMask = 1;
135
136
  while (bitMask << 1 <= this.stackNum) bitMask <<= 1;
136
137
 
137
138
  let cur = 0;
@@ -144,4 +145,4 @@ export class Fenwick extends Lifecycle {
144
145
  }
145
146
  return idx;
146
147
  }
147
- }
148
+ }
@@ -1,4 +1,8 @@
1
- import { LifecycleHookContext, LifecycleHooks, LifecycleState } from "src/ts/types/core/base/lifecycle.type";
1
+ import {
2
+ LifecycleHookContext,
3
+ LifecycleHooks,
4
+ LifecycleState,
5
+ } from "src/ts/types/core/base/lifecycle.type";
2
6
 
3
7
  type LifecycleHookName = keyof LifecycleHooks;
4
8
 
@@ -59,7 +63,10 @@ export class Lifecycle {
59
63
  * This map is initialized with keys for all supported hooks in the constructor.
60
64
  * Callbacks are cleared on {@link destroy}.
61
65
  */
62
- private hooks: Map<LifecycleHookName, Set<(ctx: LifecycleHookContext) => void>> = new Map();
66
+ private hooks: Map<
67
+ LifecycleHookName,
68
+ Set<(ctx: LifecycleHookContext) => void>
69
+ > = new Map();
63
70
 
64
71
  /**
65
72
  * Constructs the lifecycle manager and pre-registers hook containers.
@@ -98,7 +105,10 @@ export class Lifecycle {
98
105
  * @param {(ctx: LifecycleHookContext) => void} fn - Callback to remove.
99
106
  * @returns {this} The current instance (chainable).
100
107
  */
101
- off(hook: LifecycleHookName, fn: (ctx: LifecycleHookContext) => void): this {
108
+ off(
109
+ hook: LifecycleHookName,
110
+ fn: (ctx: LifecycleHookContext) => void,
111
+ ): this {
102
112
  this.hooks.get(hook)!.delete(fn);
103
113
  return this;
104
114
  }
@@ -255,4 +265,4 @@ export class Lifecycle {
255
265
  set.clear();
256
266
  }
257
267
  }
258
- }
268
+ }
@@ -43,16 +43,18 @@ export class Model<
43
43
  TTarget extends HTMLElement,
44
44
  TTags extends Record<string, HTMLElement>,
45
45
  TView extends ViewContract<TTags>,
46
- TOptions = unknown
47
- > extends Lifecycle implements ModelContract<TTarget, TView> {
48
-
46
+ TOptions = unknown,
47
+ >
48
+ extends Lifecycle
49
+ implements ModelContract<TTarget, TView>
50
+ {
49
51
  /**
50
52
  * The currently bound target DOM element.
51
53
  *
52
54
  * This element typically represents the source-of-truth node in the host DOM (e.g., a native `<option>`).
53
55
  * May be replaced via {@link updateTarget} during reconciliation.
54
56
  */
55
- public targetElement: TTarget | null = null;
57
+ public targetElement?: TTarget;
56
58
 
57
59
  /**
58
60
  * Configuration options supplied at construction time.
@@ -66,25 +68,25 @@ export class Model<
66
68
  * Ownership: this model will destroy the view on {@link destroy}.
67
69
  * The view may be attached/assigned by external orchestrators (Adapter/RecyclerView) after construction.
68
70
  */
69
- public view: TView | null = null;
71
+ public view?: TView;
70
72
 
71
73
  /**
72
74
  * Position index used by list infrastructure for ordering/tracking.
73
75
  * Semantics are library-specific (e.g., top-level index or adapter position).
74
76
  */
75
- public position = -1;
77
+ public position: number = -1;
76
78
 
77
79
  /**
78
80
  * Indicates whether this model has completed its initial binding step.
79
81
  * Typically set by the adapter/view binding layer to prevent duplicate listener wiring.
80
82
  */
81
- public isInit = false;
83
+ public isInit: boolean = false;
82
84
 
83
85
  /**
84
86
  * Indicates whether this model has been removed/destroyed from the active dataset.
85
87
  * Set to `true` during {@link destroy}.
86
88
  */
87
- public isRemoved = false;
89
+ public isRemoved: boolean = false;
88
90
 
89
91
  /**
90
92
  * Returns the current "value" associated with the bound target element.
@@ -107,13 +109,13 @@ export class Model<
107
109
  * - Calls {@link Lifecycle.init} immediately (`NEW → INITIALIZED`).
108
110
  *
109
111
  * @param {TOptions} options - Configuration options for the model.
110
- * @param {TTarget | null} [targetElement=null] - Optional DOM element to bind.
111
- * @param {TView | null} [view=null] - Optional view responsible for rendering this model.
112
+ * @param {TTarget} [targetElement=null] - Optional DOM element to bind.
113
+ * @param {TView} [view=null] - Optional view responsible for rendering this model.
112
114
  */
113
115
  public constructor(
114
116
  options: TOptions,
115
- targetElement: TTarget | null = null,
116
- view: TView | null = null
117
+ targetElement?: TTarget,
118
+ view?: TView,
117
119
  ) {
118
120
  super();
119
121
  this.options = options;
@@ -134,10 +136,10 @@ export class Model<
134
136
  * - Assigns {@link targetElement}.
135
137
  * - Calls {@link Lifecycle.update} (guarded by lifecycle state).
136
138
  *
137
- * @param {TTarget | null} targetElement - The new DOM element to associate with this model.
139
+ * @param {TTarget} targetElement - The new DOM element to associate with this model.
138
140
  * @returns {void}
139
141
  */
140
- public updateTarget(targetElement: TTarget | null): void {
142
+ public updateTarget(targetElement?: TTarget): void {
141
143
  this.targetElement = targetElement;
142
144
  this.update();
143
145
  }
@@ -167,4 +169,4 @@ export class Model<
167
169
 
168
170
  super.destroy();
169
171
  }
170
- }
172
+ }
@@ -22,9 +22,11 @@ import { LifecycleState } from "src/ts/types/core/base/lifecycle.type";
22
22
  */
23
23
  export class RecyclerView<
24
24
  TItem extends ModelContract<any, any>,
25
- TAdapter extends AdapterContract<TItem>
26
- > extends Lifecycle implements RecyclerViewContract<TAdapter> {
27
-
25
+ TAdapter extends AdapterContract<TItem>,
26
+ >
27
+ extends Lifecycle
28
+ implements RecyclerViewContract<TAdapter>
29
+ {
28
30
  /** Root container that hosts rendered item views. */
29
31
  public viewElement: HTMLDivElement | null = null;
30
32
 
@@ -113,10 +115,10 @@ export class RecyclerView<
113
115
  if (this.is(LifecycleState.DESTROYED)) {
114
116
  return;
115
117
  }
116
-
118
+
117
119
  this.viewElement = null;
118
120
  this.adapter = null;
119
121
 
120
122
  super.destroy();
121
123
  }
122
- }
124
+ }
@@ -39,13 +39,16 @@ import { LifecycleState } from "src/ts/types/core/base/lifecycle.type";
39
39
  * @see {@link ViewContract}
40
40
  * @see {@link LifecycleState}
41
41
  */
42
- export class View<TTags extends Record<string, HTMLElement>> extends Lifecycle implements ViewContract<TTags> {
42
+ export class View<TTags extends Record<string, HTMLElement>>
43
+ extends Lifecycle
44
+ implements ViewContract<TTags>
45
+ {
43
46
  /**
44
47
  * Host container element into which this view's root element is rendered/attached.
45
48
  *
46
49
  * This reference is captured at construction time and cleared on {@link destroy}.
47
50
  */
48
- public parent: HTMLElement | null = null;
51
+ public parent?: HTMLElement;
49
52
 
50
53
  /**
51
54
  * Mounted view result containing:
@@ -54,7 +57,7 @@ export class View<TTags extends Record<string, HTMLElement>> extends Lifecycle i
54
57
  *
55
58
  * This is expected to be assigned by subclasses (or a mount helper) before {@link getView} is called.
56
59
  */
57
- public view: MountViewResult<TTags> | null = null;
60
+ public view?: MountViewResult<TTags>;
58
61
 
59
62
  /**
60
63
  * Creates a View bound to the specified parent container and initializes lifecycle state.
@@ -79,7 +82,9 @@ export class View<TTags extends Record<string, HTMLElement>> extends Lifecycle i
79
82
  */
80
83
  public getView(): HTMLElement {
81
84
  if (!this.view?.view) {
82
- throw new Error("View is not mounted. Did you forget to set this.view?");
85
+ throw new Error(
86
+ "View is not mounted. Did you forget to set this.view?",
87
+ );
83
88
  }
84
89
  return this.view.view;
85
90
  }
@@ -108,4 +113,4 @@ export class View<TTags extends Record<string, HTMLElement>> extends Lifecycle i
108
113
 
109
114
  super.destroy();
110
115
  }
111
- }
116
+ }
@@ -2,7 +2,10 @@ import { ModelContract } from "src/ts/types/core/base/model.type";
2
2
  import { RecyclerView } from "./recyclerview";
3
3
  import { AdapterContract } from "src/ts/types/core/base/adapter.type";
4
4
  import { Libs } from "src/ts/utils/libs";
5
- import { VirtualOptions, VirtualRecyclerViewTags } from "src/ts/types/core/base/virtual-recyclerview.type";
5
+ import {
6
+ VirtualOptions,
7
+ VirtualRecyclerViewTags,
8
+ } from "src/ts/types/core/base/virtual-recyclerview.type";
6
9
  import { Lifecycle } from "./lifecycle";
7
10
  import { LifecycleState } from "src/ts/types/core/base/lifecycle.type";
8
11
  import { Fenwick } from "./fenwick";
@@ -58,7 +61,7 @@ import { Fenwick } from "./fenwick";
58
61
  */
59
62
  export class VirtualRecyclerView<
60
63
  TItem extends ModelContract<any, any>,
61
- TAdapter extends AdapterContract<TItem>
64
+ TAdapter extends AdapterContract<TItem>,
62
65
  > extends RecyclerView<TItem, TAdapter> {
63
66
  /**
64
67
  * Virtualization settings (materialized to `Required<VirtualOptions>`).
@@ -109,8 +112,8 @@ export class VirtualRecyclerView<
109
112
  private resizeObs?: ResizeObserver;
110
113
 
111
114
  /** Pending animation frame ids for window and measurement. */
112
- private rafId: number | null = null;
113
- private measureRaf: number | null = null;
115
+ private rafId?: number;
116
+ private measureRaf?: number;
114
117
 
115
118
  /** Re-entrancy/suspension flags used to prevent feedback loops. */
116
119
  private updating = false;
@@ -138,9 +141,9 @@ export class VirtualRecyclerView<
138
141
  *
139
142
  * Note: The virtualization scaffold is built when an adapter is set via {@link setAdapter}.
140
143
  *
141
- * @param {HTMLDivElement | null} [viewElement=null] - Optional root container for the recycler view.
144
+ * @param {HTMLDivElement} [viewElement=null] - Optional root container for the recycler view.
142
145
  */
143
- constructor(viewElement: HTMLDivElement | null = null) {
146
+ constructor(viewElement?: HTMLDivElement) {
144
147
  super(viewElement);
145
148
  }
146
149
 
@@ -187,24 +190,37 @@ export class VirtualRecyclerView<
187
190
 
188
191
  this.viewElement.replaceChildren();
189
192
 
190
- const nodeMounted = Libs.mountNode({
191
- PadTop: { tag: { node: "div", classList: "seui-virtual-pad-top" } },
192
- ItemsHost:{ tag: { node: "div", classList: "seui-virtual-items" } },
193
- PadBottom:{ tag: { node: "div", classList: "seui-virtual-pad-bottom" } },
194
- }, this.viewElement) as VirtualRecyclerViewTags;
193
+ const nodeMounted = Libs.mountNode<VirtualRecyclerViewTags>(
194
+ {
195
+ PadTop: {
196
+ tag: { node: "div", classList: "seui-virtual-pad-top" },
197
+ },
198
+ ItemsHost: {
199
+ tag: { node: "div", classList: "seui-virtual-items" },
200
+ },
201
+ PadBottom: {
202
+ tag: { node: "div", classList: "seui-virtual-pad-bottom" },
203
+ },
204
+ },
205
+ this.viewElement,
206
+ );
195
207
 
196
208
  this.PadTop = nodeMounted.PadTop;
197
209
  this.ItemsHost = nodeMounted.ItemsHost;
198
210
  this.PadBottom = nodeMounted.PadBottom;
199
211
 
200
- this.scrollEl = this.opts.scrollEl
201
- ?? (this.viewElement.closest(".seui-popup") as HTMLElement)
202
- ?? (this.viewElement.parentElement as HTMLElement);
212
+ this.scrollEl =
213
+ this.opts.scrollEl ??
214
+ (this.viewElement.closest(".seui-popup") as HTMLElement) ??
215
+ (this.viewElement.parentElement as HTMLElement);
203
216
 
204
- if (!this.scrollEl) throw new Error("VirtualRecyclerView: scrollEl not found");
217
+ if (!this.scrollEl)
218
+ throw new Error("VirtualRecyclerView: scrollEl not found");
205
219
 
206
220
  this.boundOnScroll = this.onScroll.bind(this);
207
- this.scrollEl.addEventListener("scroll", this.boundOnScroll, { passive: true });
221
+ this.scrollEl.addEventListener("scroll", this.boundOnScroll, {
222
+ passive: true,
223
+ });
208
224
 
209
225
  this.refresh(false);
210
226
  this.attachResizeObserverOnce();
@@ -249,7 +265,9 @@ export class VirtualRecyclerView<
249
265
  this.suspended = false;
250
266
 
251
267
  if (this.scrollEl && this.boundOnScroll) {
252
- this.scrollEl.addEventListener("scroll", this.boundOnScroll, { passive: true });
268
+ this.scrollEl.addEventListener("scroll", this.boundOnScroll, {
269
+ passive: true,
270
+ });
253
271
  }
254
272
 
255
273
  if (this.resumeResizeAfter) {
@@ -310,7 +328,10 @@ export class VirtualRecyclerView<
310
328
  * @param {{ scrollIntoView?: boolean }} [opt] - Optional behavior controls.
311
329
  * @returns {void}
312
330
  */
313
- public ensureRendered(index: number, opt?: { scrollIntoView?: boolean }): void {
331
+ public ensureRendered(
332
+ index: number,
333
+ opt?: { scrollIntoView?: boolean },
334
+ ): void {
314
335
  this.mountRange(index, index);
315
336
  if (opt?.scrollIntoView) this.scrollToIndex(index);
316
337
  }
@@ -334,7 +355,10 @@ export class VirtualRecyclerView<
334
355
  const topInContainer = this.offsetTopOf(index);
335
356
  const containerTop = this.containerTopInScroll();
336
357
  const target = containerTop + topInContainer;
337
- const maxScroll = Math.max(0, this.scrollEl.scrollHeight - this.scrollEl.clientHeight);
358
+ const maxScroll = Math.max(
359
+ 0,
360
+ this.scrollEl.scrollHeight - this.scrollEl.clientHeight,
361
+ );
338
362
 
339
363
  this.scrollEl.scrollTop = Math.min(Math.max(0, target), maxScroll);
340
364
  }
@@ -358,7 +382,7 @@ export class VirtualRecyclerView<
358
382
  }
359
383
 
360
384
  this.resizeObs?.disconnect();
361
- this.created.forEach(el => el.remove());
385
+ this.created.forEach((el) => el.remove());
362
386
  this.created.clear();
363
387
  }
364
388
 
@@ -442,7 +466,7 @@ export class VirtualRecyclerView<
442
466
  * @returns {void}
443
467
  */
444
468
  private resetState(): void {
445
- this.created.forEach(el => el.remove());
469
+ this.created.forEach((el) => el.remove());
446
470
  this.created.clear();
447
471
  this.heightCache = [];
448
472
  this.fenwick.reset(0);
@@ -557,7 +581,9 @@ export class VirtualRecyclerView<
557
581
  const now = performance.now();
558
582
  if (now - this.stickyCacheTick < 16) return this.stickyCacheVal;
559
583
 
560
- const sticky = this.scrollEl.querySelector(".seui-option-handle:not(.hide)") as HTMLElement | null;
584
+ const sticky = this.scrollEl.querySelector(
585
+ ".seui-option-handle:not(.hide)",
586
+ ) as HTMLElement | null;
561
587
  this.stickyCacheVal = sticky?.offsetHeight ?? 0;
562
588
  this.stickyCacheTick = now;
563
589
  return this.stickyCacheVal;
@@ -623,7 +649,7 @@ export class VirtualRecyclerView<
623
649
  private rebuildFenwick(count: number): void {
624
650
  const est = this.getEstimate();
625
651
  const arr = Array.from({ length: count }, (_, i) =>
626
- this.isIndexVisible(i) ? (this.heightCache[i] ?? est) : 0
652
+ this.isIndexVisible(i) ? (this.heightCache[i] ?? est) : 0,
627
653
  );
628
654
  this.fenwick.buildFrom(arr);
629
655
  }
@@ -738,8 +764,12 @@ export class VirtualRecyclerView<
738
764
  const next = el.nextElementSibling as HTMLElement | null;
739
765
 
740
766
  const needsReorder =
741
- (prev && Number(prev.getAttribute(VirtualRecyclerView.ATTR_INDEX)) > index) ||
742
- (next && Number(next.getAttribute(VirtualRecyclerView.ATTR_INDEX)) < index);
767
+ (prev &&
768
+ Number(prev.getAttribute(VirtualRecyclerView.ATTR_INDEX)) >
769
+ index) ||
770
+ (next &&
771
+ Number(next.getAttribute(VirtualRecyclerView.ATTR_INDEX)) <
772
+ index);
743
773
 
744
774
  if (needsReorder) {
745
775
  el.remove();
@@ -763,7 +793,13 @@ export class VirtualRecyclerView<
763
793
  if (this.resizeObs) return;
764
794
 
765
795
  this.resizeObs = new ResizeObserver(() => {
766
- if (this.suppressResize || this.suspended || !this.adapter || this.measureRaf != null) return;
796
+ if (
797
+ this.suppressResize ||
798
+ this.suspended ||
799
+ !this.adapter ||
800
+ this.measureRaf != null
801
+ )
802
+ return;
767
803
 
768
804
  this.measureRaf = requestAnimationFrame(() => {
769
805
  this.measureRaf = null;
@@ -794,7 +830,9 @@ export class VirtualRecyclerView<
794
830
  if (!this.isIndexVisible(i)) continue;
795
831
 
796
832
  const item = this.adapter.items[i];
797
- const el = (item as any)?.view?.getView?.() as HTMLElement | undefined;
833
+ const el = (item as any)?.view?.getView?.() as
834
+ | HTMLElement
835
+ | undefined;
798
836
  if (!el) continue;
799
837
 
800
838
  const newH = this.measureOuterHeight(el);
@@ -857,7 +895,8 @@ export class VirtualRecyclerView<
857
895
 
858
896
  const anchorIndex = this.findFirstVisibleIndex(stRel, count);
859
897
  const anchorTop = this.offsetTopOf(anchorIndex);
860
- const anchorDelta = containerTop + anchorTop - this.scrollEl.scrollTop;
898
+ const anchorDelta =
899
+ containerTop + anchorTop - this.scrollEl.scrollTop;
861
900
 
862
901
  const firstVis = this.findFirstVisibleIndex(stRel, count);
863
902
  if (firstVis === -1) {
@@ -868,12 +907,21 @@ export class VirtualRecyclerView<
868
907
  const est = this.getEstimate();
869
908
  const overscanPx = this.opts.overscan * est;
870
909
 
871
- let startIndex = this.nextVisibleFrom(
872
- Math.min(count - 1, this.fenwick.lowerBoundPrefix(Math.max(0, stRel - overscanPx))),
873
- count
874
- ) ?? firstVis;
875
-
876
- let endIndex = Math.min(count - 1, this.fenwick.lowerBoundPrefix(stRel + vhEff + overscanPx));
910
+ let startIndex =
911
+ this.nextVisibleFrom(
912
+ Math.min(
913
+ count - 1,
914
+ this.fenwick.lowerBoundPrefix(
915
+ Math.max(0, stRel - overscanPx),
916
+ ),
917
+ ),
918
+ count,
919
+ ) ?? firstVis;
920
+
921
+ let endIndex = Math.min(
922
+ count - 1,
923
+ this.fenwick.lowerBoundPrefix(stRel + vhEff + overscanPx),
924
+ );
877
925
 
878
926
  if (startIndex === this.start && endIndex === this.end) return;
879
927
 
@@ -900,8 +948,12 @@ export class VirtualRecyclerView<
900
948
 
901
949
  // Keep anchor item stable to prevent scroll jump
902
950
  const anchorTopNew = this.offsetTopOf(anchorIndex);
903
- const targetScroll = this.containerTopInScroll() + anchorTopNew - anchorDelta;
904
- const maxScroll = Math.max(0, this.scrollEl.scrollHeight - this.scrollEl.clientHeight);
951
+ const targetScroll =
952
+ this.containerTopInScroll() + anchorTopNew - anchorDelta;
953
+ const maxScroll = Math.max(
954
+ 0,
955
+ this.scrollEl.scrollHeight - this.scrollEl.clientHeight,
956
+ );
905
957
  const clamped = Math.min(Math.max(0, targetScroll), maxScroll);
906
958
 
907
959
  const heightChanged = Math.abs(anchorTopNew - anchorTop) > 1;
@@ -1036,4 +1088,4 @@ export class VirtualRecyclerView<
1036
1088
  private totalHeight(count: number): number {
1037
1089
  return this.fenwick.sum(count);
1038
1090
  }
1039
- }
1091
+ }