selective-ui 1.1.0 → 1.1.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.
- package/dist/selective-ui.esm.js +75 -24
- package/dist/selective-ui.esm.js.map +1 -1
- package/dist/selective-ui.esm.min.js +1 -1
- package/dist/selective-ui.esm.min.js.br +0 -0
- package/dist/selective-ui.min.js +1 -1
- package/dist/selective-ui.min.js.br +0 -0
- package/dist/selective-ui.umd.js +75 -24
- package/dist/selective-ui.umd.js.map +1 -1
- package/package.json +3 -1
- package/src/ts/components/popup.ts +70 -0
- package/src/ts/components/selectbox.ts +4 -0
- package/src/ts/core/model-manager.ts +3 -24
- package/src/ts/index.ts +2 -2
- package/src/ts/services/effector.ts +3 -1
- package/src/ts/types/services/effector.type.ts +14 -0
- package/src/ts/utils/libs.ts +1 -1
- package/src/ts/utils/selective.ts +4 -0
package/dist/selective-ui.esm.js
CHANGED
|
@@ -1449,6 +1449,9 @@ class Popup {
|
|
|
1449
1449
|
/**
|
|
1450
1450
|
* Enables infinite scroll by listening to container scroll events and loading more data
|
|
1451
1451
|
* when nearing the bottom, respecting pagination state (enabled/loading/hasMore).
|
|
1452
|
+
*
|
|
1453
|
+
* @param searchController - Provides pagination state and a method to load more items.
|
|
1454
|
+
* @param _options - Optional SelectiveOptions (reserved for future behavior tuning).
|
|
1452
1455
|
*/
|
|
1453
1456
|
setupInfiniteScroll(searchController, _options) {
|
|
1454
1457
|
if (!this.node)
|
|
@@ -1473,6 +1476,65 @@ class Popup {
|
|
|
1473
1476
|
};
|
|
1474
1477
|
this.node.addEventListener("scroll", this._scrollListener);
|
|
1475
1478
|
}
|
|
1479
|
+
/**
|
|
1480
|
+
* Completely tear down the popup instance and release all resources.
|
|
1481
|
+
*
|
|
1482
|
+
* Responsibilities:
|
|
1483
|
+
* - Clear any pending timeouts and cancel animations/effects.
|
|
1484
|
+
* - Remove event listeners (scroll, mousedown) and disconnect ResizeObserver.
|
|
1485
|
+
* - Unmount and remove the DOM node; sever references to Effector/ModelManager.
|
|
1486
|
+
* - Dispose adapter/recycler and child components (OptionHandle, EmptyState, LoadingState).
|
|
1487
|
+
* - Reset flags and null out references to avoid memory leaks.
|
|
1488
|
+
*
|
|
1489
|
+
* Safe to call multiple times; all operations are guarded via optional chaining.
|
|
1490
|
+
*/
|
|
1491
|
+
detroy() {
|
|
1492
|
+
if (this._hideLoadHandle) {
|
|
1493
|
+
clearTimeout(this._hideLoadHandle);
|
|
1494
|
+
this._hideLoadHandle = null;
|
|
1495
|
+
}
|
|
1496
|
+
if (this.node && this._scrollListener) {
|
|
1497
|
+
this.node.removeEventListener("scroll", this._scrollListener);
|
|
1498
|
+
this._scrollListener = null;
|
|
1499
|
+
}
|
|
1500
|
+
try {
|
|
1501
|
+
this._resizeObser?.disconnect();
|
|
1502
|
+
}
|
|
1503
|
+
catch (_) { }
|
|
1504
|
+
this._resizeObser = null;
|
|
1505
|
+
try {
|
|
1506
|
+
this._effSvc?.setElement?.(null);
|
|
1507
|
+
}
|
|
1508
|
+
catch (_) { }
|
|
1509
|
+
this._effSvc = null;
|
|
1510
|
+
if (this.node) {
|
|
1511
|
+
try {
|
|
1512
|
+
const clone = this.node.cloneNode(true);
|
|
1513
|
+
this.node.replaceWith(clone);
|
|
1514
|
+
clone.remove();
|
|
1515
|
+
}
|
|
1516
|
+
catch (_) {
|
|
1517
|
+
this.node.remove();
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
this.node = null;
|
|
1521
|
+
this._optionsContainer = null;
|
|
1522
|
+
try {
|
|
1523
|
+
this._modelManager?.skipEvent?.(false);
|
|
1524
|
+
this.recyclerView?.clear?.();
|
|
1525
|
+
this.recyclerView = null;
|
|
1526
|
+
this.optionAdapter = null;
|
|
1527
|
+
this.node.remove();
|
|
1528
|
+
}
|
|
1529
|
+
catch (_) { }
|
|
1530
|
+
this._modelManager = null;
|
|
1531
|
+
this.optionHandle = null;
|
|
1532
|
+
this.emptyState = null;
|
|
1533
|
+
this.loadingState = null;
|
|
1534
|
+
this._parent = null;
|
|
1535
|
+
this.options = null;
|
|
1536
|
+
this.isCreated = false;
|
|
1537
|
+
}
|
|
1476
1538
|
/**
|
|
1477
1539
|
* Computes the parent panel's location and box metrics, including size, position,
|
|
1478
1540
|
* padding, and border, accounting for iOS visual viewport offsets.
|
|
@@ -1999,7 +2061,9 @@ class EffectorImpl {
|
|
|
1999
2061
|
}
|
|
2000
2062
|
else {
|
|
2001
2063
|
this._resizeTimeout = setTimeout(() => {
|
|
2002
|
-
this.element
|
|
2064
|
+
if (this.element?.style) {
|
|
2065
|
+
this.element.style.transition = "none";
|
|
2066
|
+
}
|
|
2003
2067
|
}, duration);
|
|
2004
2068
|
}
|
|
2005
2069
|
Object.assign(this.element.style, styles);
|
|
@@ -2570,7 +2634,6 @@ class ModelManager {
|
|
|
2570
2634
|
});
|
|
2571
2635
|
let currentGroup = null;
|
|
2572
2636
|
let position = 0;
|
|
2573
|
-
const changesToApply = [];
|
|
2574
2637
|
modelData.forEach((data) => {
|
|
2575
2638
|
if (data.tagName === "OPTGROUP") {
|
|
2576
2639
|
const dataVset = data;
|
|
@@ -2579,7 +2642,7 @@ class ModelManager {
|
|
|
2579
2642
|
// Label is used as key; keep original behavior.
|
|
2580
2643
|
const hasLabelChange = existingGroup.label !== dataVset.label;
|
|
2581
2644
|
if (hasLabelChange) {
|
|
2582
|
-
|
|
2645
|
+
existingGroup.update(dataVset);
|
|
2583
2646
|
}
|
|
2584
2647
|
existingGroup.position = position;
|
|
2585
2648
|
existingGroup.items = [];
|
|
@@ -2599,17 +2662,8 @@ class ModelManager {
|
|
|
2599
2662
|
const key = `${dataVset.value}::${dataVset.text}`;
|
|
2600
2663
|
const existingOption = oldOptionMap.get(key);
|
|
2601
2664
|
if (existingOption) {
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
if (hasSelectedChange || hasPositionChange) {
|
|
2605
|
-
changesToApply.push(() => {
|
|
2606
|
-
existingOption.update(dataVset);
|
|
2607
|
-
existingOption.position = position;
|
|
2608
|
-
});
|
|
2609
|
-
}
|
|
2610
|
-
else {
|
|
2611
|
-
existingOption.position = position;
|
|
2612
|
-
}
|
|
2665
|
+
existingOption.update(dataVset);
|
|
2666
|
+
existingOption.position = position;
|
|
2613
2667
|
const parentGroup = dataVset["__parentGroup"];
|
|
2614
2668
|
if (parentGroup && currentGroup) {
|
|
2615
2669
|
currentGroup.addItem(existingOption);
|
|
@@ -2636,11 +2690,6 @@ class ModelManager {
|
|
|
2636
2690
|
position++;
|
|
2637
2691
|
}
|
|
2638
2692
|
});
|
|
2639
|
-
if (changesToApply.length > 0) {
|
|
2640
|
-
requestAnimationFrame(() => {
|
|
2641
|
-
changesToApply.forEach((change) => change());
|
|
2642
|
-
});
|
|
2643
|
-
}
|
|
2644
2693
|
oldGroupMap.forEach((removedGroup) => {
|
|
2645
2694
|
removedGroup.view?.getView?.()?.remove?.();
|
|
2646
2695
|
});
|
|
@@ -2683,9 +2732,6 @@ class ModelManager {
|
|
|
2683
2732
|
* adapter instance, and recycler view instance.
|
|
2684
2733
|
*/
|
|
2685
2734
|
getResources() {
|
|
2686
|
-
if (!this._privAdapterHandle || !this._privRecyclerViewHandle) {
|
|
2687
|
-
throw new Error("ModelManager resources not loaded. Call load() first.");
|
|
2688
|
-
}
|
|
2689
2735
|
return {
|
|
2690
2736
|
modelList: this._privModelList,
|
|
2691
2737
|
adapter: this._privAdapterHandle,
|
|
@@ -5044,6 +5090,9 @@ class SelectBox {
|
|
|
5044
5090
|
}
|
|
5045
5091
|
return flatOptions;
|
|
5046
5092
|
}
|
|
5093
|
+
detroy() {
|
|
5094
|
+
this.container.popup.detroy();
|
|
5095
|
+
}
|
|
5047
5096
|
}
|
|
5048
5097
|
|
|
5049
5098
|
/**
|
|
@@ -5275,6 +5324,8 @@ class Selective {
|
|
|
5275
5324
|
const bindMap = Libs.getBinderMap(selectElement);
|
|
5276
5325
|
if (!bindMap)
|
|
5277
5326
|
return;
|
|
5327
|
+
const popup = bindMap.container?.popup;
|
|
5328
|
+
popup?.detroy();
|
|
5278
5329
|
Libs.setUnbinderMap(selectElement, bindMap);
|
|
5279
5330
|
const wasObserving = !!this.EAObserver;
|
|
5280
5331
|
if (wasObserving)
|
|
@@ -5458,7 +5509,7 @@ function markLoaded(name, version, api) {
|
|
|
5458
5509
|
console.log(`[${name}] v${version} loaded successfully`);
|
|
5459
5510
|
}
|
|
5460
5511
|
|
|
5461
|
-
const version = "1.1.
|
|
5512
|
+
const version = "1.1.1";
|
|
5462
5513
|
const name = "SelectiveUI";
|
|
5463
5514
|
const alreadyLoaded = checkDuplicate(name);
|
|
5464
5515
|
function getGlobal() {
|
|
@@ -5490,7 +5541,7 @@ function find(query) {
|
|
|
5490
5541
|
* Destroys Selective instances associated with the given query.
|
|
5491
5542
|
* Proxies to a global loaded instance if available; otherwise uses local Selective.destroy.
|
|
5492
5543
|
*/
|
|
5493
|
-
function destroy(query) {
|
|
5544
|
+
function destroy(query = null) {
|
|
5494
5545
|
const global = getGlobal();
|
|
5495
5546
|
if (alreadyLoaded && global)
|
|
5496
5547
|
return global.destroy(query);
|