selective-ui 1.4.0 → 1.4.2
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.css +2 -2
- package/dist/selective-ui.css.map +1 -1
- package/dist/selective-ui.esm.js +407 -573
- 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.css +1 -1
- package/dist/selective-ui.min.css.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 +409 -575
- package/dist/selective-ui.umd.js.map +1 -1
- package/package.json +12 -12
- package/src/css/views/option-view.css +2 -2
- package/src/ts/adapter/mixed-adapter.ts +149 -71
- package/src/ts/components/accessorybox.ts +14 -11
- package/src/ts/components/directive.ts +1 -1
- package/src/ts/components/option-handle.ts +12 -9
- package/src/ts/components/placeholder.ts +5 -5
- package/src/ts/components/popup/empty-state.ts +5 -5
- package/src/ts/components/popup/loading-state.ts +5 -5
- package/src/ts/components/popup/popup.ts +138 -76
- package/src/ts/components/searchbox.ts +17 -13
- package/src/ts/components/selectbox.ts +260 -84
- package/src/ts/core/base/adapter.ts +61 -14
- package/src/ts/core/base/fenwick.ts +3 -2
- package/src/ts/core/base/lifecycle.ts +14 -4
- package/src/ts/core/base/model.ts +17 -15
- package/src/ts/core/base/recyclerview.ts +7 -5
- package/src/ts/core/base/view.ts +10 -5
- package/src/ts/core/base/virtual-recyclerview.ts +178 -45
- package/src/ts/core/model-manager.ts +48 -21
- package/src/ts/core/search-controller.ts +174 -56
- package/src/ts/global.ts +5 -8
- package/src/ts/index.ts +2 -2
- package/src/ts/models/group-model.ts +33 -8
- package/src/ts/models/option-model.ts +88 -20
- package/src/ts/services/dataset-observer.ts +6 -3
- package/src/ts/services/ea-observer.ts +1 -1
- package/src/ts/services/effector.ts +22 -12
- package/src/ts/services/refresher.ts +14 -4
- package/src/ts/services/resize-observer.ts +24 -11
- package/src/ts/services/select-observer.ts +2 -2
- package/src/ts/types/components/popup.type.ts +18 -1
- package/src/ts/types/components/searchbox.type.ts +43 -30
- package/src/ts/types/components/state.box.type.ts +1 -1
- package/src/ts/types/core/base/adapter.type.ts +13 -5
- package/src/ts/types/core/base/lifecycle.type.ts +1 -2
- package/src/ts/types/core/base/model.type.ts +3 -3
- package/src/ts/types/core/base/recyclerview.type.ts +7 -5
- package/src/ts/types/core/base/view.type.ts +6 -6
- package/src/ts/types/core/base/virtual-recyclerview.type.ts +45 -46
- package/src/ts/types/core/search-controller.type.ts +18 -2
- package/src/ts/types/css.d.ts +1 -0
- package/src/ts/types/plugins/plugin.type.ts +2 -2
- package/src/ts/types/services/effector.type.ts +25 -25
- package/src/ts/types/services/resize-observer.type.ts +23 -12
- package/src/ts/types/utils/callback-scheduler.type.ts +2 -2
- package/src/ts/types/utils/ievents.type.ts +1 -1
- package/src/ts/types/utils/istorage.type.ts +62 -60
- package/src/ts/types/utils/libs.type.ts +19 -17
- package/src/ts/types/utils/selective.type.ts +6 -3
- package/src/ts/types/views/view.group.type.ts +9 -5
- package/src/ts/types/views/view.option.type.ts +39 -17
- package/src/ts/utils/callback-scheduler.ts +12 -7
- package/src/ts/utils/ievents.ts +12 -5
- package/src/ts/utils/istorage.ts +5 -3
- package/src/ts/utils/libs.ts +122 -43
- package/src/ts/utils/selective.ts +15 -8
- package/src/ts/views/group-view.ts +11 -9
- package/src/ts/views/option-view.ts +37 -18
|
@@ -55,24 +55,35 @@ import { LifecycleState } from "../types/core/base/lifecycle.type";
|
|
|
55
55
|
* @see {@link GroupModel}
|
|
56
56
|
* @see {@link OptionView}
|
|
57
57
|
*/
|
|
58
|
-
export class OptionModel extends Model<
|
|
58
|
+
export class OptionModel extends Model<
|
|
59
|
+
HTMLOptionElement,
|
|
60
|
+
OptionViewTags,
|
|
61
|
+
OptionView,
|
|
62
|
+
SelectiveOptions
|
|
63
|
+
> {
|
|
59
64
|
/**
|
|
60
65
|
* External selection subscribers (emitted by the {@link selected} setter).
|
|
61
66
|
* Use this for user-facing selection flows.
|
|
62
67
|
*/
|
|
63
|
-
private privOnSelected: Array<
|
|
68
|
+
private privOnSelected: Array<
|
|
69
|
+
(evtToken: IEventCallback, el: OptionModel, selected: boolean) => void
|
|
70
|
+
> = [];
|
|
64
71
|
|
|
65
72
|
/**
|
|
66
73
|
* Internal selection subscribers (emitted by the {@link selectedNonTrigger} setter).
|
|
67
74
|
* Use this for silent synchronization flows.
|
|
68
75
|
*/
|
|
69
|
-
private privOnInternalSelected: Array<
|
|
76
|
+
private privOnInternalSelected: Array<
|
|
77
|
+
(evtToken: IEventCallback, el: OptionModel, selected: boolean) => void
|
|
78
|
+
> = [];
|
|
70
79
|
|
|
71
80
|
/**
|
|
72
81
|
* Visibility subscribers (emitted by the {@link visible} setter).
|
|
73
82
|
* Commonly used to recompute group visibility and update aggregated visibility stats.
|
|
74
83
|
*/
|
|
75
|
-
private privOnVisibilityChanged: Array<
|
|
84
|
+
private privOnVisibilityChanged: Array<
|
|
85
|
+
(evtToken: IEventCallback, model: OptionModel, visible: boolean) => void
|
|
86
|
+
> = [];
|
|
76
87
|
|
|
77
88
|
/**
|
|
78
89
|
* Visibility flag used for filtering/search.
|
|
@@ -87,19 +98,19 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
87
98
|
* Parent group model (if this option belongs to a group).
|
|
88
99
|
* Assigned by grouping logic (e.g., GroupModel/MixedAdapter).
|
|
89
100
|
*/
|
|
90
|
-
public group
|
|
101
|
+
public group?: GroupModel;
|
|
91
102
|
|
|
92
103
|
/**
|
|
93
104
|
* Creates an option model.
|
|
94
105
|
*
|
|
95
106
|
* @param {SelectiveOptions} options - Shared configuration for models/views.
|
|
96
|
-
* @param {HTMLOptionElement
|
|
97
|
-
* @param {OptionView
|
|
107
|
+
* @param {HTMLOptionElement} [targetElement=null] - Backing `<option>` element.
|
|
108
|
+
* @param {OptionView} [view=null] - Optional view used to render this model.
|
|
98
109
|
*/
|
|
99
110
|
public constructor(
|
|
100
111
|
options: SelectiveOptions,
|
|
101
|
-
targetElement
|
|
102
|
-
view
|
|
112
|
+
targetElement?: HTMLOptionElement,
|
|
113
|
+
view?: OptionView,
|
|
103
114
|
) {
|
|
104
115
|
super(options, targetElement, view);
|
|
105
116
|
}
|
|
@@ -168,7 +179,10 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
168
179
|
*/
|
|
169
180
|
public set selected(value: boolean) {
|
|
170
181
|
this.selectedNonTrigger = value;
|
|
171
|
-
iEvents.callEvent<[OptionModel, boolean]>(
|
|
182
|
+
iEvents.callEvent<[OptionModel, boolean]>(
|
|
183
|
+
[this, value],
|
|
184
|
+
...this.privOnSelected,
|
|
185
|
+
);
|
|
172
186
|
}
|
|
173
187
|
|
|
174
188
|
/**
|
|
@@ -199,7 +213,10 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
199
213
|
const viewEl = this.view?.getView?.();
|
|
200
214
|
if (viewEl) viewEl.classList.toggle("hide", !value);
|
|
201
215
|
|
|
202
|
-
iEvents.callEvent<[OptionModel, boolean]>(
|
|
216
|
+
iEvents.callEvent<[OptionModel, boolean]>(
|
|
217
|
+
[this, value],
|
|
218
|
+
...this.privOnVisibilityChanged,
|
|
219
|
+
);
|
|
203
220
|
}
|
|
204
221
|
|
|
205
222
|
/**
|
|
@@ -243,7 +260,37 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
243
260
|
this.targetElement.selected = value;
|
|
244
261
|
}
|
|
245
262
|
|
|
246
|
-
iEvents.callEvent<[OptionModel, boolean]>(
|
|
263
|
+
iEvents.callEvent<[OptionModel, boolean]>(
|
|
264
|
+
[this, value],
|
|
265
|
+
...this.privOnInternalSelected,
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Resolved display mask for this option.
|
|
271
|
+
*
|
|
272
|
+
* The mask is the primary render label used by the UI layer and supports
|
|
273
|
+
* optional inline tag translation / rich HTML rendering.
|
|
274
|
+
*
|
|
275
|
+
* Source priority:
|
|
276
|
+
* 1. `data-mask` (`dataset.mask`)
|
|
277
|
+
* 2. Native `<option>` text content (`targetElement.text`)
|
|
278
|
+
*
|
|
279
|
+
* Processing pipeline:
|
|
280
|
+
* - Raw content is first passed through {@link Libs.tagTranslate}.
|
|
281
|
+
* - When `options.allowHtml === true`, translated HTML is preserved.
|
|
282
|
+
* - Otherwise, all markup is stripped via {@link Libs.stripHtml}.
|
|
283
|
+
*
|
|
284
|
+
* Unlike {@link text}, this getter prioritizes the custom dataset mask,
|
|
285
|
+
* making it suitable for display overrides without mutating the native
|
|
286
|
+
* `<option>` label.
|
|
287
|
+
*
|
|
288
|
+
* @returns {string} Render-ready option label.
|
|
289
|
+
*/
|
|
290
|
+
public get mask(): string {
|
|
291
|
+
const raw = this.dataset?.mask ?? this.targetElement?.text ?? "";
|
|
292
|
+
const translated = Libs.tagTranslate(raw);
|
|
293
|
+
return this.options.allowHtml ? translated : Libs.stripHtml(translated);
|
|
247
294
|
}
|
|
248
295
|
|
|
249
296
|
/**
|
|
@@ -259,7 +306,7 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
259
306
|
* @returns {string}
|
|
260
307
|
*/
|
|
261
308
|
public get text(): string {
|
|
262
|
-
const raw = this.
|
|
309
|
+
const raw = this.targetElement?.text ?? this.dataset?.mask ?? "";
|
|
263
310
|
const translated = Libs.tagTranslate(raw);
|
|
264
311
|
return this.options.allowHtml ? translated : Libs.stripHtml(translated);
|
|
265
312
|
}
|
|
@@ -273,7 +320,9 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
273
320
|
* @returns {string}
|
|
274
321
|
*/
|
|
275
322
|
public get textContent(): string {
|
|
276
|
-
return this.options.allowHtml
|
|
323
|
+
return this.options.allowHtml
|
|
324
|
+
? Libs.stripHtml(this.text).trim()
|
|
325
|
+
: this.text.trim();
|
|
277
326
|
}
|
|
278
327
|
|
|
279
328
|
/**
|
|
@@ -323,7 +372,13 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
323
372
|
* @param {(evtToken: IEventCallback, el: OptionModel, selected: boolean) => void} callback - Listener callback.
|
|
324
373
|
* @returns {void}
|
|
325
374
|
*/
|
|
326
|
-
public onSelected(
|
|
375
|
+
public onSelected(
|
|
376
|
+
callback: (
|
|
377
|
+
evtToken: IEventCallback,
|
|
378
|
+
el: OptionModel,
|
|
379
|
+
selected: boolean,
|
|
380
|
+
) => void,
|
|
381
|
+
): void {
|
|
327
382
|
this.privOnSelected.push(callback);
|
|
328
383
|
}
|
|
329
384
|
|
|
@@ -333,7 +388,13 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
333
388
|
* @param {(evtToken: IEventCallback, el: OptionModel, selected: boolean) => void} callback - Listener callback.
|
|
334
389
|
* @returns {void}
|
|
335
390
|
*/
|
|
336
|
-
public onInternalSelected(
|
|
391
|
+
public onInternalSelected(
|
|
392
|
+
callback: (
|
|
393
|
+
evtToken: IEventCallback,
|
|
394
|
+
el: OptionModel,
|
|
395
|
+
selected: boolean,
|
|
396
|
+
) => void,
|
|
397
|
+
): void {
|
|
337
398
|
this.privOnInternalSelected.push(callback);
|
|
338
399
|
}
|
|
339
400
|
|
|
@@ -343,7 +404,13 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
343
404
|
* @param {(evtToken: IEventCallback, model: OptionModel, visible: boolean) => void} callback - Listener callback.
|
|
344
405
|
* @returns {void}
|
|
345
406
|
*/
|
|
346
|
-
public onVisibilityChanged(
|
|
407
|
+
public onVisibilityChanged(
|
|
408
|
+
callback: (
|
|
409
|
+
evtToken: IEventCallback,
|
|
410
|
+
model: OptionModel,
|
|
411
|
+
visible: boolean,
|
|
412
|
+
) => void,
|
|
413
|
+
): void {
|
|
347
414
|
this.privOnVisibilityChanged.push(callback);
|
|
348
415
|
}
|
|
349
416
|
|
|
@@ -389,7 +456,8 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
389
456
|
}
|
|
390
457
|
}
|
|
391
458
|
|
|
392
|
-
if (this.targetElement)
|
|
459
|
+
if (this.targetElement)
|
|
460
|
+
this.selectedNonTrigger = this.targetElement.selected;
|
|
393
461
|
|
|
394
462
|
super.update();
|
|
395
463
|
}
|
|
@@ -416,7 +484,7 @@ export class OptionModel extends Model<HTMLOptionElement, OptionViewTags, Option
|
|
|
416
484
|
this.privOnVisibilityChanged = [];
|
|
417
485
|
this.group = null;
|
|
418
486
|
this.textToFind = null;
|
|
419
|
-
|
|
487
|
+
|
|
420
488
|
super.destroy();
|
|
421
489
|
}
|
|
422
|
-
}
|
|
490
|
+
}
|
|
@@ -38,7 +38,7 @@ export class DatasetObserver {
|
|
|
38
38
|
* Debounce timer handle for coalescing rapid attribute mutations.
|
|
39
39
|
* Cleared/replaced whenever a new relevant mutation arrives within the debounce window.
|
|
40
40
|
*/
|
|
41
|
-
private debounceTimer
|
|
41
|
+
private debounceTimer?: NodeJS.Timeout;
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* Creates a {@link DatasetObserver} for the given element.
|
|
@@ -62,7 +62,10 @@ export class DatasetObserver {
|
|
|
62
62
|
let datasetChanged = false;
|
|
63
63
|
|
|
64
64
|
for (const mutation of mutations) {
|
|
65
|
-
if (
|
|
65
|
+
if (
|
|
66
|
+
mutation.type === "attributes" &&
|
|
67
|
+
mutation.attributeName?.startsWith("data-")
|
|
68
|
+
) {
|
|
66
69
|
datasetChanged = true;
|
|
67
70
|
break;
|
|
68
71
|
}
|
|
@@ -132,4 +135,4 @@ export class DatasetObserver {
|
|
|
132
135
|
this.debounceTimer = null;
|
|
133
136
|
this.observer.disconnect();
|
|
134
137
|
}
|
|
135
|
-
}
|
|
138
|
+
}
|
|
@@ -27,7 +27,7 @@ import type {
|
|
|
27
27
|
* @param query - CSS selector or element to control. When `null`, the effector is unbound.
|
|
28
28
|
* @returns An effector instance implementing {@link EffectorInterface}.
|
|
29
29
|
*/
|
|
30
|
-
export function Effector(query?: string | HTMLElement
|
|
30
|
+
export function Effector(query?: string | HTMLElement): EffectorInterface {
|
|
31
31
|
return new EffectorImpl(query ?? null);
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -57,13 +57,13 @@ class EffectorImpl implements EffectorInterface {
|
|
|
57
57
|
* Timeout used to finalize expand/collapse/swipe animations.
|
|
58
58
|
* Cleared by {@link cancel}.
|
|
59
59
|
*/
|
|
60
|
-
private timeOut
|
|
60
|
+
private timeOut?: NodeJS.Timeout;
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Timeout used to clear transitions after resize in non-animated scenarios.
|
|
64
64
|
* Cleared by {@link cancel}.
|
|
65
65
|
*/
|
|
66
|
-
private resizeTimeout
|
|
66
|
+
private resizeTimeout?: NodeJS.Timeout;
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* Internal animation flag set while a timed animation is in-flight.
|
|
@@ -80,7 +80,7 @@ class EffectorImpl implements EffectorInterface {
|
|
|
80
80
|
*
|
|
81
81
|
* @param query - CSS selector or element to control. When `null`, instance starts unbound.
|
|
82
82
|
*/
|
|
83
|
-
public constructor(query
|
|
83
|
+
public constructor(query?: string | HTMLElement) {
|
|
84
84
|
if (query) this.setElement(query);
|
|
85
85
|
}
|
|
86
86
|
|
|
@@ -145,7 +145,9 @@ class EffectorImpl implements EffectorInterface {
|
|
|
145
145
|
* @param display - The display style to use for measurement (defaults to `"flex"`).
|
|
146
146
|
* @returns A dimension snapshot including `scrollHeight` adjusted for vertical borders.
|
|
147
147
|
*/
|
|
148
|
-
public getHiddenDimensions(
|
|
148
|
+
public getHiddenDimensions(
|
|
149
|
+
display: "flex" | string = "flex",
|
|
150
|
+
): DimensionObject {
|
|
149
151
|
// Guard: element may not be set yet.
|
|
150
152
|
if (!this.element) return { width: 0, height: 0, scrollHeight: 0 };
|
|
151
153
|
|
|
@@ -169,7 +171,8 @@ class EffectorImpl implements EffectorInterface {
|
|
|
169
171
|
const borderTopWidth = parseFloat(cs.borderTopWidth);
|
|
170
172
|
const borderBottomWidth = parseFloat(cs.borderBottomWidth);
|
|
171
173
|
|
|
172
|
-
const scrollHeight =
|
|
174
|
+
const scrollHeight =
|
|
175
|
+
this.element.scrollHeight + borderTopWidth + borderBottomWidth;
|
|
173
176
|
const rect = this.element.getBoundingClientRect();
|
|
174
177
|
|
|
175
178
|
const dimensions: DimensionObject = {
|
|
@@ -286,10 +289,14 @@ class EffectorImpl implements EffectorInterface {
|
|
|
286
289
|
|
|
287
290
|
const currentHeight = this.element.offsetHeight;
|
|
288
291
|
const currentTop = this.element.offsetTop;
|
|
289
|
-
const position = this.element.classList.contains("position-top")
|
|
290
|
-
|
|
292
|
+
const position = this.element.classList.contains("position-top")
|
|
293
|
+
? "top"
|
|
294
|
+
: "bottom";
|
|
295
|
+
const isScrollable =
|
|
296
|
+
this.element.scrollHeight - this.element.offsetHeight > 0;
|
|
291
297
|
|
|
292
|
-
const finalTop =
|
|
298
|
+
const finalTop =
|
|
299
|
+
position === "top" ? currentTop + currentHeight : currentTop;
|
|
293
300
|
|
|
294
301
|
requestAnimationFrame(() => {
|
|
295
302
|
Object.assign(this.element.style, {
|
|
@@ -459,7 +466,9 @@ class EffectorImpl implements EffectorInterface {
|
|
|
459
466
|
onComplete,
|
|
460
467
|
} = config;
|
|
461
468
|
|
|
462
|
-
const currentPosition = this.element.classList.contains("position-top")
|
|
469
|
+
const currentPosition = this.element.classList.contains("position-top")
|
|
470
|
+
? "top"
|
|
471
|
+
: "bottom";
|
|
463
472
|
const isPositionChanged = currentPosition !== position;
|
|
464
473
|
const isScrollable = this.element.scrollHeight > maxHeight;
|
|
465
474
|
|
|
@@ -471,7 +480,8 @@ class EffectorImpl implements EffectorInterface {
|
|
|
471
480
|
}
|
|
472
481
|
|
|
473
482
|
requestAnimationFrame(() => {
|
|
474
|
-
const styles: Partial<CSSStyleDeclaration> &
|
|
483
|
+
const styles: Partial<CSSStyleDeclaration> &
|
|
484
|
+
Record<string, string> = {
|
|
475
485
|
width: `${width}px`,
|
|
476
486
|
left: `${left}px`,
|
|
477
487
|
top: `${top}px`,
|
|
@@ -521,4 +531,4 @@ class EffectorImpl implements EffectorInterface {
|
|
|
521
531
|
public get isAnimating(): boolean {
|
|
522
532
|
return this._isAnimating;
|
|
523
533
|
}
|
|
524
|
-
}
|
|
534
|
+
}
|
|
@@ -36,8 +36,13 @@ export class Refresher {
|
|
|
36
36
|
*
|
|
37
37
|
* @param select - Native `<select>` element used as the sizing reference and option source.
|
|
38
38
|
* @param view - View panel element whose inline styles will be updated.
|
|
39
|
+
* @param isWidthOnly - If true, only the width will be updated; height will be left unchanged.
|
|
39
40
|
*/
|
|
40
|
-
public static resizeBox(
|
|
41
|
+
public static resizeBox(
|
|
42
|
+
select: HTMLSelectElement,
|
|
43
|
+
view: HTMLElement,
|
|
44
|
+
isWidthOnly = false,
|
|
45
|
+
): void {
|
|
41
46
|
const bindedMap = Libs.getBinderMap<BinderMap>(select);
|
|
42
47
|
if (!bindedMap?.options) return;
|
|
43
48
|
|
|
@@ -55,11 +60,16 @@ export class Refresher {
|
|
|
55
60
|
const cstyle = getComputedStyle(select);
|
|
56
61
|
|
|
57
62
|
if (width === "0px" && cstyle.width !== "auto") width = cstyle.width;
|
|
58
|
-
if (height === "0px" && cstyle.height !== "auto")
|
|
63
|
+
if (height === "0px" && cstyle.height !== "auto")
|
|
64
|
+
height = cstyle.height;
|
|
59
65
|
|
|
60
66
|
if (cfgWidth > 0) width = options.width;
|
|
61
67
|
if (cfgHeight > 0) height = options.height;
|
|
62
68
|
|
|
63
|
-
|
|
69
|
+
if (isWidthOnly) {
|
|
70
|
+
Object.assign(view.style, { width, maxWidth: width, minWidth });
|
|
71
|
+
} else {
|
|
72
|
+
Object.assign(view.style, { width, height, maxWidth: width, minWidth, minHeight });
|
|
73
|
+
}
|
|
64
74
|
}
|
|
65
|
-
}
|
|
75
|
+
}
|
|
@@ -63,7 +63,7 @@ export class ResizeObserverService {
|
|
|
63
63
|
* @remarks
|
|
64
64
|
* Set by {@link connect} and cleared by {@link disconnect}.
|
|
65
65
|
*/
|
|
66
|
-
public element
|
|
66
|
+
public element?: HTMLElement;
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* Underlying `ResizeObserver` instance.
|
|
@@ -71,7 +71,7 @@ export class ResizeObserverService {
|
|
|
71
71
|
* @remarks
|
|
72
72
|
* Allocated on {@link connect}. Disconnected and nulled on {@link disconnect}.
|
|
73
73
|
*/
|
|
74
|
-
private resizeObserver
|
|
74
|
+
private resizeObserver?: ResizeObserver;
|
|
75
75
|
|
|
76
76
|
/**
|
|
77
77
|
* Underlying `MutationObserver` instance watching `style` and `class` attribute changes.
|
|
@@ -79,7 +79,7 @@ export class ResizeObserverService {
|
|
|
79
79
|
* @remarks
|
|
80
80
|
* Allocated on {@link connect}. Disconnected and nulled on {@link disconnect}.
|
|
81
81
|
*/
|
|
82
|
-
private mutationObserver
|
|
82
|
+
private mutationObserver?: MutationObserver;
|
|
83
83
|
|
|
84
84
|
/**
|
|
85
85
|
* Stable, `this`-bound handler shared by observers and global event listeners.
|
|
@@ -115,7 +115,7 @@ export class ResizeObserverService {
|
|
|
115
115
|
* @param metrics - Snapshot of geometry and box edges (padding/border/margin).
|
|
116
116
|
*/
|
|
117
117
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
118
|
-
public onChanged(metrics: ElementMetrics): void {
|
|
118
|
+
public onChanged(metrics: ElementMetrics): void {}
|
|
119
119
|
|
|
120
120
|
/**
|
|
121
121
|
* Computes metrics for the current {@link element} and forwards them to {@link onChanged}.
|
|
@@ -150,7 +150,8 @@ export class ResizeObserverService {
|
|
|
150
150
|
|
|
151
151
|
const rect = el.getBoundingClientRect();
|
|
152
152
|
const style =
|
|
153
|
-
typeof window !== "undefined" &&
|
|
153
|
+
typeof window !== "undefined" &&
|
|
154
|
+
typeof window.getComputedStyle === "function"
|
|
154
155
|
? window.getComputedStyle(el)
|
|
155
156
|
: null;
|
|
156
157
|
|
|
@@ -233,8 +234,14 @@ export class ResizeObserverService {
|
|
|
233
234
|
window.addEventListener("resize", this.boundUpdateChanged);
|
|
234
235
|
|
|
235
236
|
if (window.visualViewport) {
|
|
236
|
-
window.visualViewport.addEventListener(
|
|
237
|
-
|
|
237
|
+
window.visualViewport.addEventListener(
|
|
238
|
+
"resize",
|
|
239
|
+
this.boundUpdateChanged,
|
|
240
|
+
);
|
|
241
|
+
window.visualViewport.addEventListener(
|
|
242
|
+
"scroll",
|
|
243
|
+
this.boundUpdateChanged,
|
|
244
|
+
);
|
|
238
245
|
}
|
|
239
246
|
}
|
|
240
247
|
|
|
@@ -254,18 +261,24 @@ export class ResizeObserverService {
|
|
|
254
261
|
this.resizeObserver?.disconnect();
|
|
255
262
|
this.mutationObserver?.disconnect();
|
|
256
263
|
|
|
257
|
-
this.onChanged = (_metrics: ElementMetrics) => {
|
|
264
|
+
this.onChanged = (_metrics: ElementMetrics) => {};
|
|
258
265
|
|
|
259
266
|
window.removeEventListener("scroll", this.boundUpdateChanged, true);
|
|
260
267
|
window.removeEventListener("resize", this.boundUpdateChanged);
|
|
261
268
|
|
|
262
269
|
if (window.visualViewport) {
|
|
263
|
-
window.visualViewport.removeEventListener(
|
|
264
|
-
|
|
270
|
+
window.visualViewport.removeEventListener(
|
|
271
|
+
"resize",
|
|
272
|
+
this.boundUpdateChanged,
|
|
273
|
+
);
|
|
274
|
+
window.visualViewport.removeEventListener(
|
|
275
|
+
"scroll",
|
|
276
|
+
this.boundUpdateChanged,
|
|
277
|
+
);
|
|
265
278
|
}
|
|
266
279
|
|
|
267
280
|
this.resizeObserver = null;
|
|
268
281
|
this.mutationObserver = null;
|
|
269
282
|
this.element = null;
|
|
270
283
|
}
|
|
271
|
-
}
|
|
284
|
+
}
|
|
@@ -62,7 +62,7 @@ export class SelectObserver {
|
|
|
62
62
|
*
|
|
63
63
|
* @private
|
|
64
64
|
*/
|
|
65
|
-
private debounceTimer
|
|
65
|
+
private debounceTimer?: NodeJS.Timeout;
|
|
66
66
|
|
|
67
67
|
/**
|
|
68
68
|
* Debounce delay in milliseconds.
|
|
@@ -171,4 +171,4 @@ export class SelectObserver {
|
|
|
171
171
|
this.debounceTimer = null;
|
|
172
172
|
this.observer.disconnect();
|
|
173
173
|
}
|
|
174
|
-
}
|
|
174
|
+
}
|
|
@@ -12,4 +12,21 @@ export interface VirtualRecyclerOptions {
|
|
|
12
12
|
estimateItemHeight?: number;
|
|
13
13
|
overscan?: number;
|
|
14
14
|
dynamicHeights?: boolean;
|
|
15
|
-
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface PopupPosition {
|
|
18
|
+
position: "top" | "bottom";
|
|
19
|
+
top: number;
|
|
20
|
+
maxHeight: number;
|
|
21
|
+
realHeight: number;
|
|
22
|
+
contentHeight: number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface PopupLocaltion {
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
top: number;
|
|
29
|
+
left: number;
|
|
30
|
+
padding: { top: number; right: number; bottom: number; left: number };
|
|
31
|
+
border: { top: number; right: number; bottom: number; left: number };
|
|
32
|
+
}
|
|
@@ -14,8 +14,8 @@ import { OptionModel } from "src/ts/models/option-model";
|
|
|
14
14
|
* Represents the DOM elements used in the SearchBox component.
|
|
15
15
|
*/
|
|
16
16
|
export type SearchBoxTags = {
|
|
17
|
-
SearchBox: HTMLDivElement;
|
|
18
|
-
SearchInput: HTMLInputElement;
|
|
17
|
+
SearchBox: HTMLDivElement; // Container for the search box
|
|
18
|
+
SearchInput: HTMLInputElement; // Input field for search queries
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -35,7 +35,7 @@ export type NavigateHandler = (direction: 1 | -1) => void;
|
|
|
35
35
|
* Represents the DOM elements used in the SelectBox component.
|
|
36
36
|
*/
|
|
37
37
|
export type SelectBoxTags = {
|
|
38
|
-
ViewPanel: HTMLDivElement;
|
|
38
|
+
ViewPanel: HTMLDivElement; // Panel that displays selectable options
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
/**
|
|
@@ -43,46 +43,46 @@ export type SelectBoxTags = {
|
|
|
43
43
|
* Combines mounted view result with additional services and components.
|
|
44
44
|
*/
|
|
45
45
|
export type ContainerRuntime = MountViewResult<SelectBoxTags> & {
|
|
46
|
-
placeholder: PlaceHolder;
|
|
47
|
-
directive: Directive;
|
|
48
|
-
searchbox: SearchBox;
|
|
49
|
-
popup: Popup;
|
|
50
|
-
effector: EffectorInterface;
|
|
51
|
-
targetElement: HTMLSelectElement;
|
|
52
|
-
accessorybox: AccessoryBox;
|
|
46
|
+
placeholder: PlaceHolder; // Placeholder manager
|
|
47
|
+
directive: Directive; // Directive handler for dynamic behavior
|
|
48
|
+
searchbox: SearchBox; // Search box component
|
|
49
|
+
popup: Popup; // Popup component for dropdown
|
|
50
|
+
effector: EffectorInterface; // Effector for state management
|
|
51
|
+
targetElement: HTMLSelectElement; // Original select element
|
|
52
|
+
accessorybox: AccessoryBox; // Accessory box for extra UI elements
|
|
53
53
|
searchController: SearchController; // Controller for search logic
|
|
54
|
-
selectObserver: SelectObserver;
|
|
55
|
-
datasetObserver: DatasetObserver;
|
|
54
|
+
selectObserver: SelectObserver; // Observer for selection changes
|
|
55
|
+
datasetObserver: DatasetObserver; // Observer for dataset updates
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
/**
|
|
59
59
|
* Interface defining actions and properties for the SelectBox component.
|
|
60
60
|
*/
|
|
61
61
|
export interface SelectBoxAction {
|
|
62
|
-
targetElement: HTMLSelectElement;
|
|
62
|
+
targetElement: HTMLSelectElement; // Target Select element
|
|
63
63
|
|
|
64
|
-
placeholder: string;
|
|
65
|
-
oldValue: unknown;
|
|
64
|
+
placeholder: string; // Placeholder text
|
|
65
|
+
oldValue: unknown; // Previous value before change
|
|
66
66
|
|
|
67
|
-
value: string | string[];
|
|
68
|
-
valueArray: string[];
|
|
69
|
-
valueString: string;
|
|
67
|
+
value: string | string[]; // Current selected value(s)
|
|
68
|
+
valueArray: string[]; // Selected values as an array
|
|
69
|
+
valueString: string; // Selected values as a single string
|
|
70
70
|
|
|
71
|
-
valueOptions: OptionModel[];
|
|
72
|
-
mask: string[];
|
|
73
|
-
valueText: string | string[];
|
|
71
|
+
valueOptions: OptionModel[]; // Selected option models
|
|
72
|
+
mask: string[]; // Masked values for filtering
|
|
73
|
+
valueText: string | string[]; // Display text for selected values
|
|
74
74
|
|
|
75
|
-
isOpen: boolean;
|
|
75
|
+
isOpen: boolean; // Indicates if the dropdown is open
|
|
76
76
|
|
|
77
|
-
disabled: boolean;
|
|
78
|
-
readonly: boolean;
|
|
79
|
-
visible: boolean;
|
|
77
|
+
disabled: boolean; // Indicates if the component is disabled
|
|
78
|
+
readonly: boolean; // Indicates if the component is read-only
|
|
79
|
+
visible: boolean; // Indicates if the component is visible
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
82
|
* Get parent of self
|
|
83
83
|
* @param evtToken - Optional event token for tracking.
|
|
84
84
|
*/
|
|
85
|
-
getParent(evtToken?: unknown): HTMLElement
|
|
85
|
+
getParent(evtToken?: unknown): HTMLElement;
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
88
|
* Get dataset from selected options
|
|
@@ -90,7 +90,11 @@ export interface SelectBoxAction {
|
|
|
90
90
|
* @param strDataset - Property to find
|
|
91
91
|
* @param isArray - Keep array or return once
|
|
92
92
|
*/
|
|
93
|
-
valueDataset(
|
|
93
|
+
valueDataset(
|
|
94
|
+
evtToken?: unknown,
|
|
95
|
+
strDataset?: string,
|
|
96
|
+
isArray?: boolean,
|
|
97
|
+
): any[] | string;
|
|
94
98
|
|
|
95
99
|
/**
|
|
96
100
|
* Select all available options.
|
|
@@ -113,7 +117,12 @@ export interface SelectBoxAction {
|
|
|
113
117
|
* @param trigger - Whether to trigger change events.
|
|
114
118
|
* @param force - Whether to force the update.
|
|
115
119
|
*/
|
|
116
|
-
setValue(
|
|
120
|
+
setValue(
|
|
121
|
+
evtToken?: unknown,
|
|
122
|
+
value?: unknown,
|
|
123
|
+
trigger?: boolean,
|
|
124
|
+
force?: boolean,
|
|
125
|
+
): void;
|
|
117
126
|
|
|
118
127
|
/**
|
|
119
128
|
* Load options for the SelectBox, typically from an AJAX source.
|
|
@@ -156,7 +165,11 @@ export interface SelectBoxAction {
|
|
|
156
165
|
* @param evtName - Name of the event.
|
|
157
166
|
* @param handle - Callback function for the event.
|
|
158
167
|
*/
|
|
159
|
-
on(
|
|
168
|
+
on(
|
|
169
|
+
evtToken: unknown,
|
|
170
|
+
evtName: string,
|
|
171
|
+
handle: (...args: any[]) => any,
|
|
172
|
+
): void;
|
|
160
173
|
|
|
161
174
|
/**
|
|
162
175
|
* Perform an AJAX request.
|
|
@@ -170,4 +183,4 @@ export interface SelectBoxAction {
|
|
|
170
183
|
* @param evtToken - Event token for tracking.
|
|
171
184
|
*/
|
|
172
185
|
loadAjax(evtToken: unknown, obj: unknown): void;
|
|
173
|
-
}
|
|
186
|
+
}
|