selective-ui 1.2.0 → 1.2.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 +55 -34
- package/dist/selective-ui.esm.js.map +1 -1
- package/dist/selective-ui.esm.min.js +2 -2
- package/dist/selective-ui.esm.min.js.br +0 -0
- package/dist/selective-ui.min.js +2 -2
- package/dist/selective-ui.min.js.br +0 -0
- package/dist/selective-ui.umd.js +56 -35
- package/dist/selective-ui.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/ts/adapter/mixed-adapter.ts +17 -11
- package/src/ts/components/selectbox.ts +16 -9
- package/src/ts/core/base/virtual-recyclerview.ts +1 -0
- package/src/ts/core/search-controller.ts +1 -4
- package/src/ts/models/option-model.ts +22 -3
- package/src/ts/services/effector.ts +5 -5
package/dist/selective-ui.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! Selective UI v1.2.
|
|
1
|
+
/*! Selective UI v1.2.1 | MIT License */
|
|
2
2
|
/**
|
|
3
3
|
* @class
|
|
4
4
|
*/
|
|
@@ -2079,8 +2079,7 @@ class EffectorImpl {
|
|
|
2079
2079
|
resize(config) {
|
|
2080
2080
|
if (!this.element)
|
|
2081
2081
|
return this;
|
|
2082
|
-
|
|
2083
|
-
clearTimeout(this._resizeTimeout);
|
|
2082
|
+
this.cancel();
|
|
2084
2083
|
const { duration = 200, width, left, top, maxHeight, realHeight, position = "bottom", animate = true, onComplete, } = config;
|
|
2085
2084
|
const currentPosition = this.element.classList.contains("position-top") ? "top" : "bottom";
|
|
2086
2085
|
const isPositionChanged = currentPosition !== position;
|
|
@@ -2090,7 +2089,7 @@ class EffectorImpl {
|
|
|
2090
2089
|
if (isPositionChanged) {
|
|
2091
2090
|
this.element.style.transition = `top ${duration}ms ease-out, height ${duration}ms ease-out, max-height ${duration}ms ease-out;`;
|
|
2092
2091
|
}
|
|
2093
|
-
|
|
2092
|
+
setTimeout(() => {
|
|
2094
2093
|
const styles = {
|
|
2095
2094
|
width: `${width}px`,
|
|
2096
2095
|
left: `${left}px`,
|
|
@@ -2106,14 +2105,14 @@ class EffectorImpl {
|
|
|
2106
2105
|
else {
|
|
2107
2106
|
this._resizeTimeout = setTimeout(() => {
|
|
2108
2107
|
if (this.element?.style) {
|
|
2109
|
-
this.element.style.transition =
|
|
2108
|
+
this.element.style.transition = null;
|
|
2110
2109
|
}
|
|
2111
2110
|
}, duration);
|
|
2112
2111
|
}
|
|
2113
2112
|
Object.assign(this.element.style, styles);
|
|
2114
2113
|
if (animate && (isPositionChanged || heightDiff > 1)) {
|
|
2115
2114
|
this._resizeTimeout = setTimeout(() => {
|
|
2116
|
-
this.element.style.transition =
|
|
2115
|
+
this.element.style.transition = null;
|
|
2117
2116
|
if (isPositionChanged)
|
|
2118
2117
|
delete this.element.style.transition;
|
|
2119
2118
|
onComplete?.();
|
|
@@ -2124,7 +2123,7 @@ class EffectorImpl {
|
|
|
2124
2123
|
delete this.element.style.transition;
|
|
2125
2124
|
onComplete?.();
|
|
2126
2125
|
}
|
|
2127
|
-
});
|
|
2126
|
+
}, 20);
|
|
2128
2127
|
return this;
|
|
2129
2128
|
}
|
|
2130
2129
|
/**
|
|
@@ -2319,17 +2318,28 @@ class GroupModel extends Model {
|
|
|
2319
2318
|
}
|
|
2320
2319
|
|
|
2321
2320
|
/**
|
|
2322
|
-
* @extends {Model<HTMLOptionElement, OptionViewTags, OptionView>}
|
|
2321
|
+
* @extends {Model<HTMLOptionElement, OptionViewTags, OptionView, SelectiveOptions>}
|
|
2323
2322
|
*/
|
|
2324
2323
|
class OptionModel extends Model {
|
|
2325
|
-
|
|
2326
|
-
|
|
2324
|
+
/**
|
|
2325
|
+
* Constructs a Model instance with configuration options and optional bindings to a target element and view.
|
|
2326
|
+
* Stores references for later updates and rendering.
|
|
2327
|
+
*
|
|
2328
|
+
* @param {SelectiveOptions} options - Configuration options for the model.
|
|
2329
|
+
* @param {HTMLOptionElement|null} [targetElement=null] - The underlying element (e.g., <option> or group node).
|
|
2330
|
+
* @param {OptionView|null} [view=null] - The associated view responsible for rendering the model.
|
|
2331
|
+
*/
|
|
2332
|
+
constructor(options, targetElement = null, view = null) {
|
|
2333
|
+
super(options, targetElement, view);
|
|
2327
2334
|
this._privOnSelected = [];
|
|
2328
2335
|
this._privOnInternalSelected = [];
|
|
2329
2336
|
this._privOnVisibilityChanged = [];
|
|
2330
2337
|
this._visible = true;
|
|
2331
2338
|
this._highlighted = false;
|
|
2332
2339
|
this.group = null;
|
|
2340
|
+
(async () => {
|
|
2341
|
+
this.textToFind = Libs.string2normalize(this.textContent.toLowerCase());
|
|
2342
|
+
})();
|
|
2333
2343
|
}
|
|
2334
2344
|
/**
|
|
2335
2345
|
* Returns the image source from dataset (imgsrc or image), or an empty string if absent.
|
|
@@ -2503,6 +2513,7 @@ class OptionModel extends Model {
|
|
|
2503
2513
|
* and synchronizes initial selected state to the view.
|
|
2504
2514
|
*/
|
|
2505
2515
|
onTargetChanged() {
|
|
2516
|
+
this.textToFind = Libs.string2normalize(this.textContent.toLowerCase());
|
|
2506
2517
|
if (!this.view)
|
|
2507
2518
|
return;
|
|
2508
2519
|
const labelContent = this.view.view.tags.LabelContent;
|
|
@@ -3200,9 +3211,7 @@ class SearchController {
|
|
|
3200
3211
|
}
|
|
3201
3212
|
let hasVisibleItems = false;
|
|
3202
3213
|
flatOptions.forEach((opt) => {
|
|
3203
|
-
const
|
|
3204
|
-
const textNA = Libs.string2normalize(text);
|
|
3205
|
-
const isVisible = lower === "" || text.includes(lower) || textNA.includes(lowerNA);
|
|
3214
|
+
const isVisible = lower === "" || opt.textToFind.includes(lowerNA);
|
|
3206
3215
|
opt.visible = isVisible;
|
|
3207
3216
|
if (isVisible)
|
|
3208
3217
|
hasVisibleItems = true;
|
|
@@ -4172,6 +4181,19 @@ class MixedAdapter extends Adapter {
|
|
|
4172
4181
|
this.groups = [];
|
|
4173
4182
|
this.flatOptions = [];
|
|
4174
4183
|
this._buildFlatStructure();
|
|
4184
|
+
Libs.callbackScheduler.on(`sche_vis_${this.adapterKey}`, () => {
|
|
4185
|
+
const visibleCount = this.flatOptions.filter((item) => item.visible).length;
|
|
4186
|
+
const totalCount = this.flatOptions.length;
|
|
4187
|
+
this._visibilityChangedCallbacks.forEach((callback) => {
|
|
4188
|
+
callback({
|
|
4189
|
+
visibleCount,
|
|
4190
|
+
totalCount,
|
|
4191
|
+
hasVisible: visibleCount > 0,
|
|
4192
|
+
isEmpty: totalCount === 0,
|
|
4193
|
+
});
|
|
4194
|
+
});
|
|
4195
|
+
Libs.callbackScheduler.run(`sche_vis_proxy_${this.adapterKey}`);
|
|
4196
|
+
}, { debounce: 10 });
|
|
4175
4197
|
}
|
|
4176
4198
|
/**
|
|
4177
4199
|
* Build flat list of all options for navigation
|
|
@@ -4407,16 +4429,7 @@ class MixedAdapter extends Adapter {
|
|
|
4407
4429
|
* Computes visible and total counts, then emits aggregated state.
|
|
4408
4430
|
*/
|
|
4409
4431
|
_notifyVisibilityChanged() {
|
|
4410
|
-
|
|
4411
|
-
const totalCount = this.flatOptions.length;
|
|
4412
|
-
this._visibilityChangedCallbacks.forEach((callback) => {
|
|
4413
|
-
callback({
|
|
4414
|
-
visibleCount,
|
|
4415
|
-
totalCount,
|
|
4416
|
-
hasVisible: visibleCount > 0,
|
|
4417
|
-
isEmpty: totalCount === 0,
|
|
4418
|
-
});
|
|
4419
|
-
});
|
|
4432
|
+
Libs.callbackScheduler.run(`sche_vis_${this.adapterKey}`);
|
|
4420
4433
|
}
|
|
4421
4434
|
/**
|
|
4422
4435
|
* Computes and returns current visibility statistics for options.
|
|
@@ -5128,6 +5141,8 @@ class VirtualRecyclerView extends RecyclerView {
|
|
|
5128
5141
|
return;
|
|
5129
5142
|
}
|
|
5130
5143
|
const item = this.adapter.items[index];
|
|
5144
|
+
if (!item)
|
|
5145
|
+
return;
|
|
5131
5146
|
const existing = this.created.get(index);
|
|
5132
5147
|
if (existing) {
|
|
5133
5148
|
if (!item?.view) {
|
|
@@ -5385,6 +5400,7 @@ class SelectBox {
|
|
|
5385
5400
|
searchController.setAjax(options.ajax);
|
|
5386
5401
|
}
|
|
5387
5402
|
const optionAdapter = container.popup.optionAdapter;
|
|
5403
|
+
let hightlightTimer = null;
|
|
5388
5404
|
const searchHandle = (keyword, isTrigger) => {
|
|
5389
5405
|
if (!isTrigger && keyword === "") {
|
|
5390
5406
|
searchController.clear();
|
|
@@ -5395,13 +5411,16 @@ class SelectBox {
|
|
|
5395
5411
|
searchController
|
|
5396
5412
|
.search(keyword)
|
|
5397
5413
|
.then((result) => {
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5402
|
-
|
|
5403
|
-
|
|
5404
|
-
|
|
5414
|
+
clearTimeout(hightlightTimer);
|
|
5415
|
+
Libs.callbackScheduler.on(`sche_vis_proxy_${optionAdapter.adapterKey}`, () => {
|
|
5416
|
+
container.popup?.triggerResize?.();
|
|
5417
|
+
if (result?.hasResults) {
|
|
5418
|
+
hightlightTimer = setTimeout(() => {
|
|
5419
|
+
optionAdapter.resetHighlight();
|
|
5420
|
+
container.popup?.triggerResize?.();
|
|
5421
|
+
}, options.animationtime ?? 0);
|
|
5422
|
+
}
|
|
5423
|
+
}, { debounce: 10 });
|
|
5405
5424
|
})
|
|
5406
5425
|
.catch((error) => {
|
|
5407
5426
|
console.error("Search error:", error);
|
|
@@ -5412,16 +5431,18 @@ class SelectBox {
|
|
|
5412
5431
|
searchbox.onSearch = (keyword, isTrigger) => {
|
|
5413
5432
|
if (!searchController.compareSearchTrigger(keyword))
|
|
5414
5433
|
return;
|
|
5434
|
+
if (searchHandleTimer)
|
|
5435
|
+
clearTimeout(searchHandleTimer);
|
|
5415
5436
|
if (searchController.isAjax()) {
|
|
5416
|
-
if (searchHandleTimer)
|
|
5417
|
-
clearTimeout(searchHandleTimer);
|
|
5418
5437
|
container.popup?.showLoading?.();
|
|
5419
5438
|
searchHandleTimer = setTimeout(() => {
|
|
5420
5439
|
searchHandle(keyword, isTrigger);
|
|
5421
5440
|
}, options.delaysearchtime ?? 0);
|
|
5422
5441
|
}
|
|
5423
5442
|
else {
|
|
5424
|
-
|
|
5443
|
+
searchHandleTimer = setTimeout(() => {
|
|
5444
|
+
searchHandle(keyword, isTrigger);
|
|
5445
|
+
}, 10);
|
|
5425
5446
|
}
|
|
5426
5447
|
};
|
|
5427
5448
|
searchController.setPopup(container.popup);
|
|
@@ -6232,7 +6253,7 @@ const SECLASS = new Selective();
|
|
|
6232
6253
|
*
|
|
6233
6254
|
* Declared as `const` literal type to enable strict typing and easy tree-shaking.
|
|
6234
6255
|
*/
|
|
6235
|
-
const version = "1.2.
|
|
6256
|
+
const version = "1.2.1";
|
|
6236
6257
|
/**
|
|
6237
6258
|
* Library name identifier.
|
|
6238
6259
|
*
|