selective-ui 1.2.6 → 1.2.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selective-ui",
3
- "version": "1.2.6",
3
+ "version": "1.2.7",
4
4
  "description": "An overlay for the HTML select element.",
5
5
  "author": "Huỳnh Công Xuân Mai",
6
6
  "license": "MIT",
@@ -49,6 +49,7 @@
49
49
  "cssnano": "^7.1.2",
50
50
  "jest": "^30.2.0",
51
51
  "jest-environment-jsdom": "^30.2.0",
52
+ "mutation-observer": "^1.0.3",
52
53
  "postcss": "^8.5.6",
53
54
  "rimraf": "^6.1.2",
54
55
  "rollup": "^4.57.1",
@@ -70,5 +71,13 @@
70
71
  "browserslist": [
71
72
  ">0.25%",
72
73
  "not dead"
73
- ]
74
+ ],
75
+ "repository": {
76
+ "type": "git",
77
+ "url": "https://github.com/maihcx/selective-ui"
78
+ },
79
+ "bugs": {
80
+ "url": "https://github.com/maihcx/selective-ui/issues"
81
+ },
82
+ "homepage": "https://github.com/maihcx/selective-ui"
74
83
  }
@@ -8,6 +8,7 @@ import { IEventCallback } from "../types/utils/ievents.type";
8
8
  import { ImagePosition, LabelHalign, LabelValign } from "../types/views/view.option.type";
9
9
  import { Libs } from "../utils/libs";
10
10
  import { LifecycleState } from "../types/core/base/lifecycle.type";
11
+ import { Lifecycle } from "../core/base/lifecycle";
11
12
 
12
13
  /**
13
14
  * Mixed (heterogeneous) adapter for rendering and interacting with a list that contains
@@ -410,7 +410,8 @@ export class SearchController extends Lifecycle {
410
410
 
411
411
  let payload: Record<string, any>;
412
412
  if (typeof cfg.data === "function") {
413
- payload = cfg.data.bind(this.selectBox.Selective.find(this.selectBox.container.targetElement))(keyword, page);
413
+ const selectiveInstance = this.selectBox?.Selective?.find(this.selectBox?.container?.targetElement);
414
+ payload = cfg.data.call(selectiveInstance, keyword, page);
414
415
  if (payload && typeof payload.selectedValue === "undefined") payload.selectedValue = selectedValues;
415
416
  } else {
416
417
  payload = { search: keyword, page, selectedValue: selectedValues, ...(cfg.data ?? {}) };
package/src/ts/global.ts CHANGED
@@ -39,8 +39,8 @@ import type { SelectivePlugin } from "./types/plugins/plugin.type";
39
39
  import type { EffectorInterface } from "./types/services/effector.type";
40
40
  import { Libs } from "./utils/libs";
41
41
 
42
- declare const __LIB_VERSION__: string;
43
- declare const __LIB_NAME__: string;
42
+ const __LIB_VERSION__ = "LIB_VERSION";
43
+ const __LIB_NAME__ = "LIB_NAME";
44
44
 
45
45
  declare global {
46
46
  var GLOBAL_SEUI: SelectiveUIGlobal;
package/src/ts/index.ts CHANGED
@@ -38,8 +38,8 @@ import type { SelectivePlugin } from "./types/plugins/plugin.type";
38
38
  import type { EffectorInterface } from "./types/services/effector.type";
39
39
  import { Libs } from "./utils/libs";
40
40
 
41
- declare const __LIB_VERSION__: string;
42
- declare const __LIB_NAME__: string;
41
+ const __LIB_VERSION__ = "LIB_VERSION";
42
+ const __LIB_NAME__ = "LIB_NAME";
43
43
 
44
44
  const SECLASS = new Selective();
45
45
 
@@ -78,6 +78,7 @@ export class GroupModel extends Model<HTMLOptGroupElement, GroupViewTags, GroupV
78
78
  public constructor(options: SelectiveOptions, targetElement?: HTMLOptGroupElement) {
79
79
  super(options, targetElement ?? null, null);
80
80
  this.label = this.targetElement.label;
81
+ this.collapsed = Libs.string2Boolean(this.targetElement.dataset?.collapsed);
81
82
  }
82
83
 
83
84
  /**
@@ -95,8 +96,6 @@ export class GroupModel extends Model<HTMLOptGroupElement, GroupViewTags, GroupV
95
96
  * @override
96
97
  */
97
98
  public override init(): void {
98
- this.collapsed = Libs.string2Boolean(this.targetElement.dataset?.collapsed);
99
-
100
99
  super.init();
101
100
  this.mount();
102
101
  }
