selective-ui 1.0.2 → 1.0.3

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 (67) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +7 -2
  3. package/dist/selective-ui.css +567 -567
  4. package/dist/selective-ui.css.map +1 -1
  5. package/dist/selective-ui.esm.js +6046 -6046
  6. package/dist/selective-ui.esm.js.map +1 -1
  7. package/dist/selective-ui.esm.min.js +1 -1
  8. package/dist/selective-ui.esm.min.js.br +0 -0
  9. package/dist/selective-ui.min.js +1 -1
  10. package/dist/selective-ui.min.js.br +0 -0
  11. package/dist/selective-ui.umd.js +6046 -6046
  12. package/dist/selective-ui.umd.js.map +1 -1
  13. package/package.json +68 -68
  14. package/src/css/components/accessorybox.css +63 -63
  15. package/src/css/components/directive.css +19 -19
  16. package/src/css/components/empty-state.css +25 -25
  17. package/src/css/components/loading-state.css +25 -25
  18. package/src/css/components/optgroup.css +61 -61
  19. package/src/css/components/option-handle.css +33 -33
  20. package/src/css/components/option.css +129 -129
  21. package/src/css/components/placeholder.css +14 -14
  22. package/src/css/components/popup.css +38 -38
  23. package/src/css/components/searchbox.css +28 -28
  24. package/src/css/components/selectbox.css +53 -53
  25. package/src/css/index.css +74 -74
  26. package/src/js/adapter/mixed-adapter.js +434 -434
  27. package/src/js/components/accessorybox.js +124 -124
  28. package/src/js/components/directive.js +37 -37
  29. package/src/js/components/empty-state.js +67 -67
  30. package/src/js/components/loading-state.js +59 -59
  31. package/src/js/components/option-handle.js +113 -113
  32. package/src/js/components/placeholder.js +56 -56
  33. package/src/js/components/popup.js +470 -470
  34. package/src/js/components/searchbox.js +167 -167
  35. package/src/js/components/selectbox.js +692 -692
  36. package/src/js/core/base/adapter.js +162 -162
  37. package/src/js/core/base/model.js +59 -59
  38. package/src/js/core/base/recyclerview.js +82 -82
  39. package/src/js/core/base/view.js +62 -62
  40. package/src/js/core/model-manager.js +286 -286
  41. package/src/js/core/search-controller.js +521 -521
  42. package/src/js/index.js +136 -136
  43. package/src/js/models/group-model.js +142 -142
  44. package/src/js/models/option-model.js +236 -236
  45. package/src/js/services/dataset-observer.js +73 -73
  46. package/src/js/services/ea-observer.js +87 -87
  47. package/src/js/services/effector.js +403 -403
  48. package/src/js/services/refresher.js +39 -39
  49. package/src/js/services/resize-observer.js +151 -151
  50. package/src/js/services/select-observer.js +60 -60
  51. package/src/js/types/adapter.type.js +32 -32
  52. package/src/js/types/effector.type.js +23 -23
  53. package/src/js/types/ievents.type.js +10 -10
  54. package/src/js/types/libs.type.js +27 -27
  55. package/src/js/types/model.type.js +11 -11
  56. package/src/js/types/recyclerview.type.js +11 -11
  57. package/src/js/types/resize-observer.type.js +18 -18
  58. package/src/js/types/view.group.type.js +12 -12
  59. package/src/js/types/view.option.type.js +14 -14
  60. package/src/js/types/view.type.js +10 -10
  61. package/src/js/utils/guard.js +46 -46
  62. package/src/js/utils/ievents.js +83 -83
  63. package/src/js/utils/istorage.js +60 -60
  64. package/src/js/utils/libs.js +618 -618
  65. package/src/js/utils/selective.js +385 -385
  66. package/src/js/views/group-view.js +102 -102
  67. package/src/js/views/option-view.js +152 -152