@@ -52,7 +52,7 @@ export class ElementAdditionObserver<T extends Element = Element> {
52
52
  *
53
53
  * @internal
54
54
  */
55
- private actions: Array<(el: T) => void> = [];
55
+ private actions: Set<(el: T) => void> = new Set();
56
56
 
57
57
  /**
58
58
  * Registers a callback invoked whenever a matching element is detected as added to the DOM.
@@ -64,7 +64,7 @@ export class ElementAdditionObserver<T extends Element = Element> {
64
64
  * @param action - Function executed with the newly detected element.
65
65
  */
66
66
  public onDetect(action: (el: T) => void): void {
67
- this.actions.push(action);
67
+ this.actions.add(action);
68
68
  }
69
69
 
70
70
  /**
@@ -74,7 +74,7 @@ export class ElementAdditionObserver<T extends Element = Element> {
74
74
  * to scan mutations but will not invoke any listeners until new callbacks are registered.
75
75
  */
76
76
  public clearDetect(): void {
77
- this.actions = [];
77
+ this.actions.clear();
78
78
  }
79
79
 
80
80
  /**
@@ -156,6 +156,8 @@ export class ElementAdditionObserver<T extends Element = Element> {
156
156
  * @internal
157
157
  */
158
158
  private handle(element: T): void {
159
- this.actions.forEach((action) => action(element));
159
+ for (const action of this.actions) {
160
+ action(element);
161
+ }
160
162
  }
161
- }
163
+ }
@@ -11,8 +11,12 @@ export type MixedItem = GroupModel | OptionModel;
11
11
  * Statistics about the visibility state of items in a list or container.
12
12
  */
13
13
  export type VisibilityStats = {
14
- visibleCount?: number; // Number of items currently visible
15
- totalCount?: number; // Total number of items in the collection
16
- hasVisible?: boolean; // Indicates if there is at least one visible item
17
- isEmpty?: boolean; // Indicates if the collection is empty
18
- };
14
+ /** Number of items currently visible after filters are applied. */
15
+ visibleCount?: number;
16
+ /** Total number of items tracked by the adapter. */
17
+ totalCount?: number;
18
+ /** Convenience flag indicating whether at least one item is visible. */
19
+ hasVisible?: boolean;
20
+ /** Convenience flag indicating whether the collection has no items. */
21
+ isEmpty?: boolean;
22
+ };
@@ -2,29 +2,46 @@
2
2
  * Represents the state of pagination for AJAX-based data loading.
3
3
  */
4
4
  export type PaginationState = {
5
- currentPage: number; // Current page number
6
- totalPages: number; // Total number of pages available
7
- hasMore: boolean; // Indicates if more pages are available
8
- isLoading: boolean; // Indicates if data is currently being loaded
9
- currentKeyword: string; // Current search keyword used for filtering
10
- isPaginationEnabled: boolean; // Indicates if pagination is enabled
5
+ /** Current 1-based page index. */
6
+ currentPage: number;
7
+ /** Total number of pages available for the current query. */
8
+ totalPages: number;
9
+ /** Whether another page can be requested. */
10
+ hasMore: boolean;
11
+ /** Whether a request is currently in flight. */
12
+ isLoading: boolean;
13
+ /** Keyword currently used to fetch/filter data. */
14
+ currentKeyword: string;
15
+ /** Whether pagination behavior is enabled for this datasource. */
16
+ isPaginationEnabled: boolean;
11
17
  };
12
18
 
13
19
  /**
14
20
  * Represents an individual option item returned from an AJAX request.
15
21
  */
16
22
  export type AjaxOptionItem = {
17
- type?: "option"; // Type identifier (optional, defaults to "option")
18
- value: string; // The value of the option
19
- text: string; // Display text for the option
20
- selected?: boolean; // Indicates if the option is selected
21
- data?: Record<string, any>; // Additional custom data associated with the option
22
- imgsrc?: string; // Optional image source for the option
23
- id?: string; // Optional unique identifier
24
- key?: string; // Optional key for internal mapping
25
- label?: string; // Optional label for accessibility or grouping
26
- name?: string; // Optional name attribute
27
- title?: string; // Optional title attribute
23
+ /** Type discriminator; defaults to `"option"` when omitted. */
24
+ type?: "option";
25
+ /** Serialized option value submitted to forms / APIs. */
26
+ value: string;
27
+ /** Display text shown in the UI. */
28
+ text: string;
29
+ /** Whether the option should start in selected state. */
30
+ selected?: boolean;
31
+ /** Arbitrary metadata preserved through normalization. */
32
+ data?: Record<string, any>;
33
+ /** Optional image source for custom rendering. */
34
+ imgsrc?: string;
35
+ /** Optional unique identifier from backend data. */
36
+ id?: string;
37
+ /** Optional stable key for mapping or diffing. */
38
+ key?: string;
39
+ /** Optional label override (e.g. accessibility/grouping use-cases). */
40
+ label?: string;
41
+ /** Optional name attribute for compatibility with legacy payloads. */
42
+ name?: string;
43
+ /** Optional title attribute for tooltip/semantics. */
44
+ title?: string;
28
45
  };