@@ -1,168 +1,168 @@
1
- import {Libs} from "../utils/libs.js";
2
-
3
- /**
4
- * @class
5
- */
6
- export class SearchBox {
7
- /**
8
- * Creates a searchable input box component with optional configuration
9
- * and initializes it if options are provided.
10
- *
11
- * @param {object|null} [options=null] - Configuration (e.g., placeholder, accessibility IDs).
12
- */
13
- constructor(options = null) {
14
- this.options = options;
15
- options && this.init(options);
16
- }
17
-
18
- /**
19
- * @type {MountViewResult<any>}
20
- */
21
- nodeMounted = null;
22
-
23
- /**
24
- * @type {HTMLDivElement}
25
- */
26
- node = null;
27
-
28
- /**
29
- * @type {HTMLInputElement}
30
- */
31
- SearchInput = null;
32
-
33
- /**
34
- * @type {Function|null}
35
- */
36
- onSearch = null;
37
-
38
- options = null;
39
-
40
- onNavigate = null;
41
- onEnter = null;
42
- onEsc = null;
43
-
44
- /**
45
- * Initializes the search box DOM, sets ARIA attributes, and wires keyboard/mouse/input events.
46
- * Supports navigation (ArrowUp/ArrowDown/Tab), Enter, and Escape through callbacks.
47
- *
48
- * @param {object} options - Configuration including placeholder and SEID_LIST for aria-controls.
49
- */
50
- init(options) {
51
- this.nodeMounted = Libs.mountNode({
52
- SearchBox: {
53
- tag: {node: "div", classList: ["selective-ui-searchbox", "hide"]},
54
- child: {
55
- SearchInput: {
56
- tag: {
57
- id: Libs.randomString(),
58
- node: "input",
59
- type: "search",
60
- classList: ["selective-ui-searchbox-input"],
61
- placeholder: options.placeholder,
62
- role: "searchbox",
63
- ariaControls: options.SEID_LIST,
64
- ariaAutocomplete: "list"
65
- }
66
- }
67
- }
68
- }
69
- });
70
- this.node = /** @type {HTMLDivElement} */ (this.nodeMounted.view);
71
- this.SearchInput = this.nodeMounted.tags.SearchInput;
72
-
73
- let isControlKey = false;
74
-
75
- /** @type {HTMLInputElement} */
76
- const SearchInput = this.nodeMounted.tags.SearchInput;
77
-
78
- SearchInput.addEventListener("mousedown", (e) => {
79
- e.stopPropagation();
80
- });
81
- SearchInput.addEventListener("mouseup", (e) => {
82
- e.stopPropagation();
83
- });
84
- SearchInput.addEventListener("keydown", (e) => {
85
- isControlKey = false;
86
- if (e.key === "ArrowDown" || e.key === "Tab") {
87
- e.preventDefault();
88
- e.stopPropagation();
89
- isControlKey = true;
90
- this.onNavigate?.(1);
91
- }
92
- else if (e.key === "ArrowUp") {
93
- e.preventDefault();
94
- e.stopPropagation();
95
- isControlKey = true;
96
- this.onNavigate?.(-1);
97
- }
98
- else if (e.key === "Enter") {
99
- e.preventDefault();
100
- e.stopPropagation();
101
- isControlKey = true;
102
- this.onEnter?.();
103
- }
104
- else if (e.key === "Escape") {
105
- e.preventDefault();
106
- e.stopPropagation();
107
- isControlKey = true;
108
- this.onEsc?.();
109
- }
110
- });
111
- SearchInput.addEventListener("input", (e) => {
112
- if (isControlKey) {
113
- return;
114
- }
115
-
116
- this.onSearch && this.onSearch(this.nodeMounted.tags.SearchInput.value, true);
117
- });
118
- }
119
-
120
- /**
121
- * Shows the search box, toggles read-only based on `options.searchable`,
122
- * and focuses the input when searchable.
123
- */
124
- show() {
125
- this.node.classList.remove("hide");
126
- this.SearchInput.readOnly = !this.options.searchable;
127
- if (this.options.searchable) {
128
- requestAnimationFrame(() => {
129
- this.SearchInput.focus();
130
- });
131
- }
132
- }
133
-
134
- /**
135
- * Hides the search box by adding the "hide" class.
136
- */
137
- hide() {
138
- this.node.classList.add("hide");
139
- }
140
-
141
- /**
142
- * Clears the current search value and optionally triggers the onSearch callback.
143
- *
144
- * @param {boolean} [isTrigger=true] - Whether to invoke onSearch with an empty string.
145
- */
146
- clear(isTrigger = true) {
147
- this.nodeMounted.tags.SearchInput.value = "";
148
- this.onSearch && this.onSearch("", isTrigger);
149
- }
150
-
151
- /**
152
- * Updates the input's placeholder text, stripping any HTML for safety.
153
- *
154
- * @param {string} value - The new placeholder text.
155
- */
156
- setPlaceHolder(value) {
157
- this.SearchInput.placeholder = Libs.stripHtml(value);
158
- }
159
-
160
- /**
161
- * Sets the active descendant for ARIA to indicate which option is currently highlighted.
162
- *
163
- * @param {string} id - The DOM id of the active option element.
164
- */
165
- setActiveDescendant(id) {
166
- this.SearchInput.setAttribute("aria-activedescendant", id);
167
- }
1
+ import {Libs} from "../utils/libs.js";
2
+
3
+ /**
4
+ * @class
5
+ */
6
+ export class SearchBox {
7
+ /**
8
+ * Creates a searchable input box component with optional configuration
9
+ * and initializes it if options are provided.
10
+ *
11
+ * @param {object|null} [options=null] - Configuration (e.g., placeholder, accessibility IDs).
12
+ */
13
+ constructor(options = null) {
14
+ this.options = options;
15
+ options && this.init(options);
16
+ }
17
+
18
+ /**
19
+ * @type {MountViewResult<any>}
20
+ */
21
+ nodeMounted = null;
22
+
23
+ /**
24
+ * @type {HTMLDivElement}
25
+ */
26
+ node = null;
27
+
28
+ /**
29
+ * @type {HTMLInputElement}
30
+ */
31
+ SearchInput = null;
32
+
33
+ /**
34
+ * @type {Function|null}
35
+ */
36
+ onSearch = null;
37
+
38
+ options = null;
39
+
40
+ onNavigate = null;
41
+ onEnter = null;
42
+ onEsc = null;
43
+
44
+ /**
45
+ * Initializes the search box DOM, sets ARIA attributes, and wires keyboard/mouse/input events.
46
+ * Supports navigation (ArrowUp/ArrowDown/Tab), Enter, and Escape through callbacks.
47
+ *
48
+ * @param {object} options - Configuration including placeholder and SEID_LIST for aria-controls.
49
+ */
50
+ init(options) {
51
+ this.nodeMounted = Libs.mountNode({
52
+ SearchBox: {
53
+ tag: {node: "div", classList: ["selective-ui-searchbox", "hide"]},
54
+ child: {
55
+ SearchInput: {
56
+ tag: {
57
+ id: Libs.randomString(),
58
+ node: "input",
59
+ type: "search",
60
+ classList: ["selective-ui-searchbox-input"],
61
+ placeholder: options.placeholder,
62
+ role: "searchbox",
63
+ ariaControls: options.SEID_LIST,
64
+ ariaAutocomplete: "list"
65
+ }
66
+ }
67
+ }
68
+ }
69
+ });
70
+ this.node = /** @type {HTMLDivElement} */ (this.nodeMounted.view);
71
+ this.SearchInput = this.nodeMounted.tags.SearchInput;
72
+
73
+ let isControlKey = false;
74
+
75
+ /** @type {HTMLInputElement} */
76
+ const SearchInput = this.nodeMounted.tags.SearchInput;
77
+
78
+ SearchInput.addEventListener("mousedown", (e) => {
79
+ e.stopPropagation();
80
+ });
81
+ SearchInput.addEventListener("mouseup", (e) => {
82
+ e.stopPropagation();
83
+ });
84
+ SearchInput.addEventListener("keydown", (e) => {
85
+ isControlKey = false;
86
+ if (e.key === "ArrowDown" || e.key === "Tab") {
87
+ e.preventDefault();
88
+ e.stopPropagation();
89
+ isControlKey = true;
90
+ this.onNavigate?.(1);
91
+ }
92
+ else if (e.key === "ArrowUp") {
93
+ e.preventDefault();
94
+ e.stopPropagation();
95
+ isControlKey = true;
96
+ this.onNavigate?.(-1);
97
+ }
98
+ else if (e.key === "Enter") {
99
+ e.preventDefault();
100
+ e.stopPropagation();
101
+ isControlKey = true;
102
+ this.onEnter?.();
103
+ }
104
+ else if (e.key === "Escape") {
105
+ e.preventDefault();
106
+ e.stopPropagation();
107
+ isControlKey = true;
108
+ this.onEsc?.();
109
+ }
110
+ });
111
+ SearchInput.addEventListener("input", (e) => {
112
+ if (isControlKey) {
113
+ return;
114
+ }
115
+
116
+ this.onSearch && this.onSearch(this.nodeMounted.tags.SearchInput.value, true);
117
+ });
118
+ }
119
+
120
+ /**
121
+ * Shows the search box, toggles read-only based on `options.searchable`,
122
+ * and focuses the input when searchable.
123
+ */
124
+ show() {
125
+ this.node.classList.remove("hide");
126
+ this.SearchInput.readOnly = !this.options.searchable;
127
+ if (this.options.searchable) {
128
+ requestAnimationFrame(() => {
129
+ this.SearchInput.focus();
130
+ });
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Hides the search box by adding the "hide" class.
136
+ */
137
+ hide() {
138
+ this.node.classList.add("hide");
139
+ }
140
+
141
+ /**
142
+ * Clears the current search value and optionally triggers the onSearch callback.
143
+ *
144
+ * @param {boolean} [isTrigger=true] - Whether to invoke onSearch with an empty string.
145
+ */
146
+ clear(isTrigger = true) {
147
+ this.nodeMounted.tags.SearchInput.value = "";
148
+ this.onSearch && this.onSearch("", isTrigger);
149
+ }
150
+
151
+ /**
152
+ * Updates the input's placeholder text, stripping any HTML for safety.
153
+ *
154
+ * @param {string} value - The new placeholder text.
155
+ */
156
+ setPlaceHolder(value) {
157
+ this.SearchInput.placeholder = Libs.stripHtml(value);
158
+ }
159
+
160
+ /**
161
+ * Sets the active descendant for ARIA to indicate which option is currently highlighted.
162
+ *
163
+ * @param {string} id - The DOM id of the active option element.
164
+ */
165
+ setActiveDescendant(id) {
166
+ this.SearchInput.setAttribute("aria-activedescendant", id);
167
+ }
168
168
  }