29
46
 
30
47
  /**
@@ -32,10 +49,14 @@ export type AjaxOptionItem = {
32
49
  * Contains a label and a list of options.
33
50
  */
34
51
  export type AjaxOptGroupItem = {
35
- type: "optgroup"; // Type identifier for option groups
36
- label: string; // Display label for the group
37
- data?: Record<string, any>; // Additional custom data for the group
38
- options?: Array<{ // List of options within the group
52
+ /** Type discriminator for grouped entries. */
53
+ type: "optgroup";
54
+ /** Human-readable label for the group. */
55
+ label: string;
56
+ /** Group-level metadata from the datasource. */
57
+ data?: Record<string, any>;
58
+ /** Option children when backend uses `options` as group payload key. */
59
+ options?: Array<{
39
60
  value: string;
40
61
  text: string;
41
62
  selected?: boolean;
@@ -47,11 +68,16 @@ export type AjaxOptGroupItem = {
47
68
  name?: string;
48
69
  title?: string;
49
70
  }>;
50
- items?: any[]; // Optional raw items for flexibility
51
- isGroup?: boolean; // Indicates if this is treated as a group
52
- group?: boolean; // Alternative flag for grouping
53
- name?: string; // Optional name attribute
54
- title?: string; // Optional title attribute
71
+ /** Raw child payload when backend uses non-standard item structures. */
72
+ items?: any[];
73
+ /** Compatibility flag used by some APIs to mark grouped entries. */
74
+ isGroup?: boolean;
75
+ /** Legacy alias of `isGroup`. */
76
+ group?: boolean;
77
+ /** Optional name attribute for compatibility with legacy payloads. */
78
+ name?: string;
79
+ /** Optional title attribute for tooltip/semantics. */
80
+ title?: string;
55
81
  };
56
82
 
57
83
  /**
@@ -68,20 +94,28 @@ export type NormalizedAjaxItem =
68
94
  * Represents the result of parsing an AJAX response.
69
95
  */
70
96
  export type ParseResponseResult = {
71
- items: NormalizedAjaxItem[]; // List of normalized items
72
- hasPagination: boolean; // Indicates if pagination is supported
73
- page: number; // Current page number
74
- totalPages: number; // Total number of pages
75
- hasMore: boolean; // Indicates if more data is available
97
+ /** Normalized items ready to be consumed by the adapter layer. */
98
+ items: NormalizedAjaxItem[];
99
+ /** Whether pagination metadata is present and should be honored. */
100
+ hasPagination: boolean;
101
+ /** Current 1-based page index returned from the server. */
102
+ page: number;
103
+ /** Total number of pages for the current query. */
104
+ totalPages: number;
105
+ /** Whether another page can be fetched. */
106
+ hasMore: boolean;
76
107
  };
77
108
 
78
109
  /**
79
110
  * Configuration for making AJAX requests to fetch options or groups.
80
111
  */
81
112
  export type AjaxConfig = {
82
- url: string; // Endpoint URL for the AJAX request
83
- method?: "GET" | "POST"; // HTTP method (default: GET)
84
- keepSelected?: boolean; // Whether to keep previously selected items after refresh
113
+ /** Endpoint URL used for remote search/pagination requests. */
114
+ url: string;
115
+ /** HTTP method used by requests (defaults to `GET`). */
116
+ method?: "GET" | "POST";
117
+ /** Preserve selected options when replacing remote results. */
118
+ keepSelected?: boolean;
85
119
 
86
120
  /**
87
121
  * Data payload for the request.
@@ -96,4 +130,4 @@ export type AjaxConfig = {
96
130
  * Function to generate request data based on selected values.
97
131
  */
98
132
  dataByValues?: (values: string[]) => Record<string, any>;
99
- };
133
+ };
@@ -2,8 +2,12 @@
2
2
  * Represents a snapshot of the current selection state in a select component.
3
3
  */
4
4
  export type SelectSnapshot = {
5
- length: number; // Total number of selected items
6
- values: string; // Comma-separated string of selected values
7
- texts: string; // Comma-separated string of selected display texts
8
- selected: string; // Raw representation of selected items (could be IDs or combined keys)
9
- };
5
+ /** Total number of selected options. */
6
+ length: number;
7
+ /** Comma-separated list of selected option values. */
8
+ values: string;
9
+ /** Comma-separated list of selected option display texts. */
10
+ texts: string;
11
+ /** Raw serialized representation of selected entries. */
12
+ selected: string;
13
+ };